1 2 #include <apitest.h> 3 4 #include <wingdi.h> 5 #include <winuser.h> 6 7 #include "resource.h" 8 9 // FIXME user32 10 11 void 12 Test_GetIconInfo(BOOL fIcon, DWORD screen_bpp) 13 { 14 HICON hicon; 15 ICONINFO iconinfo, iconinfo2; 16 BITMAP bitmap; 17 18 iconinfo.fIcon = fIcon; 19 iconinfo.xHotspot = 0; 20 iconinfo.yHotspot = 0; 21 iconinfo.hbmMask = NULL; 22 iconinfo.hbmColor = NULL; 23 24 hicon = CreateIconIndirect(&iconinfo); 25 ok(hicon == 0, "should fail\n"); 26 27 iconinfo.hbmMask = CreateBitmap(8, 16, 1, 1, NULL); 28 hicon = CreateIconIndirect(&iconinfo); 29 ok(hicon != 0, "should not fail\n"); 30 31 ok(GetIconInfo(hicon, &iconinfo2), "\n"); 32 ok(iconinfo2.fIcon == iconinfo.fIcon, "\n"); 33 if (fIcon) 34 { 35 ok(iconinfo2.xHotspot == 4, "%ld\n", iconinfo2.xHotspot); 36 ok(iconinfo2.yHotspot == 4, "%ld\n", iconinfo2.yHotspot); 37 } 38 else 39 { 40 ok(iconinfo2.xHotspot == 0, "%ld\n", iconinfo2.xHotspot); 41 ok(iconinfo2.yHotspot == 0, "%ld\n", iconinfo2.yHotspot); 42 } 43 ok(iconinfo2.hbmMask != NULL, "\n"); 44 ok(iconinfo2.hbmMask != iconinfo.hbmMask, "\n"); 45 ok(iconinfo2.hbmColor == NULL, "\n"); 46 DeleteObject(iconinfo2.hbmMask); 47 48 ok(GetIconInfo(hicon, &iconinfo2), "\n"); 49 ok(iconinfo2.fIcon == iconinfo.fIcon, "\n"); 50 if (fIcon) 51 { 52 ok(iconinfo2.xHotspot == 4, "%ld\n", iconinfo2.xHotspot); 53 ok(iconinfo2.yHotspot == 4, "%ld\n", iconinfo2.yHotspot); 54 } 55 else 56 { 57 ok(iconinfo2.xHotspot == 0, "%ld\n", iconinfo2.xHotspot); 58 ok(iconinfo2.yHotspot == 0, "%ld\n", iconinfo2.yHotspot); 59 } 60 ok(iconinfo2.hbmMask != NULL, "\n"); 61 ok(iconinfo2.hbmMask != iconinfo.hbmMask, "\n"); 62 ok(iconinfo2.hbmColor == NULL, "\n"); 63 DeleteObject(iconinfo2.hbmMask); 64 ok(DestroyIcon(hicon), "\n"); 65 66 iconinfo.hbmColor = CreateBitmap(2, 2, 1, 1, NULL); 67 hicon = CreateIconIndirect(&iconinfo); 68 ok(hicon != 0, "should not fail\n"); 69 70 ok(GetIconInfo(hicon, &iconinfo2), "\n"); 71 ok(iconinfo2.fIcon == iconinfo.fIcon, "\n"); 72 if (fIcon) 73 { 74 ok(iconinfo2.xHotspot == 4, "%ld\n", iconinfo2.xHotspot); 75 ok(iconinfo2.yHotspot == 8, "%ld\n", iconinfo2.yHotspot); 76 } 77 else 78 { 79 ok(iconinfo2.xHotspot == 0, "%ld\n", iconinfo2.xHotspot); 80 ok(iconinfo2.yHotspot == 0, "%ld\n", iconinfo2.yHotspot); 81 } 82 ok(iconinfo2.hbmMask != NULL, "\n"); 83 ok(iconinfo2.hbmMask != iconinfo.hbmMask, "\n"); 84 ok(iconinfo2.hbmColor != NULL, "\n"); 85 ok(iconinfo2.hbmColor != iconinfo.hbmColor, "\n"); 86 87 ok(GetObject(iconinfo2.hbmMask, sizeof(bitmap), &bitmap), "GetObject failed\n"); 88 ok(bitmap.bmType == 0, "\n"); 89 ok(bitmap.bmWidth == 8, "\n"); 90 ok(bitmap.bmHeight == 16, "\n"); 91 ok(bitmap.bmWidthBytes == 2, "\n"); 92 ok(bitmap.bmPlanes == 1, "\n"); 93 ok(bitmap.bmBitsPixel == 1, "\n"); 94 ok(bitmap.bmBits == NULL, "\n"); 95 96 ok(GetObject(iconinfo2.hbmColor, sizeof(bitmap), &bitmap), "GetObject failed\n"); 97 ok(bitmap.bmType == 0, "\n"); 98 ok(bitmap.bmWidth == 8, "\n"); 99 ok(bitmap.bmHeight == 16, "\n"); 100 ok(bitmap.bmWidthBytes == 8 * bitmap.bmBitsPixel / 8, "\n"); 101 ok(bitmap.bmPlanes == 1, "\n"); 102 ok(bitmap.bmBitsPixel == screen_bpp, "%d\n", bitmap.bmBitsPixel); 103 ok(bitmap.bmBits == NULL, "\n"); 104 DeleteObject(iconinfo2.hbmMask); 105 DeleteObject(iconinfo2.hbmColor); 106 ok(DestroyIcon(hicon), "\n"); 107 108 DeleteObject(iconinfo.hbmMask); 109 iconinfo.hbmMask = NULL; 110 hicon = CreateIconIndirect(&iconinfo); 111 ok(hicon == 0, "should fail\n"); 112 113 DeleteObject(iconinfo.hbmColor); 114 iconinfo.hbmColor = CreateCompatibleBitmap(GetDC(0), 16, 16); 115 hicon = CreateIconIndirect(&iconinfo); 116 ok(hicon == 0, "should fail\n"); 117 118 iconinfo.hbmMask = CreateCompatibleBitmap(GetDC(0), 8, 16); 119 hicon = CreateIconIndirect(&iconinfo); 120 ok(hicon != 0, "should not fail\n"); 121 122 ok(GetIconInfo(hicon, &iconinfo2), "\n"); 123 124 ok(GetObject(iconinfo2.hbmMask, sizeof(bitmap), &bitmap), "GetObject failed\n"); 125 ok(bitmap.bmType == 0, "\n"); 126 ok(bitmap.bmWidth == 8, "%ld\n", bitmap.bmWidth); 127 ok(bitmap.bmHeight == 16, "%ld\n", bitmap.bmHeight); 128 ok(bitmap.bmWidthBytes == 2, "%ld\n", bitmap.bmWidthBytes); 129 ok(bitmap.bmPlanes == 1, "%d\n", bitmap.bmPlanes); 130 ok(bitmap.bmBitsPixel == 1, "%d\n", bitmap.bmBitsPixel); 131 ok(bitmap.bmBits == NULL, "\n"); 132 133 ok(GetObject(iconinfo2.hbmColor, sizeof(bitmap), &bitmap), "GetObject failed\n"); 134 ok(bitmap.bmType == 0, "\n"); 135 ok(bitmap.bmWidth == 8, "%ld\n", bitmap.bmWidth); 136 ok(bitmap.bmHeight == 16, "%ld\n", bitmap.bmHeight); 137 ok(bitmap.bmWidthBytes == screen_bpp, "%ld\n", bitmap.bmWidthBytes); 138 ok(bitmap.bmPlanes == 1, "%d\n", bitmap.bmPlanes); 139 ok(bitmap.bmBitsPixel == screen_bpp, "%d\n", bitmap.bmBitsPixel); 140 ok(bitmap.bmBits == NULL, "\n"); 141 DeleteObject(iconinfo2.hbmMask); 142 DeleteObject(iconinfo2.hbmColor); 143 ok(DestroyIcon(hicon), "\n"); 144 } 145 146 147 START_TEST(GetIconInfo) 148 { 149 HCURSOR hcursor; 150 ICONINFO iconinfo2; 151 BITMAP bitmap; 152 DWORD data[] = {0, 0, 0, 0, 0, 0}; 153 DWORD bpp, screenbpp, creationbpp; 154 DEVMODEW dm; 155 156 dm.dmSize = sizeof(dm); 157 dm.dmDriverExtra = 0; 158 159 /* Test icons behaviour regarding display settings */ 160 ok(EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &dm), "\n"); 161 screenbpp = dm.dmBitsPerPel; 162 163 trace("Icon default size: %dx%d.\n", GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); 164 trace("Cursor default size: %dx%d.\n", GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); 165 166 trace("Screen bpp: %lu.\n", screenbpp); 167 Test_GetIconInfo(FALSE, screenbpp); 168 Test_GetIconInfo(TRUE, screenbpp); 169 170 hcursor = LoadCursor(GetModuleHandle(NULL), "TESTCURSOR"); 171 ok(hcursor != 0, "should not fail, error %ld\n", GetLastError()); 172 ok(GetIconInfo(hcursor, &iconinfo2), "\n"); 173 ok(iconinfo2.fIcon == 0, "\n"); 174 ok(iconinfo2.xHotspot == 8, "%ld\n", iconinfo2.xHotspot); 175 ok(iconinfo2.yHotspot == 29, "%ld\n", iconinfo2.yHotspot); 176 ok(iconinfo2.hbmMask != NULL, "\n"); 177 ok(iconinfo2.hbmColor != NULL, "\n"); 178 /* Delete objects */ 179 DeleteObject(iconinfo2.hbmColor); 180 DeleteObject(iconinfo2.hbmMask); 181 /* Delete cursor */ 182 DestroyCursor(hcursor); 183 184 /* To sum it up: 185 * There are two criteria when using icons: performance and aesthetics (=alpha channel). 186 * Performance asks for bit parity with the screen display. 187 * Aesthetics needs a 32bpp bitmap. 188 * The behaviour is basically : aesthetics first if already loaded. 189 * ie: if the 32bpp bitmap were already loaded because of previous display settings, always use it. 190 * Otherwise, use the bitmap matching the screen bit depth. 191 */ 192 193 /* if we use LR_SHARED here, and reverse the loop (32->16), then hbmColor.bmBitsPixel is always 32. */ 194 for(creationbpp = 16; creationbpp <=32; creationbpp += 8) 195 { 196 dm.dmBitsPerPel = creationbpp; 197 if(ChangeDisplaySettingsExW(NULL, &dm, NULL, 0, NULL) != DISP_CHANGE_SUCCESSFUL) 198 { 199 skip("Unable to change bpp to %lu.\n", creationbpp); 200 continue; 201 } 202 trace("starting with creationbpp = %lu\n", creationbpp); 203 hcursor = LoadImage(GetModuleHandle(NULL), 204 MAKEINTRESOURCE(IDI_TEST), 205 IMAGE_ICON, 206 0, 207 0, 208 LR_DEFAULTCOLOR); 209 ok(hcursor != 0, "should not fail\n"); 210 211 /* If we reverse the loop here (32->16 bpp), then hbmColor.bmBitsPixel is always 32 */ 212 for(bpp = 16; bpp <=32; bpp += 8) 213 { 214 trace("testing resetting to %lu\n", bpp); 215 dm.dmBitsPerPel = bpp; 216 if(ChangeDisplaySettingsExW(NULL, &dm, NULL, 0, NULL) != DISP_CHANGE_SUCCESSFUL) 217 { 218 skip("Unable to change bpp to %lu.\n", bpp); 219 continue; 220 } 221 ok(GetIconInfo(hcursor, &iconinfo2), "\n"); 222 ok(iconinfo2.fIcon == 1, "\n"); 223 ok(iconinfo2.xHotspot == 24, "%ld\n", iconinfo2.xHotspot); 224 ok(iconinfo2.yHotspot == 24, "%ld\n", iconinfo2.yHotspot); 225 ok(iconinfo2.hbmMask != NULL, "\n"); 226 ok(iconinfo2.hbmColor != NULL, "\n"); 227 228 ok(GetObject(iconinfo2.hbmMask, sizeof(bitmap), &bitmap), "GetObject failed\n"); 229 ok(bitmap.bmType == 0, "\n"); 230 ok(bitmap.bmWidth == 48, "%ld\n", bitmap.bmWidth); 231 ok(bitmap.bmHeight == 48, "\n"); 232 ok(bitmap.bmWidthBytes == 6, "\n"); 233 ok(bitmap.bmPlanes == 1, "\n"); 234 ok(bitmap.bmBitsPixel == 1, "\n"); 235 ok(bitmap.bmBits == NULL, "\n"); 236 237 ok(GetObject(iconinfo2.hbmColor, sizeof(bitmap), &bitmap), "GetObject failed\n"); 238 ok(bitmap.bmType == 0, "\n"); 239 ok(bitmap.bmWidth == 48, "\n"); 240 ok(bitmap.bmHeight == 48, "\n"); 241 ok(bitmap.bmWidthBytes == 48 * bitmap.bmBitsPixel / 8, "\n"); 242 ok(bitmap.bmPlanes == 1, "\n"); 243 ok(bitmap.bmBitsPixel == (creationbpp == 32 ? 32 : bpp), "creationbpp: %lu, bpp: %lu:\n", creationbpp, bpp); 244 ok(bitmap.bmBits == NULL, "\n"); 245 246 /* Delete objects */ 247 DeleteObject(iconinfo2.hbmColor); 248 DeleteObject(iconinfo2.hbmMask); 249 } 250 ok(DestroyIcon(hcursor), "\n"); 251 } 252 /* Restore display settings */ 253 dm.dmBitsPerPel = screenbpp; 254 if(ChangeDisplaySettingsExW(NULL, &dm, NULL, 0, NULL) != DISP_CHANGE_SUCCESSFUL) 255 trace("Unable to go back to previous display settings. Sorry.\n"); 256 257 hcursor = CreateCursor(NULL, 1, 2, 4, 4, data, data); 258 ok(hcursor != 0, "should not fail\n"); 259 ok(GetIconInfo(hcursor, &iconinfo2), "\n"); 260 ok(iconinfo2.fIcon == 0, "\n"); 261 ok(iconinfo2.xHotspot == 1, "%ld\n", iconinfo2.xHotspot); 262 ok(iconinfo2.yHotspot == 2, "%ld\n", iconinfo2.yHotspot); 263 ok(iconinfo2.hbmMask != NULL, "\n"); 264 ok(iconinfo2.hbmColor == NULL, "\n"); 265 266 ok(GetObject(iconinfo2.hbmMask, sizeof(bitmap), &bitmap), "GetObject failed\n"); 267 ok(bitmap.bmType == 0, "\n"); 268 ok(bitmap.bmWidth == 4, "%ld\n", bitmap.bmWidth); 269 ok(bitmap.bmHeight == 8, "%ld\n", bitmap.bmHeight); 270 ok(bitmap.bmWidthBytes == 2, "%ld\n", bitmap.bmWidthBytes); 271 ok(bitmap.bmPlanes == 1, "\n"); 272 ok(bitmap.bmBitsPixel == 1, "\n"); 273 ok(bitmap.bmBits == NULL, "\n"); 274 275 /* Delete objects */ 276 DeleteObject(iconinfo2.hbmColor); 277 DeleteObject(iconinfo2.hbmMask); 278 /* Delete cursor */ 279 DestroyCursor(hcursor); 280 } 281 282 283