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

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

merged with wine-991031, fixed edit bugs

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