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

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

cursor handling fixed

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