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

Last change on this file since 1243 was 1243, checked in by cbratschi, 26 years ago

radio buttons fixed, disabled text output

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