1 #include <windows.h> 2 #include <uxtheme.h> 3 #include <stdlib.h> 4 #include <tchar.h> 5 #include "resource.h" 6 7 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 8 9 HICON hico; 10 HBITMAP hbmp; 11 HIMAGELIST himl; 12 POINT scPos; 13 14 HBRUSH hbrNULL; 15 HBRUSH hbrRed; 16 HBRUSH hbrGreen; 17 HBRUSH hbrBlue; 18 HBRUSH hbrCyan; 19 HBRUSH hbrYellow; 20 21 HBRUSH hbrCtlColorStatic; 22 HBRUSH hbrCtlColorBtn; 23 HBRUSH hbrPrintClientClear; 24 HBRUSH hbrErase; 25 26 BOOL bSkipErase; 27 BOOL bSkipPaint; 28 29 static void RegisterMyClass(HINSTANCE hInst) 30 { 31 WNDCLASSEXW wcex; 32 33 wcex.cbSize = sizeof(WNDCLASSEX); 34 35 wcex.style = CS_HREDRAW | CS_VREDRAW; 36 wcex.lpfnWndProc = WndProc; 37 wcex.cbClsExtra = 0; 38 wcex.cbWndExtra = 0; 39 wcex.hInstance = hInst; 40 wcex.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_WIN32PROJECT1)); 41 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 42 wcex.hbrBackground = NULL; 43 wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_MENU); 44 wcex.lpszClassName = L"ButtonTests"; 45 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 46 47 RegisterClassExW(&wcex); 48 } 49 50 #define TOP_MARGIN 50 51 #define LEFT_MARGIN 160 52 #define X_GAP 10 53 #define Y_GAP 10 54 #define Y_HEIGHT 40 55 #define X_WIDTH 150 56 57 static HWND CreateWnd(HWND hWnd, LPCWSTR Class, LPCWSTR Text, LONG style, int i, int j) 58 { 59 return CreateWindowW(Class, 60 Text, 61 style | WS_CHILD | WS_VISIBLE, 62 LEFT_MARGIN + (X_GAP + X_WIDTH) * i, 63 TOP_MARGIN + ((Y_GAP + Y_HEIGHT) *j), 64 X_WIDTH, 65 Y_HEIGHT, 66 hWnd, NULL, NULL, NULL); 67 } 68 69 static HWND CreateBtn(HWND hWnd, LPCWSTR Text, LONG style, int i, int j) 70 { 71 WCHAR buffer[100]; 72 SIZE s; 73 74 HWND ret = CreateWnd(hWnd, L"Button", Text, style, i, j); 75 if (GetWindowLongW(ret, GWL_STYLE) != (style | WS_CHILD | WS_VISIBLE)) 76 { 77 swprintf(buffer, L"expected 0x%x got 0x%x", (style | WS_CHILD | WS_VISIBLE), GetWindowLongW(ret, GWL_STYLE)); 78 MessageBox(0, buffer, L"error", MB_OK); 79 } 80 81 if (SendMessageW(ret, BCM_GETIDEALSIZE, 0, (LPARAM)&s)) 82 { 83 swprintf(buffer, L"%s (%d, %d)", Text, s.cx, s.cy); 84 SendMessageW(ret, WM_SETTEXT, 0, (LPARAM)buffer); 85 } 86 return ret; 87 } 88 89 static void CreateButtonSet(HWND hwndParent, HWND *ahwnd, int i, int j, DWORD style) 90 { 91 ahwnd[0] = CreateBtn(hwndParent, L"TestButton", style, i, j + 0); 92 ahwnd[1] = CreateBtn(hwndParent, L"TestButton1", style, i, j + 1); 93 ahwnd[2] = CreateBtn(hwndParent, L"TestButton2", style, i, j + 2); 94 ahwnd[3] = CreateBtn(hwndParent, L"TestButton3", style | BS_BITMAP, i, j + 3); 95 ahwnd[4] = CreateBtn(hwndParent, L"TestButton4", style | BS_ICON, i, j + 4); 96 97 SendMessageW(ahwnd[1], BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp); 98 SendMessageW(ahwnd[2], BM_SETIMAGE, IMAGE_ICON, (LPARAM)hico); 99 100 SendMessageW(ahwnd[3], BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp); 101 SendMessageW(ahwnd[4], BM_SETIMAGE, IMAGE_ICON, (LPARAM)hico); 102 } 103 104 int WINAPI wWinMain(_In_ HINSTANCE hInstance, 105 _In_opt_ HINSTANCE hPrevInstance, 106 _In_ LPWSTR lpCmdLine, 107 _In_ int nCmdShow) 108 { 109 HWND hwnd[200]; 110 HANDLE hActCtx; 111 ULONG_PTR cookie; 112 BOOL bActivated; 113 114 ACTCTXW actctx = { sizeof(actctx) }; 115 actctx.hModule = hInstance; 116 actctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID| ACTCTX_FLAG_HMODULE_VALID; 117 actctx.lpResourceName = MAKEINTRESOURCEW(500); 118 hActCtx = CreateActCtxW(&actctx); 119 120 hico = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_WIN32PROJECT1)); 121 hbmp = LoadBitmapW(hInstance, MAKEINTRESOURCEW(IDB_BITMAP1)); 122 123 scPos.x = 0; 124 scPos.y = 0; 125 126 hbrNULL = (HBRUSH)GetStockObject (NULL_BRUSH); 127 hbrRed = CreateSolidBrush(0x00000FF); 128 hbrGreen = CreateSolidBrush(0x0000FF00); 129 hbrBlue = CreateSolidBrush(0x00FF0000); 130 hbrCyan = CreateSolidBrush(0x00FFFF00); 131 hbrYellow = CreateSolidBrush(0x0000FFFF); 132 133 hbrCtlColorStatic = hbrRed; 134 hbrCtlColorBtn = hbrCyan; 135 hbrPrintClientClear = hbrYellow; 136 hbrErase = hbrGreen; 137 138 bSkipErase = FALSE; 139 bSkipPaint = FALSE; 140 141 RegisterMyClass(hInstance); 142 143 HWND hWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"ButtonTests", L"Button tests", WS_OVERLAPPEDWINDOW| WS_HSCROLL| WS_VSCROLL, 144 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 145 146 CreateWnd(hWnd, L"Static", L"no images", 0, -1, 0); 147 CreateWnd(hWnd, L"Static", L"with BM_SETIMAGE", 0, -1, 1); 148 CreateWnd(hWnd, L"Static", L"with BM_SETIMAGE", 0, -1, 2); 149 CreateWnd(hWnd, L"Static", L"with BM_SETIMAGE and BS_BITMAP", 0, -1, 3); 150 CreateWnd(hWnd, L"Static", L"with BM_SETIMAGE and BS_ICON", 0, -1, 4); 151 152 CreateWnd(hWnd, L"Static", L"Button V5", 0, 0, -1); 153 CreateButtonSet(hWnd, &hwnd[0], 0, 0, BS_PUSHBUTTON); 154 CreateButtonSet(hWnd, &hwnd[5], 1, 0, BS_DEFPUSHBUTTON); 155 CreateButtonSet(hWnd, &hwnd[10], 0, 5, BS_PUSHBUTTON|WS_DISABLED); 156 CreateButtonSet(hWnd, &hwnd[15], 1, 5, BS_GROUPBOX); 157 CreateButtonSet(hWnd, &hwnd[20], 0, 10, BS_CHECKBOX); 158 CreateButtonSet(hWnd, &hwnd[25], 1, 10, BS_RADIOBUTTON); 159 160 bActivated = ActivateActCtx(hActCtx, &cookie); 161 LoadLibraryW(L"comctl32.dll"); 162 163 himl = ImageList_LoadImageW(hInstance, MAKEINTRESOURCEW(IDB_BITMAP2), 16, 0, CLR_DEFAULT, IMAGE_BITMAP, LR_CREATEDIBSECTION); 164 BUTTON_IMAGELIST btniml = {himl, {1,1,1,1}, BUTTON_IMAGELIST_ALIGN_LEFT}; 165 166 CreateWnd(hWnd, L"Static", L"Button V6 without themes", 0, 2, -1); 167 CreateButtonSet(hWnd, &hwnd[30], 2, 0, BS_PUSHBUTTON); 168 CreateButtonSet(hWnd, &hwnd[35], 3, 0, BS_DEFPUSHBUTTON); 169 CreateButtonSet(hWnd, &hwnd[40], 2, 5, BS_PUSHBUTTON|WS_DISABLED); 170 CreateButtonSet(hWnd, &hwnd[55], 3, 5, BS_GROUPBOX); 171 CreateButtonSet(hWnd, &hwnd[50], 2, 10, BS_CHECKBOX); 172 CreateButtonSet(hWnd, &hwnd[55], 3, 10, BS_RADIOBUTTON); 173 174 CreateWnd(hWnd, L"Static", L"Button V6 with imagelist and no themes", 0, 4, -1); 175 CreateButtonSet(hWnd, &hwnd[60], 4, 0, BS_PUSHBUTTON); 176 CreateButtonSet(hWnd, &hwnd[65], 5, 0, BS_DEFPUSHBUTTON); 177 CreateButtonSet(hWnd, &hwnd[70], 4, 5, BS_PUSHBUTTON|WS_DISABLED); 178 CreateButtonSet(hWnd, &hwnd[75], 5, 5, BS_GROUPBOX); 179 CreateButtonSet(hWnd, &hwnd[80], 4, 10, BS_CHECKBOX); 180 CreateButtonSet(hWnd, &hwnd[85], 5, 10, BS_RADIOBUTTON); 181 182 for (int i = 30; i < 90; i++) 183 SetWindowTheme(hwnd[i], L"", L""); 184 185 for (int i = 60; i< 90; i++) 186 SendMessageW(hwnd[i], BCM_SETIMAGELIST, 0, (LPARAM)&btniml); 187 188 CreateWnd(hWnd, L"Static", L"Button V6 with themes and imagelist", 0, 6, -1); 189 CreateButtonSet(hWnd, &hwnd[120], 6, 0, BS_PUSHBUTTON); 190 CreateButtonSet(hWnd, &hwnd[125], 7, 0, BS_DEFPUSHBUTTON); 191 CreateButtonSet(hWnd, &hwnd[130], 6, 5, BS_PUSHBUTTON|WS_DISABLED); 192 CreateButtonSet(hWnd, &hwnd[135], 7, 5, BS_GROUPBOX); 193 CreateButtonSet(hWnd, &hwnd[140], 6, 10, BS_CHECKBOX); 194 CreateButtonSet(hWnd, &hwnd[145], 7, 10, BS_RADIOBUTTON); 195 196 CreateWnd(hWnd, L"Static", L"Button V6 with themes", 0, 8, -1); 197 CreateButtonSet(hWnd, &hwnd[90], 8, 0, BS_PUSHBUTTON); 198 CreateButtonSet(hWnd, &hwnd[95], 9, 0, BS_DEFPUSHBUTTON); 199 CreateButtonSet(hWnd, &hwnd[100], 8, 5, BS_PUSHBUTTON|WS_DISABLED); 200 CreateButtonSet(hWnd, &hwnd[105], 9, 5, BS_GROUPBOX); 201 CreateButtonSet(hWnd, &hwnd[110], 8, 10, BS_CHECKBOX); 202 CreateButtonSet(hWnd, &hwnd[115], 9, 10, BS_RADIOBUTTON); 203 204 for (int i = 120; i< 150; i++) 205 SendMessageW(hwnd[i], BCM_SETIMAGELIST, 0, (LPARAM)&btniml); 206 207 if (bActivated) DeactivateActCtx(0, cookie); 208 209 SCROLLINFO vsi = {sizeof(SCROLLINFO), SIF_ALL, 0, 2 * TOP_MARGIN + 10 * (Y_GAP + Y_HEIGHT), Y_HEIGHT, 0, 0}; 210 SCROLLINFO hsi = {sizeof(SCROLLINFO), SIF_ALL, 0, 2 * LEFT_MARGIN + 13 * (X_GAP + X_WIDTH), X_WIDTH, 0, 0}; 211 212 SetScrollInfo(hWnd, SB_HORZ, &hsi, FALSE); 213 SetScrollInfo(hWnd, SB_VERT, &vsi, FALSE); 214 215 ShowScrollBar(hWnd, SB_HORZ, TRUE); 216 ShowScrollBar(hWnd, SB_VERT, TRUE); 217 218 ShowWindow(hWnd, nCmdShow); 219 UpdateWindow(hWnd); 220 221 MSG msg; 222 while (GetMessage(&msg, NULL, 0, 0)) 223 { 224 TranslateMessage(&msg); 225 DispatchMessage(&msg); 226 } 227 228 return (int) msg.wParam; 229 } 230 231 static VOID 232 OnScroll(HWND hwnd, INT nBar, WORD sbCode) 233 { 234 RECT rect; 235 236 SCROLLINFO sInfo; 237 INT oldPos, Maximum; 238 PLONG pOriginXY; 239 240 //ASSERT(nBar == SB_HORZ || nBar == SB_VERT); 241 242 GetClientRect(hwnd, &rect); 243 244 if (nBar == SB_HORZ) 245 { 246 Maximum =1000;//pData->cxMin - (rect.right-rect.left) /* pData->cxOld */; 247 pOriginXY = &scPos.x; 248 } 249 else // if (nBar == SB_VERT) 250 { 251 Maximum = 1000;//pData->cyMin - (rect.bottom-rect.top) /* pData->cyOld */; 252 pOriginXY = &scPos.y; 253 } 254 255 /* Set scrollbar sizes */ 256 sInfo.cbSize = sizeof(sInfo); 257 sInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS; 258 259 if (!GetScrollInfo(hwnd, nBar, &sInfo)) 260 return; 261 262 oldPos = sInfo.nPos; 263 264 switch (sbCode) 265 { 266 case SB_LINEUP: // SB_LINELEFT: 267 sInfo.nPos--; 268 break; 269 270 case SB_LINEDOWN: // SB_LINERIGHT: 271 sInfo.nPos++; 272 break; 273 274 case SB_PAGEUP: // SB_PAGELEFT: 275 sInfo.nPos -= sInfo.nPage; 276 break; 277 278 case SB_PAGEDOWN: // SB_PAGERIGHT: 279 sInfo.nPos += sInfo.nPage; 280 break; 281 282 case SB_THUMBTRACK: 283 sInfo.nPos = sInfo.nTrackPos; 284 break; 285 286 case SB_THUMBPOSITION: 287 sInfo.nPos = sInfo.nTrackPos; 288 break; 289 290 case SB_TOP: // SB_LEFT: 291 sInfo.nPos = sInfo.nMin; 292 break; 293 294 case SB_BOTTOM: // SB_RIGHT: 295 sInfo.nPos = sInfo.nMax; 296 break; 297 298 default: 299 break; 300 } 301 302 sInfo.nPos = min(max(sInfo.nPos, 0), Maximum); 303 304 if (oldPos != sInfo.nPos) 305 { 306 POINT scOldPos = scPos; 307 308 /* We now modify scPos */ 309 *pOriginXY = sInfo.nPos; 310 311 ScrollWindowEx(hwnd, 312 (scOldPos.x - scPos.x), 313 (scOldPos.y - scPos.y), 314 NULL, 315 NULL, 316 NULL, 317 NULL, 318 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN); 319 320 sInfo.fMask = SIF_POS; 321 SetScrollInfo(hwnd, nBar, &sInfo, TRUE); 322 } 323 } 324 325 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 326 { 327 RECT rc = {0,0,5000,5000}; 328 switch (message) 329 { 330 case WM_DESTROY: 331 PostQuitMessage(0); 332 break; 333 case WM_CTLCOLORSTATIC: 334 return (LRESULT)hbrCtlColorStatic; 335 case WM_CTLCOLORBTN: 336 return (LRESULT)hbrCtlColorBtn; 337 case WM_ERASEBKGND: 338 FillRect((HDC)wParam, &rc, hbrErase); 339 return TRUE; 340 case WM_PRINTCLIENT: 341 FillRect((HDC)wParam, &rc, hbrPrintClientClear); 342 break; 343 case WM_HSCROLL: 344 OnScroll(hWnd, SB_HORZ, LOWORD(wParam)); 345 break; 346 case WM_VSCROLL: 347 OnScroll(hWnd, SB_VERT, LOWORD(wParam)); 348 break; 349 case WM_DRAWITEM : 350 { 351 DRAWITEMSTRUCT* di = (DRAWITEMSTRUCT*)lParam; 352 INT oldBkMode; 353 INT state = (di->itemState == ODS_SELECTED) ? DFCS_BUTTONPUSH|DFCS_PUSHED : DFCS_BUTTONPUSH; 354 DrawFrameControl( di->hDC, &di->rcItem, DFC_BUTTON, state ); 355 oldBkMode = SetBkMode(di->hDC, TRANSPARENT); 356 DrawTextW(di->hDC, L"Ownder drawn text", -1, &di->rcItem, DT_VCENTER | DT_CENTER); 357 SetBkMode(di->hDC, oldBkMode); 358 break; 359 } 360 case WM_NOTIFY: 361 { 362 NMHDR* phdr = (NMHDR*)lParam; 363 if (phdr->code == NM_CUSTOMDRAW) 364 { 365 LPNMCUSTOMDRAW lpNMCustomDraw = (LPNMCUSTOMDRAW) lParam; 366 if (lpNMCustomDraw->dwDrawStage == CDDS_PREERASE && bSkipErase) 367 return CDRF_SKIPDEFAULT; 368 else if (lpNMCustomDraw->dwDrawStage == CDDS_PREPAINT && bSkipPaint) 369 return CDRF_SKIPDEFAULT; 370 return CDRF_DODEFAULT; 371 } 372 } 373 case WM_COMMAND: 374 { 375 UINT id = LOWORD(wParam); 376 switch(id) 377 { 378 case IDM_NULL_WIN: hbrErase = hbrNULL; break; 379 case IDM_RED_WIN: hbrErase = hbrRed; break; 380 case IDM_GREEN_WIN: hbrErase = hbrGreen; break; 381 case IDM_BLUE_WIN: hbrErase = hbrBlue; break; 382 case IDM_YELLOW_WIN: hbrErase = hbrYellow; break; 383 case IDM_CYAN_WIN: hbrErase = hbrCyan; break; 384 385 case IDM_NULL_STATIC: hbrCtlColorStatic = hbrNULL; break; 386 case IDM_RED_STATIC: hbrCtlColorStatic = hbrRed; break; 387 case IDM_GREEN_STATIC: hbrCtlColorStatic = hbrGreen; break; 388 case IDM_BLUE_STATIC: hbrCtlColorStatic = hbrBlue; break; 389 case IDM_YELLOW_STATIC: hbrCtlColorStatic = hbrYellow; break; 390 case IDM_CYAN_STATIC: hbrCtlColorStatic = hbrCyan; break; 391 392 case IDM_NULL_BTN: hbrCtlColorBtn = hbrNULL; break; 393 case IDM_RED_BTN: hbrCtlColorBtn = hbrRed; break; 394 case IDM_GREEN_BTN: hbrCtlColorBtn = hbrGreen; break; 395 case IDM_BLUE_BTN: hbrCtlColorBtn = hbrBlue; break; 396 case IDM_YELLOW_BTN: hbrCtlColorBtn = hbrYellow; break; 397 case IDM_CYAN_BTN: hbrCtlColorBtn = hbrCyan; break; 398 399 case IDM_NULL_PRINTCLNT: hbrPrintClientClear = hbrNULL; break; 400 case IDM_RED_PRINTCLNT: hbrPrintClientClear = hbrRed; break; 401 case IDM_GREEN_PRINTCLNT: hbrPrintClientClear = hbrGreen; break; 402 case IDM_BLUE_PRINTCLNT: hbrPrintClientClear = hbrBlue; break; 403 case IDM_YELLOW_PRINTCLNT: hbrPrintClientClear = hbrYellow; break; 404 case IDM_CYAN_PRINTCLNT: hbrPrintClientClear = hbrCyan; break; 405 406 case IDM_SKIP_ERASE: bSkipErase = !bSkipErase; break; 407 case IDM_SKIP_PAINT: bSkipPaint = !bSkipPaint; break; 408 default: 409 return 0; 410 } 411 412 InvalidateRect(hWnd, NULL, TRUE); 413 break; 414 } 415 default: 416 return DefWindowProc(hWnd, message, wParam, lParam); 417 } 418 return 0; 419 } 420