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

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

compile fixes

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