Skip to content

Commit f8bb38a

Browse files
committed
Fix [17b509d78f]: wm iconbitmap does not support icon files with png images on Windows.
2 parents f8e4b11 + 9e01333 commit f8bb38a

File tree

2 files changed

+56
-33
lines changed

2 files changed

+56
-33
lines changed

changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ to the userbase.
3737
- [tk print canvas with smooth lines crashes on windows](https://core.tcl-lang.org/tk/tktview/9b23b6)
3838
- [Collect utility procs for the Tk test suite](https://core.tcl-lang.org/tk/tktview/718cbc)
3939
- [Setting ttk state may change the a variable passed by value](https://core.tcl-lang.org/tk/info/7231bf)
40+
- [wm iconbitmap does not support icon files with png images on Windows](https://core.tcl-lang.org/tk/info/17b509)
4041

4142
Release Tk 9.0.1 arises from the check-in with tag `core-9-0-1`.
4243

win/tkWinWm.c

Lines changed: 55 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -549,24 +549,16 @@ MakeIconOrCursorFromResource(
549549
* Let the OS do the real work :)
550550
*/
551551

552-
hIcon = (HICON) CreateIconFromResourceEx(lpIcon->lpBits,
553-
lpIcon->dwNumBytes, isIcon, 0x00030000,
554-
(*(LPBITMAPINFOHEADER) lpIcon->lpBits).biWidth,
555-
(*(LPBITMAPINFOHEADER) lpIcon->lpBits).biHeight/2, 0);
552+
hIcon = (HICON)CreateIconFromResourceEx(lpIcon->lpBits,
553+
lpIcon->dwNumBytes, isIcon, 0x00030000, 0, 0, 0);
556554

557555
/*
558-
* It failed, odds are good we're on NT so try the non-Ex way.
556+
* It failed, the non-Ex way might work as a fallback.
559557
*/
560558

561559
if (hIcon == NULL) {
562-
/*
563-
* We would break on NT if we try with a 16bpp image.
564-
*/
565-
566-
if (lpIcon->lpbi->bmiHeader.biBitCount != 16) {
567-
hIcon = CreateIconFromResource(lpIcon->lpBits, lpIcon->dwNumBytes,
568-
isIcon, 0x00030000);
569-
}
560+
hIcon = CreateIconFromResource(lpIcon->lpBits, lpIcon->dwNumBytes,
561+
isIcon, 0x00030000);
570562
}
571563
return hIcon;
572564
}
@@ -1104,6 +1096,50 @@ ReadIconFromFile(
11041096
*----------------------------------------------------------------------
11051097
*/
11061098

1099+
static BOOL
1100+
SetSizeAndColorFromHICON( /* Helper for AdjustIconImagePointers */
1101+
HICON hicon,
1102+
LPICONIMAGE lpImage)
1103+
{
1104+
ICONINFO info;
1105+
BOOL bRes;
1106+
BITMAP bmp;
1107+
1108+
memset(&info, 0, sizeof(info));
1109+
1110+
bRes = GetIconInfo(hicon, &info);
1111+
if (!bRes) {
1112+
return FALSE;
1113+
}
1114+
1115+
if (info.hbmColor) {
1116+
const int nWrittenBytes = GetObject(info.hbmColor, sizeof(bmp), &bmp);
1117+
1118+
if (nWrittenBytes > 0) {
1119+
lpImage->Width = bmp.bmWidth;
1120+
lpImage->Height = bmp.bmHeight;
1121+
lpImage->Colors = bmp.bmBitsPixel;
1122+
}
1123+
} else if (info.hbmMask) {
1124+
// Icon has no color plane, image data stored in mask
1125+
const int nWrittenBytes = GetObject(info.hbmMask, sizeof(bmp), &bmp);
1126+
1127+
if (nWrittenBytes > 0) {
1128+
lpImage->Width = bmp.bmWidth;
1129+
lpImage->Height = bmp.bmHeight / 2;
1130+
lpImage->Colors = 1;
1131+
}
1132+
}
1133+
1134+
if (info.hbmColor) {
1135+
DeleteObject(info.hbmColor);
1136+
}
1137+
if (info.hbmMask) {
1138+
DeleteObject(info.hbmMask);
1139+
}
1140+
return TRUE;
1141+
}
1142+
11071143
static BOOL
11081144
AdjustIconImagePointers(
11091145
LPICONIMAGE lpImage)
@@ -1123,24 +1159,10 @@ AdjustIconImagePointers(
11231159
lpImage->lpbi = (LPBITMAPINFO) lpImage->lpBits;
11241160

11251161
/*
1126-
* Width - simple enough.
1127-
*/
1128-
1129-
lpImage->Width = lpImage->lpbi->bmiHeader.biWidth;
1130-
1131-
/*
1132-
* Icons are stored in funky format where height is doubled so account for
1133-
* that.
1162+
* Width, height, and number of colors.
11341163
*/
11351164

1136-
lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2;
1137-
1138-
/*
1139-
* How many colors?
1140-
*/
1141-
1142-
lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes
1143-
* lpImage->lpbi->bmiHeader.biBitCount;
1165+
SetSizeAndColorFromHICON(lpImage->hIcon, lpImage);
11441166

11451167
/*
11461168
* XOR bits follow the header and color table.
@@ -1153,7 +1175,7 @@ AdjustIconImagePointers(
11531175
*/
11541176

11551177
lpImage->lpAND = lpImage->lpXOR +
1156-
lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER) lpImage->lpbi);
1178+
lpImage->Height * BytesPerLine((LPBITMAPINFOHEADER) lpImage->lpbi);
11571179
return TRUE;
11581180
}
11591181

@@ -1533,17 +1555,17 @@ ReadIconOrCursorFromFile(
15331555
}
15341556

15351557
/*
1536-
* Set the internal pointers appropriately.
1558+
* Create the icon from the resource, and set the internal pointers appropriately.
15371559
*/
15381560

1561+
lpIR->IconImages[i].hIcon =
1562+
MakeIconOrCursorFromResource(&lpIR->IconImages[i], isIcon);
15391563
if (!AdjustIconImagePointers(&lpIR->IconImages[i])) {
15401564
Tcl_SetObjResult(interp, Tcl_NewStringObj(
15411565
"Error converting to internal format", TCL_INDEX_NONE));
15421566
Tcl_SetErrorCode(interp, "TK", "WM", "ICON", "FORMAT", NULL);
15431567
goto readError;
15441568
}
1545-
lpIR->IconImages[i].hIcon =
1546-
MakeIconOrCursorFromResource(&lpIR->IconImages[i], isIcon);
15471569
}
15481570

15491571
/*

0 commit comments

Comments
 (0)