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

Last change on this file since 1799 was 1794, checked in by achimha, 26 years ago

added message logging statement, outcommented

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