2025-04-27 07:49:33 -04:00

1208 lines
36 KiB
C++

#include "ShowIcon.h"
HINSTANCE g_hInstance;
enum ICONVIEW
{
IV_ICON,
IV_MASK,
IV_COLOR,
IV_ALPHA
};
enum CURSORVIEW
{
CV_ICON,
CV_CURSOR,
CV_DEFAULT
};
enum LOADOPTIONS
{
LO_DEFAULT,
LO_REAL,
LO_16,
LO_32,
LO_48,
LO_64,
LO_96,
LO_128
};
enum DISPLAYOPTIONS
{
DO_NORMALDC,
DO_METAFILEDC,
DO_ENHMETAFILEDC
};
struct VIEWDATA
{
ICONINFO iconinfo;
HICON hIcon;
HCURSOR hIconCursor;
HCURSOR hDefaultCursor;
HBITMAP hbmpAlpha;
HBITMAP hbmpPreMultiplied; // Premultiplied version of the color bitmap.
HBRUSH hbrBackground;
};
/////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK ExtractIconDlgProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
static int * pcIcons = NULL;
switch(uMsg)
{
case WM_INITDIALOG:
{
pcIcons = (int *)lParam;
WCHAR strDesc[100];
wsprintf(strDesc, L"There are %d icons in this file.", *pcIcons);
SetDlgItemText(hwndDlg, IDC_EI_NUMICONS, strDesc);
SetDlgItemInt(hwndDlg, IDC_EI_ICONINDEX, 0, FALSE);
}
break;
case WM_COMMAND:
{
WORD wCommand = LOWORD(wParam);
switch(wCommand)
{
case IDOK:
{
BOOL fTranslated = FALSE;
*pcIcons = GetDlgItemInt(hwndDlg, IDC_EI_ICONINDEX, &fTranslated, FALSE);
if(!fTranslated || (*pcIcons < 0)) {
*pcIcons = -1;
}
}
EndDialog(hwndDlg, IDOK);
break;
case IDCANCEL:
*pcIcons = -1;
EndDialog(hwndDlg, IDCANCEL);
break;
}
}
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////////
void GetBitmapSize(VIEWDATA & vd, DWORD & dwWidth, DWORD & dwHeight, bool & fAlpha)
{
BITMAP bmp;
if (vd.iconinfo.hbmColor != NULL) {
if (!GetObject(vd.iconinfo.hbmColor, sizeof(BITMAP), (LPSTR) &bmp)) {
bmp.bmWidth = 0;
bmp.bmHeight = 0;
bmp.bmBitsPixel = 0;
}
} else {
if (GetObject(vd.iconinfo.hbmMask, sizeof(BITMAP), (LPSTR) &bmp)) {
bmp.bmHeight /= 2;
} else {
bmp.bmWidth = 0;
bmp.bmHeight = 0;
bmp.bmBitsPixel = 0;
}
}
dwWidth = bmp.bmWidth;
dwHeight = bmp.bmHeight;
//
// Note: This just means that the bitmap MIGHT have an alpha channel.
//
fAlpha = (bmp.bmBitsPixel == 32 && bmp.bmPlanes == 1);
}
/////////////////////////////////////////////////////////////////////////////
void SetShowIconTitle(HWND hwndMain, TCHAR * pszFileName, VIEWDATA & vd)
{
TCHAR szTitle[MAX_PATH * 2];
DWORD dwWidth, dwHeight;
bool fAlpha = false;
GetBitmapSize(vd, dwWidth, dwHeight, fAlpha);
wsprintf(szTitle,
TEXT("ShowIcon [%dx%d] - %s"),
dwWidth,
dwHeight,
NULL == pszFileName ? TEXT("[Internal]") : pszFileName);
SetWindowText(hwndMain, szTitle);
}
/////////////////////////////////////////////////////////////////////////////
void InitializeViewData(VIEWDATA & vd)
{
vd.hIcon = NULL;
vd.hIconCursor = NULL;
vd.hDefaultCursor = LoadCursor(NULL, IDC_ARROW);
vd.iconinfo.hbmColor = NULL;
vd.iconinfo.hbmMask = NULL;
vd.iconinfo.fIcon = TRUE;
vd.iconinfo.xHotspot = 0;
vd.iconinfo.yHotspot = 0;
vd.hbmpAlpha = NULL;
vd.hbmpPreMultiplied = NULL;
vd.hbrBackground = NULL;
}
/////////////////////////////////////////////////////////////////////////////
void ClearViewData(VIEWDATA & vd)
{
if (vd.hIcon != NULL) {
DestroyIcon(vd.hIcon);
vd.hIcon = NULL;
}
if (vd.hIconCursor != NULL) {
DestroyCursor(vd.hIconCursor);
vd.hIconCursor = NULL;
}
if (vd.hDefaultCursor != NULL) {
DestroyCursor(vd.hDefaultCursor);
vd.hDefaultCursor = NULL;
}
if (vd.iconinfo.hbmColor != NULL) {
DeleteObject(vd.iconinfo.hbmColor);
vd.iconinfo.hbmColor = NULL;
}
if (vd.iconinfo.hbmMask != NULL) {
DeleteObject(vd.iconinfo.hbmMask);
vd.iconinfo.hbmMask = NULL;
}
vd.iconinfo.fIcon = TRUE;
vd.iconinfo.xHotspot = 0;
vd.iconinfo.yHotspot = 0;
if (vd.hbmpAlpha != NULL) {
DeleteObject(vd.hbmpAlpha);
vd.hbmpAlpha = NULL;
}
if (vd.hbmpPreMultiplied != NULL) {
DeleteObject(vd.hbmpPreMultiplied);
vd.hbmpPreMultiplied = NULL;
}
if (vd.hbrBackground != NULL) {
DeleteObject(vd.hbrBackground);
vd.hbrBackground = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////
//
// This function takes an existing VIEWDATA structure, and rebuilds the
// ICONINFO data and hbmpAlpha from the already-loaded HICON.
//
void RefreshViewData(VIEWDATA & vd)
{
if (vd.hDefaultCursor == NULL) {
vd.hDefaultCursor = LoadCursor(NULL, IDC_ARROW);
}
if (vd.hbrBackground == NULL) {
LOGBRUSH lb;
lb.lbStyle = BS_HATCHED;
lb.lbColor = RGB(0, 0, 0);
lb.lbHatch = HS_BDIAGONAL;
vd.hbrBackground = CreateBrushIndirect(&lb);
}
if (vd.hIcon != NULL) {
//
// First, clear out any existing fields.
//
if (vd.iconinfo.hbmColor != NULL) {
DeleteObject(vd.iconinfo.hbmColor);
vd.iconinfo.hbmColor = NULL;
}
if (vd.iconinfo.hbmMask != NULL) {
DeleteObject(vd.iconinfo.hbmMask);
vd.iconinfo.hbmMask = NULL;
}
vd.iconinfo.fIcon = TRUE;
vd.iconinfo.xHotspot = 0;
vd.iconinfo.yHotspot = 0;
if (vd.hbmpAlpha != NULL) {
DeleteObject(vd.hbmpAlpha);
vd.hbmpAlpha = NULL;
}
if (vd.hbmpPreMultiplied != NULL) {
DeleteObject(vd.hbmpPreMultiplied);
vd.hbmpPreMultiplied = NULL;
}
//
// Now get the new data.
//
GetIconInfo(vd.hIcon, &vd.iconinfo);
}
else if(vd.iconinfo.hbmColor != NULL)
{
//
// This appears to be a simple bitmap. There still might be an
// alpha channel.
//
// First, clear out any existing fields.
//
if (vd.iconinfo.hbmMask != NULL) {
DeleteObject(vd.iconinfo.hbmMask);
vd.iconinfo.hbmMask = NULL;
}
vd.iconinfo.fIcon = TRUE; // Well, certainly not a cursor.
vd.iconinfo.xHotspot = 0;
vd.iconinfo.yHotspot = 0;
if (vd.hbmpAlpha != NULL) {
DeleteObject(vd.hbmpAlpha);
vd.hbmpAlpha = NULL;
}
if (vd.hbmpPreMultiplied != NULL) {
DeleteObject(vd.hbmpPreMultiplied);
vd.hbmpPreMultiplied = NULL;
}
}
else
{
//
// Neither an icon, nor a bitmap. Bail.
//
return;
}
DWORD dwWidth;
DWORD dwHeight;
bool fAlpha;
GetBitmapSize(vd, dwWidth, dwHeight, fAlpha);
//
// Create a bitmap to store a representation of the alpha channel.
//
if (fAlpha) {
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = dwWidth;
bmi.bmiHeader.biHeight = dwHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
//
// We need the desktop DC for various reasons.
//
HDC hdc = GetDC(NULL);
//
// Create the bitmap and get back a pointer to where the actual
// bits are located.
//
RGBQUAD * pImageBits = NULL;
vd.hbmpAlpha = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **) &pImageBits, NULL, 0);
//
// Now, copy the bits from the icon image bitmap into our new bitmap.
//
if (0 != GetDIBits(hdc, vd.iconinfo.hbmColor, 0, dwHeight, pImageBits, &bmi, DIB_RGB_COLORS)) {
bool fAlphaUsed = false;
//
// Now, spin through the bitmap and look to see if the alpha
// channel is even used.
//
for(DWORD y = 0; y < dwHeight && !fAlphaUsed; y++) {
for(DWORD x = 0; x < dwWidth && !fAlphaUsed; x++) {
BYTE bAlpha = pImageBits[y*dwWidth + x].rgbReserved;
if (bAlpha != 0) {
fAlphaUsed = true;
}
}
}
//
// Now, spin through the bitmap and create a grey-scale ramp
// that reflects the alpha channel.
//
if (fAlphaUsed) {
for(DWORD y = 0; y < dwHeight; y++) {
for(DWORD x = 0; x < dwWidth; x++) {
BYTE bAlpha = pImageBits[y*dwWidth + x].rgbReserved;
pImageBits[y*dwWidth + x].rgbRed = bAlpha;
pImageBits[y*dwWidth + x].rgbGreen = bAlpha;
pImageBits[y*dwWidth + x].rgbBlue = bAlpha;
pImageBits[y*dwWidth + x].rgbReserved = 0xFF;
}
}
} else {
//
// Clean up the unused alpha bitmap.
//
DeleteObject(vd.hbmpAlpha);
vd.hbmpAlpha = NULL;
}
}
//
// We're done with the desktop DC.
//
ReleaseDC(NULL, hdc);
}
//
// Create a bitmap to store the premultiplied version of the color bitmap.
//
if (fAlpha && vd.hbmpAlpha != NULL) {
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = dwWidth;
bmi.bmiHeader.biHeight = dwHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
//
// We need the desktop DC for various reasons.
//
HDC hdc = GetDC(NULL);
//
// Create the bitmap and get back a pointer to where the actual
// bits are located.
//
RGBQUAD * pImageBits = NULL;
vd.hbmpPreMultiplied = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **) &pImageBits, NULL, 0);
//
// Now, copy the bits from the icon image bitmap into our new bitmap.
//
if (0 != GetDIBits(hdc, vd.iconinfo.hbmColor, 0, dwHeight, pImageBits, &bmi, DIB_RGB_COLORS)) {
//
// Now, spin through the bitmap and pre-multiply each pixel.
//
RGBQUAD pixel;
for(DWORD y = 0; y < dwHeight; y++) {
for(DWORD x = 0; x < dwWidth; x++) {
pixel = pImageBits[y*dwWidth + x];
pImageBits[y*dwWidth + x].rgbRed = (pixel.rgbRed * pixel.rgbReserved) / 0xFF;
pImageBits[y*dwWidth + x].rgbGreen = (pixel.rgbGreen * pixel.rgbReserved) / 0xFF;
pImageBits[y*dwWidth + x].rgbBlue = (pixel.rgbBlue * pixel.rgbReserved) / 0xFF;
}
}
}
//
// We're done with the desktop DC.
//
ReleaseDC(NULL, hdc);
}
}
/////////////////////////////////////////////////////////////////////////////
void LoadViewData(VIEWDATA & vd, TCHAR * pszFileName, UINT fuLoad, LOADOPTIONS lo)
{
int x = 0;
int y = 0;
HINSTANCE hInstance = (fuLoad == LR_LOADFROMFILE ? NULL : g_hInstance);
ClearViewData(vd);
switch (lo) {
case LO_REAL:
x = 0;
y = 0;
break;
case LO_DEFAULT:
fuLoad |= LR_DEFAULTSIZE;
break;
case LO_16:
x = 16;
y = 16;
break;
case LO_32:
x = 32;
y = 32;
break;
case LO_48:
x = 48;
y = 48;
break;
case LO_64:
x = 64;
y = 64;
break;
case LO_96:
x = 96;
y = 96;
break;
case LO_128:
x = 128;
y = 128;
break;
}
vd.hIcon = (HICON) LoadImage(hInstance, pszFileName, IMAGE_ICON, x, y, fuLoad | LR_SHARED);
if (vd.hIcon != NULL) {
vd.hIconCursor = (HCURSOR) LoadImage(hInstance, pszFileName, IMAGE_CURSOR, x, y, fuLoad | LR_SHARED);
} else {
//
// Try to load the image as a bitmap...
//
vd.hIcon = NULL;
vd.hIconCursor = NULL;
vd.iconinfo.fIcon = TRUE; // Well, it certainly isn't a cursor....
vd.iconinfo.hbmColor = (HBITMAP) LoadImage(hInstance, pszFileName, IMAGE_BITMAP, x, y, fuLoad | LR_SHARED);
vd.iconinfo.hbmMask = NULL;
vd.iconinfo.xHotspot = 0;
vd.iconinfo.yHotspot = 0;
vd.hbmpAlpha = NULL;
}
RefreshViewData(vd);
}
/////////////////////////////////////////////////////////////////////////////
void ReLoadViewData(VIEWDATA & vd, UINT fuLoad, LOADOPTIONS lo)
{
int x = 0;
int y = 0;
HINSTANCE hInstance = (fuLoad == LR_LOADFROMFILE ? NULL : g_hInstance);
HICON hIcon = NULL;
HCURSOR hIconCursor = NULL;
HBITMAP hbmColor = NULL;
switch (lo) {
case LO_REAL:
x = 0;
y = 0;
break;
case LO_DEFAULT:
fuLoad |= LR_DEFAULTSIZE;
break;
case LO_16:
x = 16;
y = 16;
break;
case LO_32:
x = 32;
y = 32;
break;
case LO_48:
x = 48;
y = 48;
break;
case LO_64:
x = 64;
y = 64;
break;
case LO_96:
x = 96;
y = 96;
break;
case LO_128:
x = 128;
y = 128;
break;
}
//
// Make copies of the exisitng icon and cursor.
//
if (vd.hIcon != NULL) {
hIcon = (HICON) CopyImage(vd.hIcon, IMAGE_ICON, x, y, fuLoad | LR_COPYFROMRESOURCE | LR_SHARED);
}
if (hIcon != NULL) {
if (vd.hIconCursor != NULL) {
hIconCursor = (HCURSOR) CopyImage(vd.hIconCursor, IMAGE_CURSOR, x, y, fuLoad | LR_COPYFROMRESOURCE | LR_SHARED);
}
} else {
if (vd.iconinfo.hbmColor != NULL) {
hbmColor = (HBITMAP) CopyImage(vd.iconinfo.hbmColor, IMAGE_BITMAP, x, y, fuLoad | LR_COPYFROMRESOURCE | LR_SHARED);
}
}
//
// Nuke the existing draw data.
//
ClearViewData(vd);
vd.hIcon = hIcon;
if (vd.hIcon != NULL) {
vd.hIconCursor = hIconCursor;
} else {
//
// Try to load the image as a bitmap...
//
vd.hIcon = NULL;
vd.hIconCursor = NULL;
vd.iconinfo.fIcon = TRUE; // Well, it certainly isn't a cursor....
vd.iconinfo.hbmColor = hbmColor;
vd.iconinfo.hbmMask = NULL;
vd.iconinfo.xHotspot = 0;
vd.iconinfo.yHotspot = 0;
vd.hbmpAlpha = NULL;
}
RefreshViewData(vd);
}
/////////////////////////////////////////////////////////////////////////////
ICONVIEW SelectIconView(HMENU hMenu, int id)
{
MENUITEMINFO mii;
int rgMenuItems[] = { VIEW_ICON, VIEW_MASK, VIEW_COLOR, VIEW_ALPHA };
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STATE;
for(int i = 0; i < sizeof(rgMenuItems) / sizeof(rgMenuItems[ 0 ]); i++) {
GetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
if (rgMenuItems[ i ] == id) {
if ((mii.fState & MFS_CHECKED) == 0) {
mii.fState |= MFS_CHECKED;
SetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
}
} else {
if (mii.fState & MFS_CHECKED) {
mii.fState &= (~MFS_CHECKED);
SetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
}
}
}
switch (id) {
case VIEW_ICON:
default:
return IV_ICON;
case VIEW_MASK:
return IV_MASK;
case VIEW_COLOR:
return IV_COLOR;
case VIEW_ALPHA:
return IV_ALPHA;
}
}
/////////////////////////////////////////////////////////////////////////////
CURSORVIEW SelectCursorView(HMENU hMenu, int id)
{
MENUITEMINFO mii;
int rgMenuItems[] = { VIEW_ICONCURSOR, VIEW_REALCURSOR, VIEW_DEFAULTCURSOR };
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STATE;
for(int i = 0; i < sizeof(rgMenuItems) / sizeof(rgMenuItems[ 0 ]); i++) {
GetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
if (rgMenuItems[ i ] == id) {
if ((mii.fState & MFS_CHECKED) == 0) {
mii.fState |= MFS_CHECKED;
SetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
}
} else {
if (mii.fState & MFS_CHECKED) {
mii.fState &= (~MFS_CHECKED);
SetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
}
}
}
switch (id) {
case VIEW_ICONCURSOR:
return CV_ICON;
case VIEW_REALCURSOR:
return CV_CURSOR;
case VIEW_DEFAULTCURSOR:
default:
return CV_DEFAULT;
}
}
/////////////////////////////////////////////////////////////////////////////
LOADOPTIONS SelectLoadOptions(HMENU hMenu, int id)
{
MENUITEMINFO mii;
int rgMenuItems[] = { IDM_DEFAULT_SIZE, IDM_REAL_SIZE, IDM_SIZE_16, IDM_SIZE_32, IDM_SIZE_48, IDM_SIZE_64, IDM_SIZE_96, IDM_SIZE_128 };
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STATE;
for(int i = 0; i < sizeof(rgMenuItems) / sizeof(rgMenuItems[ 0 ]); i++) {
GetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
if (rgMenuItems[ i ] == id) {
if ((mii.fState & MFS_CHECKED) == 0) {
mii.fState |= MFS_CHECKED;
SetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
}
} else {
if (mii.fState & MFS_CHECKED) {
mii.fState &= (~MFS_CHECKED);
SetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
}
}
}
switch (id) {
case IDM_REAL_SIZE:
return LO_REAL;
case IDM_SIZE_16:
return LO_16;
case IDM_SIZE_32:
return LO_32;
case IDM_SIZE_48:
return LO_48;
case IDM_SIZE_64:
return LO_64;
case IDM_SIZE_96:
return LO_96;
case IDM_SIZE_128:
return LO_128;
case IDM_DEFAULT_SIZE:
default:
return LO_DEFAULT;
}
}
/////////////////////////////////////////////////////////////////////////////
DISPLAYOPTIONS SelectDisplayOptions(HMENU hMenu, int id)
{
MENUITEMINFO mii;
int rgMenuItems[] = { IDM_METAFILEDC, IDM_ENHMETAFILEDC, IDM_NORMALDC };
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STATE;
for(int i = 0; i < sizeof(rgMenuItems) / sizeof(rgMenuItems[ 0 ]); i++) {
GetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
if (rgMenuItems[ i ] == id) {
if ((mii.fState & MFS_CHECKED) == 0) {
mii.fState |= MFS_CHECKED;
SetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
}
} else {
if (mii.fState & MFS_CHECKED) {
mii.fState &= (~MFS_CHECKED);
SetMenuItemInfo(hMenu, rgMenuItems[ i ], FALSE, &mii);
}
}
}
switch(id)
{
case IDM_METAFILEDC:
return DO_METAFILEDC;
break;
case IDM_ENHMETAFILEDC:
return DO_ENHMETAFILEDC;
break;
case IDM_NORMALDC:
default:
return DO_NORMALDC;
}
}
/////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static VIEWDATA vd;
static TCHAR szFileName[MAX_PATH];
static ICONVIEW iv = IV_ICON;
static CURSORVIEW cv = CV_DEFAULT;
static LOADOPTIONS lo = LO_REAL;
static DISPLAYOPTIONS dop = DO_NORMALDC;
switch (message) {
case WM_CREATE:
InitializeViewData(vd);
szFileName[0] = '\0';
iv = IV_ICON;
cv = CV_DEFAULT;
lo = LO_REAL;
dop = DO_NORMALDC;
DragAcceptFiles(hWnd, TRUE);
LoadViewData(vd, szFileName, 0, lo);
SetShowIconTitle(hWnd, szFileName, vd);
break;
case WM_DROPFILES:
{
HDROP hdrop = (HDROP) wParam;
DragQueryFile(hdrop, 0, szFileName, MAX_PATH);
LoadViewData(vd, szFileName, LR_LOADFROMFILE, lo);
SetShowIconTitle(hWnd, szFileName, vd);
InvalidateRgn(hWnd, NULL, TRUE);
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
int wmEvent HIWORD(wParam);
switch (wmId) {
case IDM_DEFAULT_SIZE:
case IDM_REAL_SIZE:
case IDM_SIZE_16:
case IDM_SIZE_32:
case IDM_SIZE_48:
case IDM_SIZE_64:
case IDM_SIZE_96:
case IDM_SIZE_128:
lo = SelectLoadOptions(GetMenu(hWnd), wmId);
break;
case IDM_NORMALDC:
case IDM_METAFILEDC:
case IDM_ENHMETAFILEDC:
dop = SelectDisplayOptions(GetMenu(hWnd), wmId);
InvalidateRgn(hWnd, NULL, TRUE);
break;
case VIEW_ICON:
case VIEW_MASK:
case VIEW_COLOR:
case VIEW_ALPHA:
iv = SelectIconView(GetMenu(hWnd), wmId);
InvalidateRgn(hWnd, NULL, TRUE);
break;
case VIEW_REFRESH:
RefreshViewData(vd);
InvalidateRgn(hWnd, NULL, TRUE);
break;
case VIEW_ICONCURSOR:
case VIEW_REALCURSOR:
case VIEW_DEFAULTCURSOR:
cv = SelectCursorView(GetMenu(hWnd), wmId);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDM_SAMPLE16:
LoadViewData(vd, MAKEINTRESOURCE(IDI_SAMPLE16), LR_DEFAULTCOLOR, lo);
SetShowIconTitle(hWnd, NULL, vd);
InvalidateRgn(hWnd, NULL, TRUE);
break;
case IDM_SAMPLE32:
LoadViewData(vd, MAKEINTRESOURCE(IDI_SAMPLE32), LR_DEFAULTCOLOR, lo);
SetShowIconTitle(hWnd, NULL, vd);
InvalidateRgn(hWnd, NULL, TRUE);
break;
case IDM_SAMPLE64:
LoadViewData(vd, MAKEINTRESOURCE(IDI_SAMPLE64), LR_DEFAULTCOLOR, lo);
SetShowIconTitle(hWnd, NULL, vd);
InvalidateRgn(hWnd, NULL, TRUE);
break;
case IDM_APPICON:
LoadViewData(vd, MAKEINTRESOURCE(IDI_SHOWICON), LR_DEFAULTCOLOR, lo);
SetShowIconTitle(hWnd, NULL, vd);
InvalidateRgn(hWnd, NULL, TRUE);
break;
case IDM_MYCOMPUTER:
LoadViewData(vd, MAKEINTRESOURCE(IDI_MYCOMPUTER), LR_DEFAULTCOLOR, lo);
SetShowIconTitle(hWnd, NULL, vd);
InvalidateRgn(hWnd, NULL, TRUE);
break;
case IDM_FILE_OPEN:
{
OPENFILENAME ofn;
TCHAR * szFilter = TEXT("Icons (*.ico)\0*.ico\0")
TEXT("Cursors (*.cur)\0*.cur\0")
TEXT("Bitmaps (*.bmp)\0*.bmp\0")
TEXT("All Supported Formats (*.ico;*.cur;*.bmp)\0*.ico;*.cur;*.bmp\0")
TEXT("All Files (*.*)\0*.*\0");
szFileName[0] = TEXT('\0');
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.hInstance = g_hInstance;
ofn.lpstrFilter = szFilter;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
ofn.lpstrDefExt = TEXT("*.ico");
if (GetOpenFileName(&ofn)) {
LoadViewData(vd, szFileName, LR_LOADFROMFILE, lo);
SetShowIconTitle(hWnd, szFileName, vd);
InvalidateRgn(hWnd, NULL, TRUE);
}
}
break;
case IDM_FILE_EXTRACTICON:
{
OPENFILENAME ofn;
TCHAR * szFilter = TEXT("Programs (*.exe)\0*.exe\0")
TEXT("DLLs (*.dll;*.ocx)\0*.dll;*.ocx\0")
TEXT("All Supported Formats (*.exe;*.dll;*.ocx)\0*.exe;*.dll;*.ocx\0")
TEXT("All Files (*.*)\0*.*\0");
szFileName[0] = TEXT('\0');
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.hInstance = g_hInstance;
ofn.lpstrFilter = szFilter;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
ofn.lpstrDefExt = TEXT("*.exe");
if (GetOpenFileName(&ofn)) {
ClearViewData(vd);
int cIcons = (int) ExtractIconW(g_hInstance, szFileName, -1);
if (cIcons > 0) {
if(DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_EXTRACTICON), hWnd, ExtractIconDlgProc, LPARAM(&cIcons)) == IDOK) {
vd.hIcon = ExtractIconW(g_hInstance, szFileName, cIcons);
RefreshViewData(vd);
SetShowIconTitle(hWnd, szFileName, vd);
}
}
InvalidateRgn(hWnd, NULL, TRUE);
}
}
break;
case IDM_FILE_REOPEN:
{
ReLoadViewData(vd, 0, lo);
InvalidateRgn(hWnd, NULL, TRUE);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_SO_LOADFILE:
LoadViewData(vd, (TCHAR*)lParam, LR_LOADFROMFILE, lo);
SetShowIconTitle(hWnd, (TCHAR*)lParam, vd);
InvalidateRgn(hWnd, NULL, TRUE);
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdcWindow = BeginPaint(hWnd, &ps);
RECT rcClient;
HDC hdcPaint = NULL;
if (dop == DO_METAFILEDC) {
hdcPaint = CreateMetaFile(NULL);
} else if (dop == DO_ENHMETAFILEDC) {
hdcPaint = CreateEnhMetaFile(hdcWindow, NULL, NULL, NULL);
} else {
hdcPaint = hdcWindow;
}
GetClientRect(hWnd, &rcClient);
SetBrushOrgEx(hdcPaint, -5, -5, NULL);
SetBkColor(hdcPaint, RGB(128, 128, 128));
SetBkMode(hdcPaint, OPAQUE);
if (ps.fErase) {
FillRect(hdcPaint, &(ps.rcPaint), vd.hbrBackground);
}
if (iv == IV_ICON) {
//
// Draw either the icon, alpha-blended bitmap, or normal bitmap.
//
if (vd.hIcon != NULL) {
DrawIconEx(hdcPaint, 5, 5, vd.hIcon, rcClient.right - 10, rcClient.bottom - 10, 0, NULL, DI_NORMAL);
} else if(vd.hbmpPreMultiplied != NULL) {
HDC hdcBitmap = NULL;
HBITMAP hbmOld = NULL;
DWORD dwWidth, dwHeight;
bool fAlpha;
BLENDFUNCTION bf;
GetBitmapSize(vd, dwWidth, dwHeight, fAlpha);
hdcBitmap = CreateCompatibleDC(hdcPaint);
hbmOld = (HBITMAP) SelectObject(hdcBitmap, vd.iconinfo.hbmColor);
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;
AlphaBlend(hdcPaint, 5, 5, rcClient.right - 10, rcClient.bottom - 10, hdcBitmap, 0, 0, dwWidth, dwHeight, bf);
SelectObject(hdcBitmap, hbmOld);
DeleteDC(hdcBitmap);
} else if(vd.iconinfo.hbmColor != NULL) {
HDC hdcBitmap = NULL;
HBITMAP hbmOld = NULL;
DWORD dwWidth, dwHeight;
bool fAlpha;
GetBitmapSize(vd, dwWidth, dwHeight, fAlpha);
hdcBitmap = CreateCompatibleDC(hdcPaint);
hbmOld = (HBITMAP) SelectObject(hdcBitmap, vd.iconinfo.hbmColor);
StretchBlt(hdcPaint, 5, 5, rcClient.right - 10, rcClient.bottom - 10, hdcBitmap, 0, 0, dwWidth, dwHeight, SRCCOPY);
SelectObject(hdcBitmap, hbmOld);
DeleteDC(hdcBitmap);
} else {
DrawText(hdcPaint, TEXT("No icon data to display"), -1, &rcClient, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
}
} else if (iv == IV_COLOR && vd.iconinfo.hbmColor != NULL) {
HDC hdcBitmap = NULL;
HBITMAP hbmOld = NULL;
DWORD dwWidth, dwHeight;
bool fAlpha;
GetBitmapSize(vd, dwWidth, dwHeight, fAlpha);
hdcBitmap = CreateCompatibleDC(hdcPaint);
hbmOld = (HBITMAP) SelectObject(hdcBitmap, vd.iconinfo.hbmColor);
StretchBlt(hdcPaint, 5, 5, rcClient.right - 10, rcClient.bottom - 10, hdcBitmap, 0, 0, dwWidth, dwHeight, SRCCOPY);
SelectObject(hdcBitmap, hbmOld);
DeleteDC(hdcBitmap);
} else if (iv == IV_MASK && vd.iconinfo.hbmMask != NULL) {
HDC hdcBitmap = NULL;
HBITMAP hbmOld = NULL;
DWORD dwWidth, dwHeight;
bool fAlpha;
GetBitmapSize(vd, dwWidth, dwHeight, fAlpha);
hdcBitmap = CreateCompatibleDC(hdcPaint);
hbmOld = (HBITMAP) SelectObject(hdcBitmap, vd.iconinfo.hbmMask);
StretchBlt(hdcPaint, 5, 5, rcClient.right - 10, rcClient.bottom - 10, hdcBitmap, 0, 0, dwWidth, dwHeight, SRCCOPY);
SelectObject(hdcBitmap, hbmOld);
DeleteDC(hdcBitmap);
} else if (iv == IV_ALPHA && vd.hbmpAlpha != NULL) {
HDC hdcBitmap = NULL;
HBITMAP hbmOld = NULL;
DWORD dwWidth, dwHeight;
bool fAlpha;
GetBitmapSize(vd, dwWidth, dwHeight, fAlpha);
hdcBitmap = CreateCompatibleDC(hdcPaint);
hbmOld = (HBITMAP) SelectObject(hdcBitmap, vd.hbmpAlpha);
StretchBlt(hdcPaint, 5, 5, rcClient.right - 10, rcClient.bottom - 10, hdcBitmap, 0, 0, dwWidth, dwHeight, SRCCOPY);
SelectObject(hdcBitmap, hbmOld);
DeleteDC(hdcBitmap);
} else {
DrawText(hdcPaint, TEXT("No icon data to display"), -1, &rcClient, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
}
if (dop == DO_METAFILEDC) {
HMETAFILE hMetafile = CloseMetaFile(hdcPaint);
PlayMetaFile(hdcWindow, hMetafile);
DeleteMetaFile(hMetafile);
} else if (dop == DO_ENHMETAFILEDC) {
HENHMETAFILE hMetafile = CloseEnhMetaFile(hdcPaint);
PlayEnhMetaFile(hdcWindow, hMetafile, &rcClient);
DeleteEnhMetaFile(hMetafile);
} else {
hdcPaint = NULL;
}
EndPaint(hWnd, &ps);
}
break;
case WM_SETCURSOR:
if (LOWORD(lParam) == HTCLIENT) {
HCURSOR hCursor = NULL;
switch (cv) {
case CV_ICON:
hCursor = (HCURSOR) vd.hIcon;
break;
case CV_CURSOR:
hCursor = vd.hIconCursor;
break;
case CV_DEFAULT:
hCursor = vd.hDefaultCursor;
break;
}
SetCursor(hCursor);
return(TRUE);
} else {
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
ClearViewData(vd);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
/////////////////////////////////////////////////////////////////////////////
ATOM RegisterLoadIconClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR) IDI_SHOWICON);
wcex.hCursor = NULL;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = (LPCTSTR) IDC_SHOWICON;
wcex.lpszClassName = TEXT("LoadIconClass");
wcex.hIconSm = LoadIcon(hInstance, (LPCTSTR) IDI_SHOWICON);
return RegisterClassEx(&wcex);
}
int
WINAPI
WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HACCEL hAccelTable = LoadAccelerators(hInstance, (LPCTSTR) IDC_SHOWICON);
LPWSTR *argv;
int argc;
g_hInstance = hInstance;
//
// Register the window class.
//
RegisterLoadIconClass(hInstance);
HWND hwndMain = CreateWindow(TEXT("LoadIconClass"),
TEXT("LoadIcon"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
0,
180,
180,
NULL,
NULL,
hInstance,
NULL);
if (hwndMain == NULL) {
return FALSE;
}
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
/*
* For now we only allow one file to be passed on the command line.
* Ideally, we should package up the VIEWDATA, LOADOPTIONS, etc. into a
* struct that we hang off each window. Then we can open a window for every
* file (however many) on the cl.
*
* Moreover, the file can't be on a share; it must be local. I'm not sure if
* this is by design, but it's something to look into.
*/
if (argc == 2) {
SendMessage(hwndMain, WM_SO_LOADFILE, (WPARAM)0, (LPARAM)argv[1]);
}
GlobalFree(argv);
ShowWindow(hwndMain, nCmdShow);
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam != 0;
}