source: trunk/src/user32/new/button.cpp@ 2290

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

* empty log message *

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