You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
471 lines
14 KiB
471 lines
14 KiB
//----------------------------------------------------------------------------
|
|
// 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;
|
|
}
|
|
//----------------------------------------------------------------------------
|