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

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

Added new logging feature

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