|
|
//----------------------------------------------------------------------------
// Preview.cpp - image preview app for theme authoring
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "resource.h"
#include "shlwapip.h"
#include "themeldr.h"
//----------------------------------------------------------------------------
#define MAX_LOADSTRING 100
//----------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); HRESULT InitDib(HINSTANCE hInstance, LPCWSTR pszFileName); void SetBackground(HWND hWnd, HINSTANCE hinst, int id, int iMenuId); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); void OnFileOpen(HINSTANCE hInst, HWND hWnd); void SetZoom(HWND hWnd, HINSTANCE hInstance, int iZoomPercent, int iMenuId); //----------------------------------------------------------------------------
HINSTANCE hInst; HBITMAP hCenterDIB = NULL; HBITMAP hbrBackground = NULL; int iDibWidth; int iDibHeight; int iCurrentBgMenu = 0; int iCurrentZoomMenu = 0; int iZoomFactor = 100; BOOL fAlpha; //----------------------------------------------------------------------------
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int nCmdShow) { MSG msg; HACCEL hAccelTable; TCHAR szWindowClass[MAX_LOADSTRING]; TCHAR szTitle[MAX_LOADSTRING];
//---- initialize globals from themeldr.lib ----
ThemeLibStartUp(FALSE); //---- Initialize global strings ----
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_PREVIEW, szWindowClass, MAX_LOADSTRING);
//---- register window class ----
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_PREVIEW); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = NULL; wcex.lpszMenuName = MAKEINTRESOURCE(IDC_PREVIEW); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
RegisterClassEx(&wcex); if (*lpCmdLine) InitDib(hInstance, lpCmdLine);
//---- create the main window ----
HWND hWnd; hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) return 1;
SetBackground(hWnd, hInstance, IDB_PINKGRAY, ID_BACKGROUND_GRAYPINK); SetZoom(hWnd, hInstance, 100, ID_ZOOM_100);
ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_PREVIEW);
//---- initialize us as a drag target ----
DragAcceptFiles(hWnd, TRUE);
//---- main message loop ----
while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
return (int)msg.wParam; } //----------------------------------------------------------------------------
void SetBackground(HWND hWnd, HINSTANCE hInstance, int id, int iMenuId) { if (hbrBackground) DeleteObject(hbrBackground); hbrBackground = LoadBitmap(hInstance, MAKEINTRESOURCE(id));
InvalidateRect(hWnd, NULL, TRUE);
//---- update menu items ----
HMENU hMenu = GetMenu(hWnd); hMenu = GetSubMenu(hMenu, 1);
if (iCurrentBgMenu) CheckMenuItem(hMenu, iCurrentBgMenu, MF_BYCOMMAND | MF_UNCHECKED); CheckMenuItem(hMenu, iMenuId, MF_BYCOMMAND | MF_CHECKED);
iCurrentBgMenu = iMenuId; } //----------------------------------------------------------------------------
HRESULT InitDib(HINSTANCE hInstance, LPCWSTR pszFileName) { if (hCenterDIB) { DeleteObject(hCenterDIB); hCenterDIB = NULL; }
int iRetVal = 0; fAlpha = FALSE; WCHAR *pszOutputName = L"$temp$.bmp"; HRESULT hr = S_OK; HDC hdc = NULL; DWORD *pBits = NULL;
//---- ensure file exists ----
if (! FileExists(pszFileName)) { hr = MakeError32(STG_E_FILENOTFOUND); goto exit; }
//---- convert file, if needed ----
WCHAR szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szBaseName[_MAX_FNAME], szExt[_MAX_EXT]; _wsplitpath(pszFileName, szDrive, szDir, szBaseName, szExt); if (lstrcmpi(szExt, L".bmp") != 0) // not a .bmp file
{ //---- protect ourselves from crashes ----
try { hr = SHConvertGraphicsFile(pszFileName, pszOutputName, SHCGF_REPLACEFILE); } catch (...) { hr = MakeError32(E_FAIL); }
if ((SUCCEEDED(hr)) && (! FileExists(pszOutputName))) hr = MakeError32(E_FAIL);
if (FAILED(hr)) goto exit;
pszFileName = pszOutputName; }
//---- load the specified center bitmap as a DIB ----
hCenterDIB = (HBITMAP) LoadImage(hInstance, pszFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE); if (! hCenterDIB) { hr = MakeErrorLast(); goto exit; }
BITMAP bminfo; GetObject(hCenterDIB, sizeof(bminfo), &bminfo);
iDibWidth = bminfo.bmWidth; iDibHeight = bminfo.bmHeight;
if (bminfo.bmBitsPixel < 32) iRetVal = 1; else { pBits = new DWORD[(iDibWidth+20)*iDibHeight]; if (! pBits) { hr = MakeError32(E_OUTOFMEMORY); goto exit; }
BITMAPINFOHEADER BitMapHdr = {sizeof(BITMAPINFOHEADER), iDibWidth, iDibHeight, 1, 32, BI_RGB}; hdc = GetWindowDC(NULL); if (! hdc) { hr = MakeErrorLast(); goto exit; }
iRetVal = GetDIBits(hdc, hCenterDIB, 0, iDibHeight, pBits, (BITMAPINFO *)&BitMapHdr, DIB_RGB_COLORS); if (! iRetVal) { hr = MakeErrorLast(); goto exit; }
DWORD *pdw = pBits;
//---- pre-multiply bits - required by AlphaBlend() API ----
for (int r=0; r < iDibHeight; r++) { for (int c=0; c < iDibWidth; c++) { COLORREF cr = *pdw; int iAlpha = ALPHACHANNEL(cr); if (iAlpha) { int iRed = (RED(cr)*iAlpha)/255; int iGreen = (GREEN(cr)*iAlpha)/255; int iBlue = (BLUE(cr)*iAlpha)/255;
*pdw++ = (RGB(iRed, iGreen, iBlue) | (iAlpha << 24)); fAlpha = TRUE; } else *pdw++ = 0; } }
if (fAlpha) { iRetVal = SetDIBits(NULL, hCenterDIB, 0, iDibHeight, pBits, (BITMAPINFO *)&BitMapHdr, DIB_RGB_COLORS); if (! iRetVal) { hr = MakeErrorLast(); goto exit; } } else MessageBox(NULL, L"Alpha Channel of bitmap is all zero's", L"Warning", MB_OK); }
exit: if (hdc) ReleaseDC(NULL, hdc); if (pBits) delete [] pBits;
if (FAILED(hr)) MessageBox(NULL, L"Error loading bitmap", L"Error", MB_OK);
return hr; } //----------------------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc;
switch (message) { case WM_DROPFILES: { HDROP hDrop = (HDROP)wParam; WCHAR szFileName[_MAX_PATH+1]; int iGot = DragQueryFile(hDrop, 0, szFileName, ARRAYSIZE(szFileName)); DragFinish(hDrop);
if (iGot) // got a valid filename
{ HRESULT hr = InitDib(hInst, szFileName); if (SUCCEEDED(hr)) InvalidateRect(hWnd, NULL, TRUE); } } break;
case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections:
switch (wmId) { case ID_FILE_OPEN: OnFileOpen(hInst, hWnd); break;
case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About); break;
case IDM_EXIT: DestroyWindow(hWnd); break;
case ID_BACKGROUND_GRAYPINK: SetBackground(hWnd, hInst, IDB_PINKGRAY, wmId); break;
case ID_BACKGROUND_BLUEGRAY: SetBackground(hWnd, hInst, IDB_BLUEGRAY, wmId); break;
case ID_BACKGROUND_WHITE: SetBackground(hWnd, hInst, IDB_WHITE, wmId); break; case ID_BACKGROUND_GRAY: SetBackground(hWnd, hInst, IDB_GRAY, wmId); break; case ID_ZOOM_50: SetZoom(hWnd, hInst, 50, wmId); break; case ID_ZOOM_100: SetZoom(hWnd, hInst, 100, wmId); break; case ID_ZOOM_200: SetZoom(hWnd, hInst, 200, wmId); break; case ID_ZOOM_400: SetZoom(hWnd, hInst, 400, wmId); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break;
case WM_ERASEBKGND: HBRUSH hbr; hbr = CreatePatternBrush(hbrBackground); hdc = (HDC)wParam; if ((hbr) && (hdc)) { RECT rect; GetClientRect(hWnd, &rect); FillRect(hdc, &rect, hbr); DeleteObject(hbr); } return 1;
case WM_PAINT: hdc = BeginPaint(hWnd, &ps);
XFORM xForm;
xForm.eM11 = (FLOAT)(iZoomFactor/100.); xForm.eM12 = (FLOAT) 0.0; xForm.eM21 = (FLOAT) 0.0; xForm.eM22 = (FLOAT)(iZoomFactor/100.); xForm.eDx = (FLOAT) 0.0; xForm.eDy = (FLOAT) 0.0;
SetGraphicsMode(hdc, GM_ADVANCED); SetWorldTransform(hdc, &xForm);
//---- get scaled rect ----
RECT rc; GetClientRect(hWnd, &rc); rc.right = (rc.right*100)/iZoomFactor; rc.bottom = (rc.bottom*100)/iZoomFactor;
//---- paint the center bitmap ----
HDC dc2; dc2 = CreateCompatibleDC(hdc); if ((dc2) && (hCenterDIB)) { HBITMAP hOldBitmap2; hOldBitmap2 = (HBITMAP) SelectObject(dc2, hCenterDIB);
int x = ((rc.right - rc.left) - iDibWidth)/2; int y = ((rc.bottom - rc.top) - iDibHeight)/2; BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
if (fAlpha) { AlphaBlend(hdc, x, y, iDibWidth, iDibHeight, dc2, 0, 0, iDibWidth, iDibHeight, bf); } else { BitBlt(hdc, x, y, iDibWidth, iDibHeight, dc2, 0, 0, SRCCOPY); }
SelectObject(dc2, hOldBitmap2); DeleteDC(dc2); }
EndPaint(hWnd, &ps); break;
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } //----------------------------------------------------------------------------
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE;
case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } //----------------------------------------------------------------------------
void OnFileOpen(HINSTANCE hInst, HWND hWnd) { const WCHAR *filter = L"Bitmap Files (*.bmp)\0*.bmp\0" L"PNG Files (*.png)\0*.png\0" L"All Files (*.*)\0*.*\0\0";
OPENFILENAME ofn = {sizeof(ofn)}; WCHAR szFile[_MAX_PATH+1] = {0};
//---- init ofn ----
ofn.hwndOwner = hWnd; ofn.hInstance = hInst; ofn.lpstrFile = szFile; ofn.nMaxFile = ARRAYSIZE(szFile); ofn.lpstrFilter = filter; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = L"Select an Image File to preview"; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn)) { HRESULT hr = InitDib(hInst, szFile); if (SUCCEEDED(hr)) InvalidateRect(hWnd, NULL, TRUE); } } //----------------------------------------------------------------------------
void SetZoom(HWND hWnd, HINSTANCE hInstance, int iZoomPercent, int iMenuId) { iZoomFactor = iZoomPercent;
InvalidateRect(hWnd, NULL, TRUE);
//---- update menu items ----
HMENU hMenu = GetMenu(hWnd); hMenu = GetSubMenu(hMenu, 2);
if (iCurrentZoomMenu) CheckMenuItem(hMenu, iCurrentZoomMenu, MF_BYCOMMAND | MF_UNCHECKED); CheckMenuItem(hMenu, iMenuId, MF_BYCOMMAND | MF_CHECKED);
iCurrentZoomMenu = iMenuId; } //----------------------------------------------------------------------------
|