=============================== PBUTTEST.CPP =============================== // Windows Picture Button Control Test Program #define OEMRESOURCE 1 #include LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static struct { long number; char *name; } OBM[] = { {OBM_CLOSE, "OBM_CLOSE"}, {OBM_UPARROW, "OBM_UPARROW"}, {OBM_DNARROW, "OBM_DNARROW"}, {OBM_RGARROW, "OBM_RGARROW"}, {OBM_LFARROW, "OBM_LFARROW"}, {OBM_REDUCE, "OBM_REDUCE"}, {OBM_ZOOM, "OBM_ZOOM"}, {OBM_RESTORE, "OBM_RESTORE"}, {OBM_REDUCED, "OBM_REDUCED"}, {OBM_ZOOMD, "OBM_ZOOMD"}, {OBM_RESTORED, "OBM_RESTORED"}, {OBM_UPARROWD, "OBM_UPARROWD"}, {OBM_DNARROWD, "OBM_DNARROWD"}, {OBM_RGARROWD, "OBM_RGARROWD"}, {OBM_LFARROWD, "OBM_LFARROWD"}, {OBM_MNARROW, "OBM_MNARROW"}, {OBM_COMBO, "OBM_COMBO"}, {OBM_UPARROWI, "OBM_UPARROWI"}, {OBM_DNARROWI, "OBM_DNARROWI"}, {OBM_RGARROWI, "OBM_RGARROWI"}, {OBM_LFARROWI, "OBM_LFARROWI"}, {OBM_OLD_CLOSE, "OBM_OLD_CLOSE"}, {OBM_SIZE, "OBM_SIZE"}, {OBM_OLD_UPARROW, "OBM_OLD_UPARROW"}, {OBM_OLD_DNARROW, "OBM_OLD_DNARROW"}, {OBM_OLD_RGARROW, "OBM_OLD_RGARROW"}, {OBM_OLD_LFARROW, "OBM_OLD_LFARROW"}, {OBM_BTSIZE, "OBM_BTSIZE"}, {OBM_CHECK, "OBM_CHECK"}, {OBM_CHECKBOXES, "OBM_CHECKBOXES"}, {OBM_BTNCORNERS, "OBM_BTNCORNERS"}, {OBM_OLD_REDUCE, "OBM_OLD_REDUCE"}, {OBM_OLD_ZOOM, "OBM_OLD_ZOOM"}, {OBM_OLD_RESTORE, "OBM_OLD_RESTORE",} }; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: return 0; case WM_COMMAND: switch((WORD) wParam) { case 101: DestroyWindow(hwnd); return 0; case 102: { static unsigned i; HBITMAP bitmap = LoadBitmap(NULL, (const char far *) OBM[i].number); #ifdef WIN32 SendDlgItemMessage(hwnd, 101, BM_SETSTYLE, (WPARAM) bitmap, (LPARAM) bitmap); #else SendDlgItemMessage(hwnd, 101, BM_SETSTYLE, 0, MAKELPARAM(bitmap, bitmap)); #endif SetDlgItemText(hwnd, 106, OBM[i].name); if (++i == sizeof(OBM)/sizeof(OBM[0])) i = 0; return 0; } case 105: { static BOOL enabled = TRUE; enabled = !enabled; EnableWindow(GetDlgItem(hwnd, 104), enabled); return 0; } } break; case WM_CLOSE: DestroyWindow(hwnd); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefDlgProc (hwnd, message, wParam, lParam); } #pragma argsused int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { HWND hwnd; MSG msg; if (!hPrevInstance) { WNDCLASS wndclass; wndclass.style = 0; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = DLGWINDOWEXTRA; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "PBUTTONTEST"; RegisterClass (&wndclass); } hwnd = CreateDialog(hInstance, "PBUTTONTEST", 0, NULL); SetFocus(GetDlgItem(hwnd, 102)); SendDlgItemMessage(hwnd, 101, BM_SETSTATE, (WPARAM) GetDlgItem(hwnd, 107), (LPARAM)(char far *) "Terminate test"); SendDlgItemMessage(hwnd, 102, BM_SETSTATE, (WPARAM) GetDlgItem(hwnd, 107), (LPARAM)(char far *) "Show OBM bitmaps"); SendDlgItemMessage(hwnd, 103, BM_SETSTATE, (WPARAM) GetDlgItem(hwnd, 107), (LPARAM)(char far *) "Has no tabstop"); SendDlgItemMessage(hwnd, 104, BM_SETSTATE, (WPARAM) GetDlgItem(hwnd, 107), (LPARAM)(char far *) "Enabled or disabled by button 5"); SendDlgItemMessage(hwnd, 105, BM_SETSTATE, (WPARAM) GetDlgItem(hwnd, 107), (LPARAM)(char far *) "Enable or disable button 4"); ShowWindow(hwnd, nCmdShow == SW_SHOWMAXIMIZED ? SW_SHOW : nCmdShow); UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) if (!IsDialogMessage (hwnd, &msg)) DispatchMessage (&msg); return msg.wParam; } =============================== PBUTTEST.RC =============================== PBUTTONTEST DIALOG 29, 69, 264, 70 STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CLASS "PBUTTONTEST" CAPTION "Picture Button Test Program" FONT 8, "MS Sans Serif" { CONTROL "NONEXISTENT", 101, "PICTUREBUTTON", 2 | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 18, 12, 60, 36 CONTROL "", 106, STATIC, WS_CHILD | WS_VISIBLE | WS_BORDER | SS_LEFT, 12, 54, 90, 10 CONTROL "CHECKMARK", 102, "PICTUREBUTTON", 2 | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 90, 21, 27, 21 CONTROL "CHECKMARK", 103, "PICTUREBUTTON", 0 | WS_CHILD | WS_VISIBLE, 132, 15, 20, 32 CONTROL "SAFE", 104, "PICTUREBUTTON", 2 | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 165, 18, 33, 27 CONTROL "SAFE", 105, "PICTUREBUTTON", 2 | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 210, 12, 42, 36 CONTROL "", 107, STATIC, WS_CHILD | WS_VISIBLE | WS_BORDER | SS_CENTER, 116, 53, 138, 10 } CHECKMARK BITMAP { '42 4D C6 00 00 00 00 00 00 00 76 00 00 00 28 00' '00 00 0A 00 00 00 0A 00 00 00 01 00 04 00 00 00' '00 00 50 00 00 00 00 00 00 00 00 00 00 00 00 00' '00 00 10 00 00 00 00 00 00 00 00 00 80 00 00 80' '00 00 00 80 80 00 80 00 00 00 80 00 80 00 80 80' '00 00 80 80 80 00 C0 C0 C0 00 00 00 FF 00 00 FF' '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' '00 00 FF FF FF 00 88 81 88 88 88 00 00 00 88 11' '18 88 88 00 00 00 81 11 11 88 88 00 00 00 11 18' '81 88 88 00 00 00 11 88 81 18 88 00 00 00 88 88' '88 18 88 00 10 11 88 88 88 11 88 00 14 14 88 88' '88 81 88 00 14 14 88 88 88 81 18 00 04 05 88 88' '88 88 18 00 00 41' } CHECKMARKX BITMAP { '42 4D C6 00 00 00 00 00 00 00 76 00 00 00 28 00' '00 00 0A 00 00 00 0A 00 00 00 01 00 04 00 00 00' '00 00 50 00 00 00 00 00 00 00 00 00 00 00 00 00' '00 00 10 00 00 00 00 00 00 00 00 00 80 00 00 80' '00 00 00 80 80 00 80 00 00 00 80 00 80 00 80 80' '00 00 80 80 80 00 C0 C0 C0 00 00 00 FF 00 00 FF' '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' '00 00 FF FF FF 00 88 80 88 88 88 00 00 00 88 88' '88 88 88 00 00 00 88 08 08 88 88 00 00 00 80 88' '80 88 88 00 00 00 88 88 88 88 88 00 00 00 08 88' '88 08 88 00 10 11 88 88 88 88 88 00 14 14 88 88' '88 80 88 00 14 14 88 88 88 88 08 00 04 05 88 88' '88 88 88 00 00 41' } SAFEX BITMAP BEGIN '42 4D BE 00 00 00 00 00 00 00 3E 00 00 00 28 00' '00 00 20 00 00 00 20 00 00 00 01 00 01 00 00 00' '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' '00 00 00 00 00 00 00 00 00 00 FF FF FF 00 E3 FF' 'FC 7F D1 FF FA 3F C0 00 00 3F BF FF FF BF 7F FF' 'FF C7 7F FF FF C3 78 00 03 D3 77 FF FD CB 63 FF' 'FD D5 6B F0 FD C9 6B EF 7D D5 6B D1 BD C9 63 CC' 'BD D5 77 CC BD C9 77 D1 BD D5 77 EF 7D C9 77 F0' 'FD D5 63 FF FD C9 6B E0 0D D5 6B DF F5 C9 6B E0' '35 D5 63 FF CD C9 77 FF FD D5 78 00 03 C9 7F FF' 'FF D5 7F FF FF C9 BF FF FF 95 C0 00 00 29 EF FF' 'FF D5 F7 FF FF E9 FB FF FF F3 FC 00 00 07' END SAFE BITMAP BEGIN '42 4D 76 02 00 00 00 00 00 00 76 00 00 00 28 00' '00 00 20 00 00 00 20 00 00 00 01 00 04 00 00 00' '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' '00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 80' '00 00 00 80 80 00 80 00 00 00 80 00 80 00 80 80' '00 00 80 80 80 00 C0 C0 C0 00 00 00 FF 00 00 FF' '00 00 00 FF FF 00 FF 00 00 00 FF 00 FF 00 FF FF' '00 00 FF FF FF 00 88 80 00 88 88 88 88 88 88 88' '88 00 08 88 88 88 88 0F 77 08 88 88 88 88 88 88' '80 F7 70 88 88 88 88 00 00 00 00 00 00 00 00 00' '00 00 00 88 88 88 80 77 77 77 77 77 77 77 77 77' '77 77 70 88 88 88 0F 78 88 88 88 88 88 88 88 88' '88 88 77 00 08 88 0F 88 88 88 88 88 88 88 88 88' '88 88 87 70 70 88 0F 88 80 00 00 00 00 00 00 00' '00 88 88 07 00 88 0F 88 07 77 77 77 77 77 77 77' '77 08 88 07 70 88 0F 80 00 78 88 88 87 77 78 88' '87 08 88 07 77 08 0F 87 80 78 88 88 00 00 77 88' '87 08 88 07 77 08 0F 87 80 78 88 80 FF FF 07 78' '87 08 88 07 77 08 0F 87 80 78 88 0F 00 0F F0 78' '87 08 88 07 77 08 0F 87 70 88 88 00 DD 00 F0 78' '87 08 88 07 77 08 0F 88 0F 88 88 00 FD 00 F0 78' '87 08 88 07 77 08 0F 88 0F 88 88 0F 00 0F F0 88' '87 08 88 07 77 08 0F 88 0F 88 88 80 FF FF 08 88' '87 08 88 07 77 08 0F 88 07 78 88 88 00 00 88 88' '87 08 88 07 77 08 0F 80 00 78 88 88 77 77 77 77' '77 08 88 07 77 08 0F 87 80 78 88 80 00 00 00 00' '77 08 88 07 77 08 0F 87 80 78 88 0E EE EE EE 66' '07 08 88 07 77 08 0F 87 80 78 88 80 00 00 00 E6' '07 08 88 07 77 08 0F 87 70 88 88 88 88 88 88 00' '87 08 88 07 77 08 0F 88 0F FF FF FF FF FF FF FF' 'F7 08 88 07 77 08 0F 88 80 00 00 00 00 00 00 00' '00 88 88 07 77 08 0F 88 88 88 88 88 88 88 88 88' '88 88 88 07 77 08 0F F8 88 88 88 88 88 88 88 88' '88 88 87 77 77 08 80 FF 88 88 88 88 88 88 88 88' '88 88 F7 87 77 08 88 0F FF FF FF FF FF FF FF FF' 'FF FF 78 78 77 08 88 80 88 88 88 88 88 88 88 88' '88 88 87 87 87 08 88 88 08 88 88 88 88 88 88 88' '88 88 88 78 78 08 88 88 80 88 88 88 88 88 88 88' '88 88 88 87 80 88 88 88 88 00 00 00 00 00 00 00' '00 00 00 00 08 88' END =============================== PBUTTON.CPP =============================== // Windows Picture Button #include const unsigned MAX_NAME_LENGTH = 31; const unsigned FOCUS_BORDER_WIDTH = 2; LRESULT CALLBACK PictureButtonProc(HWND, UINT, WPARAM, LPARAM); /*----------------------------------------------------------------------------- This function registers the PICTUREBUTTON class. It is called automatically when the program starts up. The external variables _hPrev and _hInstance duplicate the arguments hPrevInstance and hInstance, which are passed to WinMain(). If the startup code does not supply these external variables, you must pass the arguments to this function and call it explicitly before invoking any PICTUREBUTTON control. -----------------------------------------------------------------------------*/ extern HINSTANCE _hInstance; #ifndef WIN32 extern HINSTANCE _hPrev; #endif static void register_picture_button(void) { #ifndef WIN32 if (!_hPrev) #endif { WNDCLASS w; w.cbClsExtra = 0; w.cbWndExtra = sizeof(HGLOBAL); w.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH); w.hCursor = LoadCursor(NULL, IDC_ARROW); w.hIcon = NULL; w.hInstance = _hInstance; w.lpfnWndProc = PictureButtonProc; w.lpszClassName = "PICTUREBUTTON"; w.lpszMenuName = NULL; w.style = 0; RegisterClass(&w); } } #pragma startup register_picture_button struct PICTUREBUTTON { BOOL disabled : 1; BOOL focus : 1; BOOL depressed : 1; BOOL captured : 1; BOOL tabstop : 1; int unused : 11; int height; int width; HBITMAP picture, disabled_picture; HWND status_bar; char far *status_message; }; #ifdef WIN32 inline void MoveTo(HDC dc, int x, int y) { MoveToEx(dc, x, y, NULL); } #define GetWindowHandle GetWindowLong #define SetWindowHandle SetWindowLong #define GWH_HINSTANCE GWL_HINSTANCE #define HANDLE_WORD DWORD inline void PostClickedMessage(HWND handle) { PostMessage(GetParent(handle), WM_COMMAND, MAKELONG((WORD) GetMenu(handle), BN_CLICKED), (LPARAM) handle); } #else #define GetWindowHandle GetWindowWord #define SetWindowHandle SetWindowWord #define GWH_HINSTANCE GWW_HINSTANCE #define HANDLE_WORD WORD inline void PostClickedMessage(HWND handle) { PostMessage(GetParent(handle), WM_COMMAND, GetMenu(handle), MAKELONG(handle, BN_CLICKED)); } #endif /*----------------------------------------------------------------------------- This function receives all messages directed to the control. -----------------------------------------------------------------------------*/ LRESULT CALLBACK PictureButtonProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) { PICTUREBUTTON far *p; HGLOBAL hp = (HGLOBAL) GetWindowHandle(handle, 0); if (hp != NULL) p = (PICTUREBUTTON far *) GlobalLock(hp); switch (message) { case WM_CREATE: { int width = ((CREATESTRUCT far *) lParam)->cx; int height = ((CREATESTRUCT far *) lParam)->cy; hp = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(PICTUREBUTTON)); if (hp == NULL) return -1L; p = (PICTUREBUTTON far *) GlobalLock(hp); p->height = height; p->width = width; if (((CREATESTRUCT far *) lParam)->style & WS_DISABLED) p->disabled = TRUE; if (((CREATESTRUCT far *) lParam)->style & WS_TABSTOP) p->tabstop = TRUE; char name[MAX_NAME_LENGTH + 2]; { int i, c; for (i = 0; i < sizeof(name) - 2 && (c = ((CREATESTRUCT far *) lParam)->lpszName[i]) != 0; i++) { name[i] = c; } name[i] = 0; } p->picture = LoadBitmap((HINSTANCE) GetWindowHandle(handle, GWH_HINSTANCE), name); lstrcat(name, "X"); p->disabled_picture = LoadBitmap((HINSTANCE) GetWindowHandle(handle, GWH_HINSTANCE), name); SetWindowHandle(handle, 0, (HANDLE_WORD) hp); GlobalUnlock(hp); return 0; } case BM_SETSTYLE: if (p->picture != NULL) DeleteObject(p->picture); if (p->disabled_picture != NULL && p->disabled_picture != p->picture) DeleteObject(p->disabled_picture); #ifdef WIN32 p->picture = (HBITMAP) wParam; p->disabled_picture = (HBITMAP) lParam; #else p->picture = (HBITMAP) LOWORD(lParam); p->disabled_picture = (HBITMAP) HIWORD(lParam); #endif InvalidateRect(handle, NULL, TRUE); GlobalUnlock(hp); return 0; case BM_SETSTATE: p->status_bar = (HWND) wParam; p->status_message = (char far *) lParam; GlobalUnlock(hp); return 0; case WM_PAINT: { PAINTSTRUCT paint; HDC dc = BeginPaint(handle, &paint); int height = p->height; int width = p->width; HPEN old_pen = SelectObject(dc, GetStockObject(BLACK_PEN)); HBRUSH old_brush = SelectObject(dc, GetStockObject(LTGRAY_BRUSH)); Rectangle(dc, 0, 0, width, height); SelectObject(dc, GetStockObject(p->depressed ? BLACK_PEN : WHITE_PEN)); MoveTo(dc, 1, 1); LineTo(dc, width - 3, 1); LineTo(dc, width - 4, 2); LineTo(dc, 2, 2); LineTo(dc, 2, height - 4); LineTo(dc, 1, height - 3); LineTo(dc, 1, 1); SelectObject(dc, GetStockObject(p->depressed ? WHITE_PEN : BLACK_PEN)); MoveTo(dc, width - 3, height - 3); LineTo(dc, width - 3, 3); LineTo(dc, width - 2, 2); LineTo(dc, width - 2, height - 2); LineTo(dc, 2, height - 2); LineTo(dc, 3, height - 3); LineTo(dc, width - 3, height - 3); HBITMAP picture = p->disabled ? p->disabled_picture : p->picture; { HDC memory = CreateCompatibleDC(dc); HBITMAP old_bitmap; BITMAP bm; int x, y; SetBkColor(dc, RGB(192, 192, 192)); SetTextColor(dc, RGB(0, 0, 0)); if (picture != NULL) { GetObject(picture, sizeof(BITMAP), &bm); old_bitmap = SelectObject(memory, picture); x = (width - bm.bmWidth) / 2; if (x < 5) x = 5; y = (height - bm.bmHeight) / 2; if (y < 5) y = 5; if (p->depressed) { x++; y++; } BitBlt(dc, x, y, bm.bmWidth, bm.bmHeight, memory, 0, 0, SRCCOPY); SelectObject(memory, old_bitmap); DeleteDC(memory); } else { x = y = 5 + FOCUS_BORDER_WIDTH; bm.bmWidth = width - 2*x; bm.bmHeight = height - 2*y; } if (p->tabstop && p->focus) { RECT r; r.left = x - FOCUS_BORDER_WIDTH; r.right = x + bm.bmWidth + FOCUS_BORDER_WIDTH; r.top = y - FOCUS_BORDER_WIDTH; r.bottom = y + bm.bmHeight + FOCUS_BORDER_WIDTH; DrawFocusRect(dc, &r); } } SelectObject(dc, old_pen); SelectObject(dc, old_brush); EndPaint(handle, &paint); GlobalUnlock(hp); return 0; } case WM_ENABLE: if (p->disabled && wParam || !p->disabled && !wParam) { p->disabled = !p->disabled; InvalidateRect(handle, NULL, TRUE); } GlobalUnlock(hp); return 0; case WM_LBUTTONDOWN: p->captured = TRUE; p->depressed = TRUE; InvalidateRect(handle, NULL, TRUE); SetCapture(handle); if (p->tabstop) SetFocus(handle); if (p->status_bar != NULL && p->status_message != NULL) SetWindowText(p->status_bar, p->status_message); GlobalUnlock(hp); return 0; case WM_LBUTTONUP: { BOOL notify = !p->captured || LOWORD(lParam) < p->width && HIWORD(lParam) < p->height; p->depressed = FALSE; p->captured = FALSE; InvalidateRect(handle, NULL, TRUE); ReleaseCapture(); if (p->status_bar != NULL && p->status_message != NULL) SetWindowText(p->status_bar, ""); if (notify) PostClickedMessage(handle); GlobalUnlock(hp); return 0; } case WM_MOUSEMOVE: if (p->captured) { BOOL old_depressed = p->depressed; p->depressed = LOWORD(lParam) < p->width && HIWORD(lParam) < p->height; if (p->depressed != old_depressed) { InvalidateRect(handle, NULL, TRUE); GlobalUnlock(hp); return 0; } } break; case WM_SETFOCUS: p->focus = TRUE; InvalidateRect(handle, NULL, TRUE); GlobalUnlock(hp); return 0; case WM_KILLFOCUS: p->focus = FALSE; InvalidateRect(handle, NULL, TRUE); GlobalUnlock(hp); return 0; case WM_GETDLGCODE: GlobalUnlock(hp); return DLGC_BUTTON; case WM_KEYDOWN: if (wParam == ' ' && !p->captured && !p->depressed) { p->depressed = TRUE; InvalidateRect(handle, NULL, TRUE); GlobalUnlock(hp); return 0; } break; case WM_KEYUP: if (wParam == ' ' && !p->captured) { p->depressed = FALSE; InvalidateRect(handle, NULL, TRUE); PostClickedMessage(handle); GlobalUnlock(hp); return 0; } break; case WM_DESTROY: if (p->picture != NULL) DeleteObject(p->picture); if (p->disabled_picture != NULL && p->disabled_picture != p->picture) DeleteObject(p->disabled_picture); GlobalUnlock(hp); GlobalFree(hp); return 0; } return DefWindowProc(handle, message, wParam, lParam); }