hr = pTransFact->QueryService(SID_SDXSurfaceFactory,
IID_IDXSurfaceFactory, (void **)&pSurfFact);
if (SUCCEEDED(hr)) {
CComBSTR bstrFile(szFile);
CComPtr pDXSurf;
// Load DX surface.
hr = pSurfFact->LoadImage(bstrFile, NULL, NULL,
NULL, IID_IDXSurface, (void**)&pDXSurf);
if (SUCCEEDED(hr)) {
// Get IDXDCLock object
hr = pDXSurf->LockSurfaceDC(NULL, INFINITE, DXLOCKF_READ, &m_pDCLock);
}
}
return hr;
}
Достоинства: Прост в использовании. Поддерживает загрузку из IStream.
Недостатки: Медленный и ресурсоемкий. Это связянно с тем, что сначала для картинки создается обертка в виде IDirectDrawSurface, а затем еще одна для IDXSurface, которые нам совершенно не нужны.
Способ 5 (Фильтры импорта)
Многие программы (например PaintBrush или WinWord) при инсталляции кладут в каталог %ProgramFiles%\Common Files\Microsoft Shared\Grphfltнекоторое количество файлов, предназначенных для чтения файлов картинок. Способ не документированный и сильно устаревший. Полный список установленных в системе фильтров находится в реестре по адресу SOFTWARE\\Microsoft\\Shared Tools\\Graphics Filters\\Import
Я не буду рассматривать этот способ подробно, поскольку он сильно устарел и очень неудобен. Тем не менее, в приложении DrawImg этот способ реализован наравне с другими.
Способ 6 (Снова Фильтры импорта)
Майкрософт Офис, начиная с версии 8.0 (97) использует новый API с теми же фильтрами.
HRESULT Load(LPCTSTR szFile) {
HMODULE hModule = g_pMapExtToFilter->LoadFilter(szFile);
if (NULL == hModule) return E_FAIL;
struct NameStruct {
DWORD dwHead[2];
char szName[MAX_PATH];
DWORD dwTail[2];
};
typedef DWORD (__stdcall *GetFilterInfo_t)
(DWORD dwVersion, DWORD dwReserved, HGLOBAL *phFilterData, DWORD dwReserved2);
typedef DWORD (__stdcall *SetFilterPref_t)
(HGLOBAL hFilterData, LPCSTR szOption, LPCSTR szValue, DWORD dwReserved2, DWORD dwReserved1);
typedef DWORD (__stdcall *ImportGr_t)
(DWORD dwReserved, NameStruct *pFile, ImgInfo *pInfo, HGLOBAL hFilterData);
GetFilterInfo_t pGetFilterInfo = (GetFilterInfo_t)::GetProcAddress(hModule, "GetFilterInfo");
SetFilterPref_t pSetFilterPref = (SetFilterPref_t)::GetProcAddress(hModule, "SetFilterPref");
ImportGr_t pImportGr = (ImportGr_t)::GetProcAddress(hModule, "ImportGr");
if (NULL == pImportGr) pImportGr = (ImportGr_t)::GetProcAddress(hModule, "ImportGR");
if (pImportGr) {
NameStruct name = {0};
HGLOBAL hFilterData = NULL;
if (pGetFilterInfo) {
DWORD dwVer = pGetFilterInfo(2, 0, &hFilterData, 0x00170000);
ATLASSERT(2 == dwVer);
if (2 != dwVer) {
::FreeLibrary(hModule);
return E_UNEXPECTED;
}
}
// PB 01/26/2001 Turn off dialogs
if (pSetFilterPref) {
pSetFilterPref(hFilterData, "ShowProgressDialog", "No", 2, 1);
pSetFilterPref(hFilterData, "ShowOptionsDialog", "No", 2, 1);
}
USES_CONVERSION;
::lstrcpynA(name.szName, T2CA(szFile), MAX_PATH);
DWORD dwRet = pImportGr(0, &name, &m_Image, hFilterData);
if (hFilterData) ::GlobalFree(hFilterData);
if (0 != dwRet || NULL == m_Image.hObj) {
::FreeLibrary(hModule);
return E_FAIL;
}
if (OBJ_METAFILE != ::GetObjectType(m_Image.hObj)) {
HGLOBAL hObj = (HGLOBAL)m_Image.hObj;
LPBYTE pObj = (LPBYTE)::GlobalLock(hObj);
m_Image.hObj = ::SetMetaFileBitsEx(::GlobalSize(hObj), pObj);
::GlobalUnlock(hObj);
::GlobalFree(hObj);
}
if (NULL == m_Image.hObj) {
::FreeLibrary(hModule);
return E_FAIL;
}
return S_OK;
}
::FreeLibrary(hModule);
return E_UNEXPECTED;
}
HRESULT DrawImg(HDC hdc, const RECT& rcBounds) {
if (m_Image.hObj) {
::SetMapMode(hdc, MM_ANISOTROPIC);
::SetViewportExtEx(hdc,
rcBounds.right - rcBounds.left, rcBounds.bottom - rcBounds.top,
NULL);
::PlayMetaFile(hdc, m_Image.hObj);
return S_OK;
}
return E_UNEXPECTED;
}
Достоинства: понимает очень редкие форматы. Например wpg или cdr
Недостатки: Нет никакой гарантии, что на компьютере пользователя будет установлен нужный фильтр.
Способ 7 (Direct3D)
Direct3Dверсии 8.0 и выше умеет загружать картинки в формате BMP, JPEG, PNG:
#include
HRESULT hr = ::D3DXCreateTextureFromFile(m_pD3DDevice, szFile, &ppTexture);
Достоинства: если вы разрабатываете 3D-приложение, то это наиболее удобный способ создания текстур (D3DXCreateTextureFromFile автоматически создает необходимое количество MipMap уровней).
Недостатки: если вы не разрабатываете 3D-приложение, то этот способ крайне неудобен, так как предназначен для работы с 3D объектами. На входе нужен IDirect3DDevice8объект, а на выходе получаем IDirect3DTexture8, который очень не просто вывести в hdc.
Не реализован в демонстрационном приложении.
Это все на сегодня. Пока!
Алекс Jenter jenter@rsdn.ru Duisburg, 2001. Публикуемые в рассылке материалы принадлежат сайту RSDN.
Программирование на Visual C++
Выпуск №60 от 20 января 2002 г.
Здравствуйте, дорогие подписчики!
Рад снова вас приветствовать на страницах рассылки.
Читать дальше