source: branches/swt/src/user32/button.cpp@ 22097

Last change on this file since 22097 was 22097, checked in by rousseau, 11 years ago

Include a bunch of Console Debug calls

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