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

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

non-client fixes, DefWndProc enhancements, several other bugs fixed

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