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

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

* empty log message *

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