// WndImgCtx.cpp : implementation file
//
#include "stdafx.h"
#include "ImgViewer.h"
#include "WndImgCtx.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
HBITMAP GetBitmapFromFile(LPCTSTR pszFilename)
{
HBITMAP hRet = NULL;
CoInitialize( NULL );
CWndImgCtx wndImg;
RECT rectWnd;
rectWnd.left = rectWnd.top = 0;
rectWnd.right = rectWnd.bottom = 100;
wndImg.Create(NULL, "WndImgCtx", WS_OVERLAPPED, rectWnd, AfxGetApp()->m_pMainWnd, 1);
if (IsWindow(wndImg.m_hWnd))
{
HRESULT hr = wndImg.StartDecode(pszFilename);
if (SUCCEEDED(hr))
{
// make ure the message pump can get a message every 50 ms
UINT iTimer = wndImg.SetTimer(1, 50, NULL);
// use message pump to drive decode process
BOOL bGet = FALSE;
MSG msg;
while (!bGet)
{
while (::PeekMessage(&msg, (HWND) NULL, 0, 0, PM_REMOVE))
{
if ( msg.message==WM_QUIT )
{
::PostQuitMessage(-1);
bGet = TRUE;
break;
}
else if (wndImg.CheckState())
{
bGet = TRUE;
break;
}
else if (!AfxGetApp()->PreTranslateMessage(&msg))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
}
if (bGet)
hRet = wndImg.GetBitmap();
wndImg.KillTimer(iTimer);
}
}
wndImg.DestroyWindow();
CoUninitialize();
return hRet;
}
/////////////////////////////////////////////////////////////////////////////
// CWndImgCtx
CWndImgCtx::CWndImgCtx()
{
m_pImgCtx = NULL;
m_hPal = NULL;
}
CWndImgCtx::~CWndImgCtx()
{
}
BEGIN_MESSAGE_MAP(CWndImgCtx, CWnd)
//{{AFX_MSG_MAP(CWndImgCtx)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWndImgCtx message handlers
void CWndImgCtx::OnDestroy()
{
CWnd::OnDestroy();
// TODO: Add your message handler code here
if ( m_pImgCtx )
m_pImgCtx->Release();
}
const char c_szFilePro[] = "file://";
void CreateUrlFromPath(LPCTSTR pszPath, WCHAR* pszUrl, int cchWideChar)
{
CHAR szURL[MAX_PATH + sizeof(c_szFilePro)];
lstrcpy(szURL, c_szFilePro);
lstrcat(szURL, pszPath);
for (char* p = szURL; *p; p++)
if (*p == '\\') *p = '/';
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szURL, -1, pszUrl, cchWideChar);
}
HRESULT CWndImgCtx::StartDecode(LPCTSTR pszFilename)
{
if (!pszFilename)
return E_INVALIDARG;
WCHAR szURL[MAX_PATH + sizeof(c_szFilePro)];
CreateUrlFromPath(pszFilename, szURL, sizeof(szURL)/sizeof(WCHAR));
HRESULT hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER, IID_IImgCtx, (LPVOID*)&m_pImgCtx);
if (SUCCEEDED(hr))
hr = m_pImgCtx->Load(szURL, 0);
return hr;
}
BOOL CWndImgCtx::CheckState()
{
BOOL bRet = FALSE;
if ( m_pImgCtx )
{
HRESULT hr;
SIZE sizeImage;
ULONG ulState;
hr = m_pImgCtx->GetStateInfo(&ulState, &sizeImage, FALSE);
if (SUCCEEDED(hr))
{
if ((ulState & IMGLOAD_COMPLETE) || (ulState & IMGLOAD_STOPPED) || (ulState & IMGLOAD_ERROR))
{
m_pImgCtx->GetPalette(&m_hPal);
m_sizeImage = sizeImage;
bRet = TRUE;
};
}
}
return bRet;
}
void CWndImgCtx::OnDraw(HDC hdcDraw)
{
SetMapMode(hdcDraw, MM_TEXT);
if (m_hPal)
{
SelectPalette(hdcDraw, m_hPal, TRUE);
RealizePalette(hdcDraw);
}
if (m_pImgCtx)
m_pImgCtx->Draw(hdcDraw, &CRect(0, 0, m_sizeImage.cx, m_sizeImage.cy));
}
HBITMAP CWndImgCtx::GetBitmap()
{
HBITMAP hRet = NULL;
if (m_pImgCtx == NULL)
return hRet;
HDC hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
if (hScrDC)
{
HDC hMemDC = CreateCompatibleDC(hScrDC);
if (hMemDC)
{
// create a bitmap compatible with the screen DC
HBITMAP hBitmap = CreateCompatibleBitmap(hScrDC, GetImageWidth(), GetImageHeight());
if (hBitmap)
{
// select new bitmap into memory DC
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
//CDC::FillSolidRect();
{
RECT rect;
rect.left = rect.top = 0;
rect.right = GetImageWidth();
rect.bottom = GetImageHeight();
::SetBkColor(hMemDC, GetSysColor(COLOR_WINDOW));
::ExtTextOut(hMemDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
}
OnDraw(hMemDC);
// select the old bitmap back into memory DC and get handle to bitmap
hRet = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
SetBitmapDimensionEx(hRet, GetImageWidth(), GetImageHeight(), NULL);
}
DeleteDC(hMemDC);
}
}
DeleteDC(hScrDC);
return hRet;
}