source: trunk/src/user32/button.cpp@ 1320

Last change on this file since 1320 was 1320, checked in by sandervl, 26 years ago

YD's button fix + windlg costmetic changes

File size: 29.5 KB
Line 
1/* $Id: button.cpp,v 1.11 1999-10-16 11:05:37 sandervl Exp $ */
2/* File: button.cpp -- Button type widgets
3 *
4 * Copyright (C) 1993 Johannes Ruscheinski
5 * Copyright (C) 1993 David Metcalfe
6 * Copyright (C) 1994 Alexandre Julliard
7 * Copyright (c) 1999 Christoph Bratschi
8 *
9 * WINE version: 990923
10 */
11
12#include <string.h>
13#include <stdlib.h>
14
15#include "winuser.h"
16#include "winbase.h"
17#include "controls.h"
18#include "button.h"
19#include <misc.h>
20
21//Prototypes
22
23static void DrawDisabledText(HDC hdc,char* text,RECT* rtext,UINT format);
24
25static void PB_Paint(HWND hwnd,HDC hDC,WORD action);
26static void CB_Paint(HWND hwnd,HDC hDC,WORD action);
27static void GB_Paint(HWND hwnd,HDC hDC,WORD action);
28static void UB_Paint(HWND hwnd,HDC hDC,WORD action);
29static void OB_Paint(HWND hwnd,HDC hDC,WORD action);
30static void BUTTON_CheckAutoRadioButton(HWND hwnd);
31static void BUTTON_DrawPushButton(HWND hwnd,HDC hDC,WORD action,BOOL pushedState);
32static LRESULT BUTTON_LButtonDown(HWND hwnd,WPARAM wParam,LPARAM lParam);
33
34#define MAX_BTN_TYPE 12
35
36static const WORD maxCheckState[MAX_BTN_TYPE] =
37{
38 BUTTON_UNCHECKED, /* BS_PUSHBUTTON */
39 BUTTON_UNCHECKED, /* BS_DEFPUSHBUTTON */
40 BUTTON_CHECKED, /* BS_CHECKBOX */
41 BUTTON_CHECKED, /* BS_AUTOCHECKBOX */
42 BUTTON_CHECKED, /* BS_RADIOBUTTON */
43 BUTTON_3STATE, /* BS_3STATE */
44 BUTTON_3STATE, /* BS_AUTO3STATE */
45 BUTTON_UNCHECKED, /* BS_GROUPBOX */
46 BUTTON_UNCHECKED, /* BS_USERBUTTON */
47 BUTTON_CHECKED, /* BS_AUTORADIOBUTTON */
48 BUTTON_UNCHECKED, /* Not defined */
49 BUTTON_UNCHECKED /* BS_OWNERDRAW */
50};
51
52typedef void (*pfPaint)(HWND hwnd,HDC hdc,WORD action);
53
54static const pfPaint btnPaintFunc[MAX_BTN_TYPE] =
55{
56 PB_Paint, /* BS_PUSHBUTTON */
57 PB_Paint, /* BS_DEFPUSHBUTTON */
58 CB_Paint, /* BS_CHECKBOX */
59 CB_Paint, /* BS_AUTOCHECKBOX */
60 CB_Paint, /* BS_RADIOBUTTON */
61 CB_Paint, /* BS_3STATE */
62 CB_Paint, /* BS_AUTO3STATE */
63 GB_Paint, /* BS_GROUPBOX */
64 UB_Paint, /* BS_USERBUTTON */
65 CB_Paint, /* BS_AUTORADIOBUTTON */
66 NULL, /* Not defined */
67 OB_Paint /* BS_OWNERDRAW */
68};
69
70#define PAINT_BUTTON(hwnd,style,action) \
71 if (btnPaintFunc[style]) { \
72 HDC hdc = GetDC(hwnd); \
73 (btnPaintFunc[style])(hwnd,hdc,action); \
74 ReleaseDC(hwnd,hdc); }
75
76#define BUTTON_SEND_CTLCOLOR(hwnd,hdc) \
77 SendMessageA( GetParent(hwnd), WM_CTLCOLORBTN, \
78 (hdc),hwnd)
79
80static HBITMAP hbitmapCheckBoxes = 0;
81static WORD checkBoxWidth = 0, checkBoxHeight = 0;
82
83
84static LRESULT BUTTON_GetDlgCode(HWND hwnd,WPARAM wParam,LPARAM lParam)
85{
86 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
87
88 switch (dwStyle & 0x0f)
89 {
90 case BS_AUTOCHECKBOX:
91 case BS_CHECKBOX:
92 return DLGC_WANTCHARS | DLGC_BUTTON;
93
94 case BS_PUSHBUTTON:
95 return DLGC_UNDEFPUSHBUTTON;
96
97 case BS_DEFPUSHBUTTON:
98 return DLGC_DEFPUSHBUTTON;
99
100 case BS_AUTORADIOBUTTON:
101 case BS_RADIOBUTTON:
102 return DLGC_RADIOBUTTON;
103
104 case BS_GROUPBOX:;
105 return DLGC_STATIC;
106
107 default:
108 return DLGC_BUTTON;
109 }
110}
111
112static LRESULT BUTTON_Enable(HWND hwnd,WPARAM wParam,LPARAM lParam)
113{
114 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
115
116// PAINT_BUTTON(hwnd,dwStyle & 0x0f,ODA_DRAWENTIRE);
117 //SvL: 09/10/99 Force it to redraw properly
118 InvalidateRect( hwnd, NULL, FALSE );
119
120 return 0;
121}
122
123static LRESULT BUTTON_Create(HWND hwnd,WPARAM wParam,LPARAM lParam)
124{
125 BUTTONINFO* infoPtr;
126 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
127
128 if (!hbitmapCheckBoxes)
129 {
130 BITMAP bmp;
131 HINSTANCE hinst;
132
133 //CB: Open32 hack to load our own bitmap
134 hinst = LoadLibraryA("USER32.DLL");
135 hbitmapCheckBoxes = NativeLoadBitmap(hinst,MAKEINTRESOURCEA(OBM_CHECKBOXES));
136 FreeLibrary(hinst);
137 if (GetObjectA(hbitmapCheckBoxes,sizeof(bmp),&bmp))
138 {
139 checkBoxWidth = bmp.bmWidth / 4;
140 checkBoxHeight = bmp.bmHeight / 3;
141 } else checkBoxWidth = checkBoxHeight = 0;
142 }
143 if (style < 0L || style >= MAX_BTN_TYPE) return -1; /* abort */
144
145 infoPtr = (BUTTONINFO*)malloc(sizeof(BUTTONINFO));
146 infoPtr->state = BUTTON_UNCHECKED;
147 infoPtr->hFont = 0;
148 infoPtr->hImage = NULL;
149 SetInfoPtr(hwnd,(DWORD)infoPtr);
150
151 return 0;
152}
153
154static LRESULT BUTTON_Destroy(HWND hwnd,WPARAM wParam,LPARAM lParam)
155{
156 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
157
158 free(infoPtr);
159
160 return 0;
161}
162
163static LRESULT BUTTON_EraseBkgnd(HWND hwnd,WPARAM wParam,LPARAM lParam)
164{
165 //SvL: Erase background for groupboxes as the paint function only draws
166 // a box
167 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
168// if(style == BS_GROUPBOX) {
169 return DefWindowProcA(hwnd, WM_ERASEBKGND, wParam, lParam);
170// }
171// return 1;
172}
173
174static LRESULT BUTTON_Paint(HWND hwnd,WPARAM wParam,LPARAM lParam)
175{
176 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
177
178 if (btnPaintFunc[style])
179 {
180 PAINTSTRUCT ps;
181
182 HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd,&ps);
183 SetBkMode(hdc,OPAQUE);
184 (btnPaintFunc[style])(hwnd,hdc,ODA_DRAWENTIRE);
185 if(!wParam) EndPaint(hwnd,&ps);
186 }
187
188 return 0;
189}
190
191static LRESULT BUTTON_LButtonDblClk(HWND hwnd,WPARAM wParam,LPARAM lParam)
192{
193 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
194 DWORD style = dwStyle & 0x0f;
195
196 if(dwStyle & BS_NOTIFY || style == BS_RADIOBUTTON ||
197 style == BS_USERBUTTON || style == BS_OWNERDRAW)
198 SendMessageA(GetParent(hwnd),WM_COMMAND,MAKEWPARAM(GetWindowLongA(hwnd,GWL_ID),BN_DOUBLECLICKED),hwnd);
199 else BUTTON_LButtonDown(hwnd,wParam,lParam);
200
201 return 0;
202}
203
204static LRESULT BUTTON_LButtonDown(HWND hwnd,WPARAM wParam,LPARAM lParam)
205{
206 SetCapture(hwnd);
207 SetFocus(hwnd);
208 SendMessageA(hwnd,BM_SETSTATE,TRUE,0);
209
210 return 0;
211}
212
213static LRESULT BUTTON_LButtonUp(HWND hwnd,WPARAM wParam,LPARAM lParam)
214{
215 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
216 RECT rect;
217 POINT pt;
218
219 pt.x = LOWORD(lParam);
220 pt.y = HIWORD(lParam);
221
222 ReleaseCapture();
223 if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) return 0;
224 SendMessageA(hwnd,BM_SETSTATE,FALSE,0);
225 GetClientRect(hwnd,&rect);
226 if (PtInRect(&rect,pt))
227 {
228 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
229 DWORD id = GetWindowLongA(hwnd,GWL_ID);
230
231 switch(dwStyle & 0x0f)
232 {
233 case BS_AUTOCHECKBOX:
234 SendMessageA(hwnd,BM_SETCHECK,!(infoPtr->state & BUTTON_CHECKED),0);
235 break;
236 case BS_AUTORADIOBUTTON:
237 SendMessageA(hwnd,BM_SETCHECK,TRUE,0);
238 break;
239 case BS_AUTO3STATE:
240 SendMessageA(hwnd,BM_SETCHECK,
241 (infoPtr->state & BUTTON_3STATE) ? 0 :
242 ((infoPtr->state & 3)+1),0);
243 break;
244 }
245 SendMessageA(GetParent(hwnd),WM_COMMAND,MAKEWPARAM(id,BN_CLICKED),hwnd);
246 }
247
248 return 0;
249}
250
251static LRESULT BUTTON_MouseMove(HWND hwnd,WPARAM wParam,LPARAM lParam)
252{
253 if (GetCapture() == hwnd)
254 {
255 RECT rect;
256 POINT pt;
257
258 pt.x = LOWORD(lParam);
259 pt.y = HIWORD(lParam);
260
261 GetClientRect(hwnd,&rect);
262 SendMessageA(hwnd,BM_SETSTATE,PtInRect(&rect,pt),0);
263 }
264
265 return 1; //SvL: Bugfix -> PMWINDOW expects non-zero return value if
266 // we want to restore the default mouse cursor
267}
268
269static LRESULT BUTTON_NCHitTest(HWND hwnd,WPARAM wParam,LPARAM lParam)
270{
271 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
272
273 if (style == BS_GROUPBOX) return HTTRANSPARENT;
274
275 return DefWindowProcA(hwnd,WM_NCHITTEST,wParam,lParam);
276}
277
278static LRESULT BUTTON_SetText(HWND hwnd,WPARAM wParam,LPARAM lParam)
279{
280 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
281
282 DefWindowProcA(hwnd,WM_SETTEXT,wParam,lParam);
283 if (dwStyle & WS_VISIBLE) PAINT_BUTTON(hwnd,dwStyle & 0x0f,ODA_DRAWENTIRE);
284
285 return 0;
286}
287
288static LRESULT BUTTON_SetFont(HWND hwnd,WPARAM wParam,LPARAM lParam)
289{
290 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
291 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
292
293 infoPtr->hFont = (HFONT)wParam;
294 if (lParam && (dwStyle & WS_VISIBLE)) PAINT_BUTTON(hwnd,dwStyle & 0x0f,ODA_DRAWENTIRE);
295
296 return 0;
297}
298
299static LRESULT BUTTON_GetFont(HWND hwnd,WPARAM wParam,LPARAM lParam)
300{
301 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
302
303 return infoPtr->hFont;
304}
305
306static LRESULT BUTTON_KeyDown(HWND hwnd,WPARAM wParam,LPARAM lParam)
307{
308 if (wParam == VK_SPACE)
309 {
310 SendMessageA(hwnd,BM_SETSTATE,TRUE,0);
311 SetFocus(hwnd);
312 SetCapture(hwnd);
313 }
314
315 return 0;
316}
317
318static LRESULT BUTTON_KeyUp(HWND hwnd,WPARAM wParam,LPARAM lParam)
319{
320 if (wParam == VK_SPACE)
321 {
322 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
323 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
324 DWORD id = GetWindowLongA(hwnd,GWL_ID);
325
326 ReleaseCapture();
327 if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) return 0;
328 SendMessageA(hwnd,BM_SETSTATE,FALSE,0);
329
330 switch(dwStyle & 0x0f)
331 {
332 case BS_AUTOCHECKBOX:
333 SendMessageA(hwnd,BM_SETCHECK,!(infoPtr->state & BUTTON_CHECKED),0);
334 break;
335 case BS_AUTORADIOBUTTON:
336 SendMessageA(hwnd,BM_SETCHECK,TRUE,0);
337 break;
338 case BS_AUTO3STATE:
339 SendMessageA(hwnd,BM_SETCHECK,
340 (infoPtr->state & BUTTON_3STATE) ? 0 :
341 ((infoPtr->state & 3)+1),0);
342 break;
343 }
344 SendMessageA(GetParent(hwnd),WM_COMMAND,MAKEWPARAM(id,BN_CLICKED),hwnd);
345 } else if (wParam != VK_TAB) ReleaseCapture();
346
347 return 0;
348}
349
350static LRESULT BUTTON_SysKeyUp(HWND hwnd,WPARAM wParam,LPARAM lParam)
351{
352 if (wParam != VK_TAB) ReleaseCapture();
353
354 return 0;
355}
356
357static LRESULT BUTTON_SetFocus(HWND hwnd,WPARAM wParam,LPARAM lParam)
358{
359 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
360 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
361
362 if ((style == BS_AUTORADIOBUTTON || style == BS_RADIOBUTTON) &&
363 (GetCapture() != hwnd) && !(SendMessageA(hwnd,BM_GETCHECK,0,0) & BST_CHECKED))
364 {
365 /* The notification is sent when the button (BS_AUTORADIOBUTTON)
366 is unckecked and the focus was not given by a mouse click. */
367 if (style == BS_AUTORADIOBUTTON) SendMessageA(hwnd,BM_SETCHECK,TRUE,0);
368 SendMessageA(GetParent(hwnd),WM_COMMAND,MAKEWPARAM(GetWindowLongA(hwnd,GWL_ID),BN_CLICKED),hwnd);
369 }
370
371 infoPtr->state |= BUTTON_HASFOCUS;
372 PAINT_BUTTON(hwnd,style,ODA_FOCUS);
373
374 return 0;
375}
376
377static LRESULT BUTTON_KillFocus(HWND hwnd,WPARAM wParam,LPARAM lParam)
378{
379 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
380 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
381
382 if (infoPtr->state & BUTTON_HASFOCUS)
383 {
384 infoPtr->state &= ~BUTTON_HASFOCUS;
385 PAINT_BUTTON(hwnd,style,ODA_FOCUS);
386 InvalidateRect(hwnd,NULL,TRUE);
387 }
388
389 return 0;
390}
391
392static LRESULT BUTTON_SysColorChange(HWND hwnd,WPARAM wParam,LPARAM lParam)
393{
394 InvalidateRect(hwnd,NULL,FALSE);
395
396 return 0;
397}
398
399static LRESULT BUTTON_Click(HWND hwnd,WPARAM wParam,LPARAM lParam)
400{
401 RECT rect;
402 LPARAM point;
403
404 GetClientRect(hwnd,&rect);
405 point = MAKELPARAM(rect.right/2,rect.bottom/2);
406 SendMessageA(hwnd,WM_LBUTTONDOWN,MK_LBUTTON,point);
407 Sleep(100);
408 SendMessageA(hwnd,WM_LBUTTONUP,0,point);
409
410 return 0;
411}
412
413static LRESULT BUTTON_SetStyle(HWND hwnd,WPARAM wParam,LPARAM lParam)
414{
415 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
416
417 if ((wParam & 0x0f) >= MAX_BTN_TYPE) return 0;
418 dwStyle = (dwStyle & 0xfffffff0) | (wParam & 0x0000000f);
419 SetWindowLongA(hwnd,GWL_STYLE,dwStyle);
420 PAINT_BUTTON(hwnd,dwStyle & 0x0f,ODA_DRAWENTIRE);
421
422 return 0;
423}
424
425static LRESULT BUTTON_SetImage(HWND hwnd,WPARAM wParam,LPARAM lParam)
426{
427 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
428 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
429 HANDLE oldHbitmap = infoPtr->hImage;
430
431 if (dwStyle & BS_BITMAP || dwStyle & BS_ICON) infoPtr->hImage = (HANDLE)lParam;
432
433 return oldHbitmap;
434}
435
436static LRESULT BUTTON_GetImage(HWND hwnd,WPARAM wParam,LPARAM lParam)
437{
438 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
439
440 switch(wParam)
441 {
442 case IMAGE_BITMAP:
443 return (HBITMAP)infoPtr->hImage;
444 case IMAGE_ICON:
445 return (HICON)infoPtr->hImage;
446 default:
447 return NULL;
448 }
449}
450
451static LRESULT BUTTON_GetCheck(HWND hwnd,WPARAM wParam,LPARAM lParam)
452{
453 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
454
455 return infoPtr->state & 3;
456}
457
458static LRESULT BUTTON_SetCheck(HWND hwnd,WPARAM wParam,LPARAM lParam)
459{
460 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
461 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
462 DWORD style = dwStyle & 0x0f;
463
464 if (wParam > maxCheckState[style]) wParam = maxCheckState[style];
465 if ((infoPtr->state & 3) != wParam)
466 {
467 if ((style == BS_RADIOBUTTON) || (style == BS_AUTORADIOBUTTON))
468 {
469 DWORD oldStyle = dwStyle;
470
471 if (wParam)
472 dwStyle |= WS_TABSTOP;
473 else
474 dwStyle &= ~WS_TABSTOP;
475
476 //if (oldStyle != dwStyle) SetWindowLongA(hwnd,GWL_STYLE,dwStyle);
477 }
478 infoPtr->state = (infoPtr->state & ~3) | wParam;
479 PAINT_BUTTON(hwnd,style,ODA_SELECT);
480 }
481 if ((style == BS_AUTORADIOBUTTON) && (wParam == BUTTON_CHECKED))
482 BUTTON_CheckAutoRadioButton(hwnd);
483
484 return 0;
485}
486
487static LRESULT BUTTON_GetState(HWND hwnd,WPARAM wParam,LPARAM lParam)
488{
489 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
490
491 return infoPtr->state;
492}
493
494static LRESULT BUTTON_SetState(HWND hwnd,WPARAM wParam,LPARAM lParam)
495{
496 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
497 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
498
499 if (wParam)
500 {
501 if (infoPtr->state & BUTTON_HIGHLIGHTED) return 0;
502 infoPtr->state |= BUTTON_HIGHLIGHTED;
503 } else
504 {
505 if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) return 0;
506 infoPtr->state &= ~BUTTON_HIGHLIGHTED;
507 }
508 PAINT_BUTTON(hwnd,style,ODA_SELECT);
509
510 return 0;
511}
512
513/***********************************************************************
514 * ButtonWndProc
515 */
516static
517LRESULT WINAPI ButtonWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
518{
519 switch (uMsg)
520 {
521 case WM_GETDLGCODE:
522 return BUTTON_GetDlgCode(hwnd,wParam,lParam);
523
524 case WM_ENABLE:
525 return BUTTON_Enable(hwnd,wParam,lParam);
526
527 case WM_CREATE:
528 return BUTTON_Create(hwnd,wParam,lParam);
529
530 case WM_DESTROY:
531 return BUTTON_Destroy(hwnd,wParam,lParam);
532
533 case WM_ERASEBKGND:
534 return BUTTON_EraseBkgnd(hwnd,wParam,lParam);
535
536 case WM_PAINT:
537 return BUTTON_Paint(hwnd,wParam,lParam);
538
539 case WM_LBUTTONDBLCLK:
540 return BUTTON_LButtonDblClk(hwnd,wParam,lParam);
541
542 case WM_LBUTTONDOWN:
543 return BUTTON_LButtonDown(hwnd,wParam,lParam);
544
545 case WM_LBUTTONUP:
546 return BUTTON_LButtonUp(hwnd,wParam,lParam);
547
548 case WM_MOUSEMOVE:
549 return BUTTON_MouseMove(hwnd,wParam,lParam);
550
551 case WM_NCHITTEST:
552 return BUTTON_NCHitTest(hwnd,wParam,lParam);
553
554 case WM_SETTEXT:
555 return BUTTON_SetText(hwnd,wParam,lParam);
556
557 case WM_SETFONT:
558 return BUTTON_SetFont(hwnd,wParam,lParam);
559
560 case WM_GETFONT:
561 return BUTTON_GetFont(hwnd,wParam,lParam);
562
563 case WM_KEYDOWN:
564 return BUTTON_KeyDown(hwnd,wParam,lParam);
565
566 case WM_KEYUP:
567 return BUTTON_KeyUp(hwnd,wParam,lParam);
568
569 case WM_SYSKEYUP:
570 return BUTTON_SysKeyUp(hwnd,wParam,lParam);
571
572 case WM_SETFOCUS:
573 return BUTTON_SetFocus(hwnd,wParam,lParam);
574
575 case WM_KILLFOCUS:
576 return BUTTON_KillFocus(hwnd,wParam,lParam);
577
578 case WM_SYSCOLORCHANGE:
579 return BUTTON_SysColorChange(hwnd,wParam,lParam);
580
581 case BM_CLICK:
582 return BUTTON_Click(hwnd,wParam,lParam);
583
584 case BM_SETSTYLE:
585 return BUTTON_SetStyle(hwnd,wParam,lParam);
586
587 case BM_SETIMAGE:
588 return BUTTON_SetImage(hwnd,wParam,lParam);
589
590 case BM_GETIMAGE:
591 return BUTTON_GetImage(hwnd,wParam,lParam);
592
593 case BM_GETCHECK:
594 return BUTTON_GetCheck(hwnd,wParam,lParam);
595
596 case BM_SETCHECK:
597 return BUTTON_SetCheck(hwnd,wParam,lParam);
598
599 case BM_GETSTATE:
600 return BUTTON_GetState(hwnd,wParam,lParam);
601
602 case BM_SETSTATE:
603 return BUTTON_SetState(hwnd,wParam,lParam);
604
605 default:
606 return DefWindowProcA(hwnd,uMsg,wParam,lParam);
607 }
608
609 return 0;
610}
611
612
613/**********************************************************************
614 * Push Button Functions
615 */
616static void PB_Paint( HWND hwnd, HDC hDC, WORD action )
617{
618 BUTTONINFO *infoPtr = (BUTTONINFO *)GetInfoPtr(hwnd);
619 BOOL bHighLighted = (infoPtr->state & BUTTON_HIGHLIGHTED);
620
621 /*
622 * Delegate this to the more generic pushbutton painting
623 * method.
624 */
625 BUTTON_DrawPushButton(hwnd,
626 hDC,
627 action,
628 bHighLighted);
629}
630
631/**********************************************************************
632 * This method will actually do the drawing of the pushbutton
633 * depending on it's state and the pushedState parameter.
634 */
635static void BUTTON_DrawPushButton(
636 HWND hwnd,
637 HDC hDC,
638 WORD action,
639 BOOL pushedState )
640{
641 RECT rc, focus_rect;
642 HPEN hOldPen;
643 HBRUSH hOldBrush;
644 BUTTONINFO *infoPtr = (BUTTONINFO *)GetInfoPtr(hwnd);
645 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
646 int xBorderOffset, yBorderOffset;
647 xBorderOffset = yBorderOffset = 0;
648 INT textLen;
649 char* text;
650
651 GetClientRect( hwnd, &rc );
652
653 /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
654 if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
655 BUTTON_SEND_CTLCOLOR( hwnd, hDC );
656 hOldPen = (HPEN)SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME));
657 hOldBrush =(HBRUSH)SelectObject(hDC,GetSysColorBrush(COLOR_BTNFACE));
658 SetBkMode(hDC, TRANSPARENT);
659
660 if ((dwStyle & 0x000f) == BS_DEFPUSHBUTTON)
661 {
662 Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
663 InflateRect( &rc, -1, -1 );
664 }
665
666 UINT uState = DFCS_BUTTONPUSH;
667
668 if (pushedState)
669 {
670 if ( (dwStyle & 0x000f) == BS_DEFPUSHBUTTON )
671 uState |= DFCS_FLAT;
672 else
673 uState |= DFCS_PUSHED;
674 }
675
676 DrawFrameControl( hDC, &rc, DFC_BUTTON, uState );
677 InflateRect( &rc, -2, -2 );
678
679 focus_rect = rc;
680
681 if (pushedState)
682 {
683 rc.left += 2; /* To position the text down and right */
684 rc.top += 2;
685 }
686
687
688 /* draw button label, if any:
689 *
690 * In win9x we don't show text if there is a bitmap or icon.
691 * I don't know about win31 so I leave it as it was for win31.
692 * Dennis Björklund 12 Jul, 99
693 */
694 textLen = GetWindowTextLengthA(hwnd);
695 if (textLen > 0 && (!(dwStyle & (BS_ICON|BS_BITMAP))))
696 {
697 textLen++;
698 text = (char*)malloc(textLen);
699 GetWindowTextA(hwnd,text,textLen);
700
701 if (dwStyle & WS_DISABLED) DrawDisabledText(hDC,text,&rc,DT_SINGLELINE | DT_CENTER | DT_VCENTER); else
702 {
703 SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
704 DrawTextA( hDC, text, -1, &rc,
705 DT_SINGLELINE | DT_CENTER | DT_VCENTER );
706 /* do we have the focus?
707 * Win9x draws focus last with a size prop. to the button
708 */
709 }
710 free(text);
711 }
712 if ( ((dwStyle & BS_ICON) || (dwStyle & BS_BITMAP) ) &&
713 (infoPtr->hImage != NULL) )
714 {
715 int yOffset, xOffset;
716 int imageWidth, imageHeight;
717
718 /*
719 * We extract the size of the image from the handle.
720 */
721 if (dwStyle & BS_ICON)
722 {
723 ICONINFO iconInfo;
724 BITMAP bm;
725
726 GetIconInfo((HICON)infoPtr->hImage, &iconInfo);
727 GetObjectA (iconInfo.hbmColor, sizeof(BITMAP), &bm);
728
729 imageWidth = bm.bmWidth;
730 imageHeight = bm.bmHeight;
731
732 DeleteObject(iconInfo.hbmColor);
733 DeleteObject(iconInfo.hbmMask);
734
735 }
736 else
737 {
738 BITMAP bm;
739
740 GetObjectA (infoPtr->hImage, sizeof(BITMAP), &bm);
741
742 imageWidth = bm.bmWidth;
743 imageHeight = bm.bmHeight;
744 }
745
746 /* Center the bitmap */
747 xOffset = (((rc.right - rc.left) - 2*xBorderOffset) - imageWidth ) / 2;
748 yOffset = (((rc.bottom - rc.top) - 2*yBorderOffset) - imageHeight) / 2;
749
750 /* If the image is too big for the button then create a region*/
751 if(xOffset < 0 || yOffset < 0)
752 {
753 HRGN hBitmapRgn = NULL;
754 hBitmapRgn = CreateRectRgn(
755 rc.left + xBorderOffset, rc.top +yBorderOffset,
756 rc.right - xBorderOffset, rc.bottom - yBorderOffset);
757 SelectClipRgn(hDC, hBitmapRgn);
758 DeleteObject(hBitmapRgn);
759 }
760
761 /* Let minimum 1 space from border */
762 xOffset++, yOffset++;
763
764 /*
765 * Draw the image now.
766 */
767 if (dwStyle & BS_ICON)
768 {
769 DrawIcon(hDC,
770 rc.left + xOffset, rc.top + yOffset,
771 (HICON)infoPtr->hImage);
772 }
773 else
774 {
775 HDC hdcMem;
776
777 hdcMem = CreateCompatibleDC (hDC);
778 SelectObject (hdcMem, (HBITMAP)infoPtr->hImage);
779 BitBlt(hDC,
780 rc.left + xOffset,
781 rc.top + yOffset,
782 imageWidth, imageHeight,
783 hdcMem, 0, 0, SRCCOPY);
784
785 DeleteDC (hdcMem);
786 }
787
788 if(xOffset < 0 || yOffset < 0)
789 {
790 SelectClipRgn(hDC, NULL);
791 }
792 }
793
794 SelectObject( hDC, hOldPen );
795 SelectObject( hDC, hOldBrush );
796
797 if (infoPtr->state & BUTTON_HASFOCUS)
798 {
799 InflateRect( &focus_rect, -1, -1 );
800 DrawFocusRect( hDC, &focus_rect );
801 }
802}
803
804
805static void DrawDisabledText(HDC hdc,char* text,RECT* rtext,UINT format)
806{
807 COLORREF textColor = (GetSysColor(COLOR_GRAYTEXT) == GetBkColor(hdc)) ? COLOR_BTNTEXT:COLOR_GRAYTEXT;
808 RECT rect = *rtext;
809 COLORREF oldMode;
810
811 //CB: bug in Open32 DrawText: underscore is always black! -> two black lines!
812 SetTextColor(hdc,GetSysColor(COLOR_3DHILIGHT));
813 DrawTextA(hdc,text,-1,&rect,format);
814 SetTextColor(hdc,GetSysColor(COLOR_GRAYTEXT));
815 oldMode = SetBkMode(hdc,TRANSPARENT);
816 OffsetRect(&rect,-1,-1);
817 DrawTextA(hdc,text,-1,&rect,format);
818 SetBkMode(hdc,oldMode);
819}
820
821/**********************************************************************
822 * Check Box & Radio Button Functions
823 */
824
825static void CB_Paint(HWND hwnd,HDC hDC,WORD action)
826{
827 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
828 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
829 RECT rbox, rtext, client;
830 HBRUSH hBrush;
831 int textLen, delta;
832 char* text = NULL;
833
834 /*
835 * if the button has a bitmap/icon, draw a normal pushbutton
836 * instead of a radion button.
837 */
838 if (infoPtr->hImage!=NULL)
839 {
840 BOOL bHighLighted = ((infoPtr->state & BUTTON_HIGHLIGHTED) ||
841 (infoPtr->state & BUTTON_CHECKED));
842
843 BUTTON_DrawPushButton(hwnd,
844 hDC,
845 action,
846 bHighLighted);
847 return;
848 }
849
850 textLen = 0;
851 GetClientRect(hwnd, &client);
852 rbox = rtext = client;
853
854 if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
855
856 /* Something is still not right, checkboxes (and edit controls)
857 * in wsping32 have white backgrounds instead of dark grey.
858 * BUTTON_SEND_CTLCOLOR() is even worse since it returns 0 in this
859 * particular case and the background is not painted at all.
860 */
861 //SvL: 20/09/99: This works well for us. Now the background of
862 // the dialog button strings in Solitaire is gray
863 SendMessageA(GetParent(hwnd),WM_CTLCOLORBTN,hDC,hwnd);
864
865 hBrush = GetSysColorBrush(COLOR_BTNFACE);
866
867 if (dwStyle & BS_LEFTTEXT)
868 {
869 /* magic +4 is what CTL3D expects */
870
871 rtext.right -= checkBoxWidth + 4;
872 rbox.left = rbox.right - checkBoxWidth;
873 }
874 else
875 {
876 rtext.left += checkBoxWidth + 4;
877 rbox.right = checkBoxWidth;
878 }
879
880 /* Draw the check-box bitmap */
881
882 textLen = GetWindowTextLengthA(hwnd);
883 if (textLen > 0)
884 {
885 textLen++;
886 text = (char*)malloc(textLen);
887 GetWindowTextA(hwnd,text,textLen);
888 }
889 if (action == ODA_DRAWENTIRE || action == ODA_SELECT)
890 {
891 UINT state;
892
893 if (((dwStyle & 0x0f) == BS_RADIOBUTTON) ||
894 ((dwStyle & 0x0f) == BS_AUTORADIOBUTTON)) state = DFCS_BUTTONRADIO;
895 else if (infoPtr->state & BUTTON_3STATE) state = DFCS_BUTTON3STATE;
896 else state = DFCS_BUTTONCHECK;
897
898 if (infoPtr->state & (BUTTON_CHECKED | BUTTON_3STATE)) state |= DFCS_CHECKED;
899
900 if (infoPtr->state & BUTTON_HIGHLIGHTED) state |= DFCS_PUSHED;
901
902 if (dwStyle & WS_DISABLED) state |= DFCS_INACTIVE;
903
904 DrawFrameControl( hDC, &rbox, DFC_BUTTON, state );
905
906 if( text && action != ODA_SELECT )
907 {
908
909 if (dwStyle & WS_DISABLED) DrawDisabledText(hDC,text,&rtext,DT_SINGLELINE | DT_VCENTER);
910 else DrawTextA(hDC,text,-1,&rtext,DT_SINGLELINE | DT_VCENTER);
911 }
912 }
913
914 if ((action == ODA_FOCUS) ||
915 ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS)))
916 {
917 /* again, this is what CTL3D expects */
918
919 SetRectEmpty(&rbox);
920 if(textLen > 0)
921 DrawTextA( hDC, text, -1, &rbox,
922 DT_SINGLELINE | DT_CALCRECT );
923 textLen = rbox.bottom - rbox.top;
924 delta = ((rtext.bottom - rtext.top) - textLen)/2;
925 rbox.bottom = (rbox.top = rtext.top + delta - 1) + textLen + 2;
926 textLen = rbox.right - rbox.left;
927 rbox.right = (rbox.left += --rtext.left) + textLen + 2;
928 IntersectRect(&rbox, &rbox, &rtext);
929 DrawFocusRect( hDC, &rbox );
930 }
931 if (text) free(text);
932}
933
934
935/**********************************************************************
936 * BUTTON_CheckAutoRadioButton
937 *
938 * wndPtr is checked, uncheck every other auto radio button in group
939 */
940static void BUTTON_CheckAutoRadioButton(HWND hwnd)
941{
942 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
943 HWND parent, sibling, start;
944
945 if (!(dwStyle & WS_CHILD)) return;
946 parent = GetParent(hwnd);
947 /* assure that starting control is not disabled or invisible */
948// start = sibling = GetNextDlgGroupItem( parent, hwnd, TRUE );
949 //@YD: bugfix
950 start = sibling = GetNextDlgGroupItem( parent, hwnd, FALSE );
951 do
952 {
953 if (!sibling) break;
954 if ((hwnd != sibling) &&
955 ((GetWindowLongA(sibling,GWL_STYLE) & 0x0f) == BS_AUTORADIOBUTTON))
956 SendMessageA( sibling, BM_SETCHECK, BUTTON_UNCHECKED, 0 );
957 sibling = GetNextDlgGroupItem( parent, sibling, FALSE );
958 } while (sibling != start);
959}
960
961
962/**********************************************************************
963 * Group Box Functions
964 */
965
966static void GB_Paint(HWND hwnd,HDC hDC,WORD action)
967{
968 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
969 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
970 RECT rc, rcFrame;
971 TEXTMETRICA tm;
972 INT textLen;
973 char* text;
974
975 if (action != ODA_DRAWENTIRE) return;
976
977 SendMessageA(GetParent(hwnd),WM_CTLCOLORBTN,hDC,hwnd);
978
979 GetClientRect(hwnd,&rc);
980
981 rcFrame = rc;
982
983 if (infoPtr->hFont)
984 SelectObject (hDC, infoPtr->hFont);
985 GetTextMetricsA (hDC, &tm);
986 rcFrame.top += (tm.tmHeight / 2) - 1;
987 DrawEdge (hDC, &rcFrame, EDGE_ETCHED, BF_RECT);
988
989 textLen = GetWindowTextLengthA(hwnd);
990 if (textLen > 0)
991 {
992 textLen++;
993 text = (char*)malloc(textLen);
994 GetWindowTextA(hwnd,text,textLen);
995 if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
996 rc.left += 10;
997
998 if (dwStyle & WS_DISABLED) DrawDisabledText(hDC,text,&rc,DT_SINGLELINE | DT_NOCLIP); else
999 {
1000 SetTextColor( hDC, GetSysColor(COLOR_BTNTEXT) );
1001 DrawTextA( hDC, text, -1, &rc,
1002 DT_SINGLELINE | DT_NOCLIP );
1003 }
1004
1005 free(text);
1006 }
1007}
1008
1009
1010/**********************************************************************
1011 * User Button Functions
1012 */
1013
1014static void UB_Paint(HWND hwnd,HDC hDC,WORD action)
1015{
1016 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
1017 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
1018 RECT rc;
1019 HBRUSH hBrush;
1020 if (action == ODA_SELECT) return;
1021
1022 GetClientRect(hwnd,&rc);
1023
1024 if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
1025 hBrush = GetSysColorBrush(COLOR_BTNFACE);
1026
1027 FillRect( hDC, &rc, hBrush );
1028 if ((action == ODA_FOCUS) ||
1029 ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS)))
1030 DrawFocusRect( hDC, &rc );
1031}
1032
1033
1034/**********************************************************************
1035 * Ownerdrawn Button Functions
1036 */
1037
1038static void OB_Paint(HWND hwnd,HDC hDC,WORD action)
1039{
1040 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
1041 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
1042 DRAWITEMSTRUCT dis;
1043
1044 dis.CtlType = ODT_BUTTON;
1045 dis.CtlID = GetWindowLongA(hwnd,GWL_ID);
1046 dis.itemID = 0;
1047 dis.itemAction = action;
1048 dis.itemState = ((infoPtr->state & BUTTON_HASFOCUS) ? ODS_FOCUS : 0) |
1049 ((infoPtr->state & BUTTON_HIGHLIGHTED) ? ODS_SELECTED : 0) |
1050 ((dwStyle & WS_DISABLED) ? ODS_DISABLED : 0);
1051 dis.hwndItem = hwnd;
1052 dis.hDC = hDC;
1053 dis.itemData = 0;
1054 GetClientRect( hwnd, &dis.rcItem );
1055
1056 SetBkColor( hDC, GetSysColor( COLOR_BTNFACE ) );
1057 FillRect( hDC, &dis.rcItem, GetSysColorBrush( COLOR_BTNFACE ) );
1058
1059 SendMessageA( GetParent(hwnd), WM_DRAWITEM,
1060 GetWindowLongA(hwnd,GWL_ID), (LPARAM)&dis );
1061}
1062
1063BOOL BUTTON_Register()
1064{
1065 WNDCLASSA wndClass;
1066
1067 if (GlobalFindAtomA(BUTTONCLASSNAME)) return FALSE;
1068
1069 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
1070 wndClass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW | CS_PARENTDC | CS_DBLCLKS;
1071 wndClass.lpfnWndProc = (WNDPROC)ButtonWndProc;
1072 wndClass.cbClsExtra = 0;
1073 wndClass.cbWndExtra = sizeof(BUTTONINFO);
1074 wndClass.hCursor = LoadCursorA(0,IDC_ARROWA);
1075// wndClass.hbrBackground = (HBRUSH)0;
1076 wndClass.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
1077 wndClass.lpszClassName = BUTTONCLASSNAME;
1078
1079 return RegisterClassA(&wndClass);
1080}
1081
1082BOOL BUTTON_Unregister()
1083{
1084 if (GlobalFindAtomA(BUTTONCLASSNAME))
1085 return UnregisterClassA(BUTTONCLASSNAME,(HINSTANCE)NULL);
1086 else return FALSE;
1087}
Note: See TracBrowser for help on using the repository browser.