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

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

WINE 991212, WM_SETREDRAW fix, MDI work

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