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

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

controls update

File size: 26.5 KB
Line 
1/* File: button.c -- Button type widgets
2 *
3 * Copyright (c) 1999 Christoph Bratschi (ported from WINE)
4 *
5 * Copyright (C) 1993 Johannes Ruscheinski
6 * Copyright (C) 1993 David Metcalfe
7 * Copyright (C) 1994 Alexandre Julliard
8 */
9
10/* CB: todo
11 - window words not right implemented
12 - update checkboxes.bmp to Win9x style
13*/
14
15#include <string.h>
16#include <stdlib.h>
17
18#include "winuser.h"
19#include "winbase.h"
20#include "controls.h"
21#include "button.h"
22
23//Prototypes
24
25static void PaintGrayOnGray(HDC hDC,HFONT hFont,RECT *rc,char *text,UINT format);
26
27static void PB_Paint(HWND hwnd,HDC hDC,WORD action);
28static void CB_Paint(HWND hwnd,HDC hDC,WORD action);
29static void GB_Paint(HWND hwnd,HDC hDC,WORD action);
30static void UB_Paint(HWND hwnd,HDC hDC,WORD action);
31static void OB_Paint(HWND hwnd,HDC hDC,WORD action);
32static void BUTTON_CheckAutoRadioButton(HWND hwnd);
33
34#define MAX_BTN_TYPE 12
35
36static const WORD maxCheckState[MAX_BTN_TYPE] =
37{
38 BUTTON_UNCHECKED, /* BS_PUSHBUTTON */
39 BUTTON_UNCHECKED, /* BS_DEFPUSHBUTTON */
40 BUTTON_CHECKED, /* BS_CHECKBOX */
41 BUTTON_CHECKED, /* BS_AUTOCHECKBOX */
42 BUTTON_CHECKED, /* BS_RADIOBUTTON */
43 BUTTON_3STATE, /* BS_3STATE */
44 BUTTON_3STATE, /* BS_AUTO3STATE */
45 BUTTON_UNCHECKED, /* BS_GROUPBOX */
46 BUTTON_UNCHECKED, /* BS_USERBUTTON */
47 BUTTON_CHECKED, /* BS_AUTORADIOBUTTON */
48 BUTTON_UNCHECKED, /* Not defined */
49 BUTTON_UNCHECKED /* BS_OWNERDRAW */
50};
51
52typedef void (*pfPaint)(HWND hwnd,HDC hdc,WORD action);
53
54static const pfPaint btnPaintFunc[MAX_BTN_TYPE] =
55{
56 PB_Paint, /* BS_PUSHBUTTON */
57 PB_Paint, /* BS_DEFPUSHBUTTON */
58 CB_Paint, /* BS_CHECKBOX */
59 CB_Paint, /* BS_AUTOCHECKBOX */
60 CB_Paint, /* BS_RADIOBUTTON */
61 CB_Paint, /* BS_3STATE */
62 CB_Paint, /* BS_AUTO3STATE */
63 GB_Paint, /* BS_GROUPBOX */
64 UB_Paint, /* BS_USERBUTTON */
65 CB_Paint, /* BS_AUTORADIOBUTTON */
66 NULL, /* Not defined */
67 OB_Paint /* BS_OWNERDRAW */
68};
69
70#define PAINT_BUTTON(hwnd,style,action) \
71 if (btnPaintFunc[style]) { \
72 HDC hdc = GetDC(hwnd); \
73 (btnPaintFunc[style])(hwnd,hdc,action); \
74 ReleaseDC(hwnd,hdc); }
75
76#define BUTTON_SEND_CTLCOLOR(hwnd,hdc) \
77 SendMessageA( GetParent(hwnd), WM_CTLCOLORBTN, \
78 (hdc),hwnd)
79
80static HBITMAP hbitmapCheckBoxes = 0;
81static WORD checkBoxWidth = 0, checkBoxHeight = 0;
82
83
84static LRESULT BUTTON_GetDlgCode(HWND hwnd,WPARAM wParam,LPARAM lParam)
85{
86 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
87
88 switch (dwStyle & 0x0f)
89 {
90 case BS_PUSHBUTTON:
91 return DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON;
92 case BS_DEFPUSHBUTTON:
93 return DLGC_BUTTON | DLGC_DEFPUSHBUTTON;
94 case BS_RADIOBUTTON:
95 case BS_AUTORADIOBUTTON:
96 return DLGC_BUTTON | DLGC_RADIOBUTTON;
97 default:
98 return DLGC_BUTTON;
99 }
100}
101
102static LRESULT BUTTON_Enable(HWND hwnd,WPARAM wParam,LPARAM lParam)
103{
104 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
105
106 PAINT_BUTTON(hwnd,dwStyle & 0x0f,ODA_DRAWENTIRE);
107
108 return 0;
109}
110
111static LRESULT BUTTON_Create(HWND hwnd,WPARAM wParam,LPARAM lParam)
112{
113 BUTTONINFO* infoPtr;
114 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
115
116 if (!hbitmapCheckBoxes)
117 {
118 BITMAP bmp;
119
120 hbitmapCheckBoxes = NativeLoadBitmap(0,MAKEINTRESOURCEA(OBM_CHECKBOXES));
121 GetObjectA( hbitmapCheckBoxes, sizeof(bmp), &bmp );
122 checkBoxWidth = bmp.bmWidth / 4;
123 checkBoxHeight = bmp.bmHeight / 3;
124 }
125 if (style < 0L || style >= MAX_BTN_TYPE) return -1; /* abort */
126
127 infoPtr = (BUTTONINFO*)malloc(sizeof(BUTTONINFO));
128 infoPtr->state = BUTTON_UNCHECKED;
129 infoPtr->hFont = 0;
130 infoPtr->hImage = NULL;
131 SetInfoPtr(hwnd,(DWORD)infoPtr);
132
133 return 0;
134}
135
136static LRESULT BUTTON_Destroy(HWND hwnd,WPARAM wParam,LPARAM lParam)
137{
138 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
139
140 free(infoPtr);
141
142 return 0;
143}
144
145static LRESULT BUTTON_EraseBkgnd(HWND hwnd,WPARAM wParam,LPARAM lParam)
146{
147 return 1;
148}
149
150static LRESULT BUTTON_Paint(HWND hwnd,WPARAM wParam,LPARAM lParam)
151{
152 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
153
154 if (btnPaintFunc[style])
155 {
156 PAINTSTRUCT ps;
157
158 HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd,&ps);
159 SetBkMode(hdc,OPAQUE);
160 (btnPaintFunc[style])(hwnd,hdc,ODA_DRAWENTIRE);
161 if(!wParam) EndPaint(hwnd,&ps);
162 }
163
164 return 0;
165}
166
167static LRESULT BUTTON_LButtonDown(HWND hwnd,WPARAM wParam,LPARAM lParam)
168{
169 SendMessageA(hwnd,BM_SETSTATE,TRUE,0);
170 SetFocus(hwnd);
171 SetCapture(hwnd);
172
173 return 0;
174}
175
176static LRESULT BUTTON_LButtonUp(HWND hwnd,WPARAM wParam,LPARAM lParam)
177{
178 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
179 RECT rect;
180 POINT pt;
181
182 pt.x = LOWORD(lParam);
183 pt.y = HIWORD(lParam);
184
185 ReleaseCapture();
186 if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) return 0;
187 SendMessageA(hwnd,BM_SETSTATE,FALSE,0);
188 GetClientRect(hwnd,&rect);
189 if (PtInRect(&rect,pt))
190 {
191 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
192 DWORD id = GetWindowLongA(hwnd,GWL_ID);
193
194 switch(dwStyle & 0x0f)
195 {
196 case BS_AUTOCHECKBOX:
197 SendMessageA(hwnd,BM_SETCHECK,!(infoPtr->state & BUTTON_CHECKED),0);
198 break;
199 case BS_AUTORADIOBUTTON:
200 SendMessageA(hwnd,BM_SETCHECK,TRUE,0);
201 break;
202 case BS_AUTO3STATE:
203 SendMessageA(hwnd,BM_SETCHECK,
204 (infoPtr->state & BUTTON_3STATE) ? 0 :
205 ((infoPtr->state & 3)+1),0);
206 break;
207 }
208 SendMessageA(GetParent(hwnd),WM_COMMAND,MAKEWPARAM(id,BN_CLICKED),hwnd);
209 }
210
211 return 0;
212}
213
214static LRESULT BUTTON_MouseMove(HWND hwnd,WPARAM wParam,LPARAM lParam)
215{
216 if (GetCapture() == hwnd)
217 {
218 RECT rect;
219 POINT pt;
220
221 pt.x = LOWORD(lParam);
222 pt.y = HIWORD(lParam);
223
224 GetClientRect(hwnd,&rect);
225 SendMessageA(hwnd,BM_SETSTATE,PtInRect(&rect,pt),0);
226 }
227
228 return 0;
229}
230
231static LRESULT BUTTON_NCHitTest(HWND hwnd,WPARAM wParam,LPARAM lParam)
232{
233 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
234
235 if (style == BS_GROUPBOX) return HTTRANSPARENT;
236
237 return DefWindowProcA(hwnd,WM_NCHITTEST,wParam,lParam);
238}
239
240static LRESULT BUTTON_SetText(HWND hwnd,WPARAM wParam,LPARAM lParam)
241{
242 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
243
244 DefWindowProcA(hwnd,WM_SETTEXT,wParam,lParam);
245 if (dwStyle & WS_VISIBLE) PAINT_BUTTON(hwnd,dwStyle & 0x0f,ODA_DRAWENTIRE);
246
247 return 0;
248}
249
250static LRESULT BUTTON_SetFont(HWND hwnd,WPARAM wParam,LPARAM lParam)
251{
252 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
253 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
254
255 infoPtr->hFont = (HFONT)wParam;
256 if (lParam && (dwStyle & WS_VISIBLE)) PAINT_BUTTON(hwnd,dwStyle & 0x0f,ODA_DRAWENTIRE);
257
258 return 0;
259}
260
261static LRESULT BUTTON_GetFont(HWND hwnd,WPARAM wParam,LPARAM lParam)
262{
263 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
264
265 return infoPtr->hFont;
266}
267
268static LRESULT BUTTON_SetFocus(HWND hwnd,WPARAM wParam,LPARAM lParam)
269{
270 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
271 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
272
273 infoPtr->state |= BUTTON_HASFOCUS;
274 if (style == BS_AUTORADIOBUTTON)
275 {
276 SendMessageA(hwnd,BM_SETCHECK,1,0);
277 }
278 PAINT_BUTTON(hwnd,style,ODA_FOCUS);
279
280 return 0;
281}
282
283static LRESULT BUTTON_KillFocus(HWND hwnd,WPARAM wParam,LPARAM lParam)
284{
285 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
286 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
287
288 infoPtr->state &= ~BUTTON_HASFOCUS;
289 PAINT_BUTTON(hwnd,style,ODA_FOCUS);
290 InvalidateRect(hwnd,NULL,TRUE);
291
292 return 0;
293}
294
295static LRESULT BUTTON_SysColorChange(HWND hwnd,WPARAM wParam,LPARAM lParam)
296{
297 InvalidateRect(hwnd,NULL,FALSE);
298
299 return 0;
300}
301
302static LRESULT BUTTON_SetStyle(HWND hwnd,WPARAM wParam,LPARAM lParam)
303{
304 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
305
306 if ((wParam & 0x0f) >= MAX_BTN_TYPE) return 0;
307 dwStyle = (dwStyle & 0xfffffff0) | (wParam & 0x0000000f);
308 SetWindowLongA(hwnd,GWL_STYLE,dwStyle);
309 PAINT_BUTTON(hwnd,dwStyle & 0x0f,ODA_DRAWENTIRE);
310
311 return 0;
312}
313
314static LRESULT BUTTON_SetImage(HWND hwnd,WPARAM wParam,LPARAM lParam)
315{
316 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
317 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
318 HANDLE oldHbitmap = infoPtr->hImage;
319
320 if (dwStyle & BS_BITMAP) infoPtr->hImage = (HANDLE)lParam;
321
322 return oldHbitmap;
323}
324
325static LRESULT BUTTON_GetImage(HWND hwnd,WPARAM wParam,LPARAM lParam)
326{
327 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
328
329 return infoPtr->hImage;
330}
331
332static LRESULT BUTTON_GetCheck(HWND hwnd,WPARAM wParam,LPARAM lParam)
333{
334 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
335
336 return infoPtr->state & 3;
337}
338
339static LRESULT BUTTON_SetCheck(HWND hwnd,WPARAM wParam,LPARAM lParam)
340{
341 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
342 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
343 DWORD style = dwStyle & 0x0f;
344
345 if (wParam > maxCheckState[style]) wParam = maxCheckState[style];
346 if ((infoPtr->state & 3) != wParam)
347 {
348 if ((style == BS_RADIOBUTTON) || (style == BS_AUTORADIOBUTTON))
349 {
350 DWORD oldStyle = dwStyle;
351
352 if (wParam)
353 dwStyle |= WS_TABSTOP;
354 else
355 dwStyle &= ~WS_TABSTOP;
356
357 if (oldStyle != dwStyle) SetWindowLongA(hwnd,GWL_STYLE,dwStyle);
358 }
359 infoPtr->state = (infoPtr->state & ~3) | wParam;
360 PAINT_BUTTON(hwnd,style,ODA_SELECT);
361 }
362 if ((style == BS_AUTORADIOBUTTON) && (wParam == BUTTON_CHECKED))
363 BUTTON_CheckAutoRadioButton(hwnd);
364
365 return 0;
366}
367
368static LRESULT BUTTON_GetState(HWND hwnd,WPARAM wParam,LPARAM lParam)
369{
370 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
371
372 return infoPtr->state;
373}
374
375static LRESULT BUTTON_SetState(HWND hwnd,WPARAM wParam,LPARAM lParam)
376{
377 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
378 DWORD style = GetWindowLongA(hwnd,GWL_STYLE) & 0x0f;
379
380 if (wParam)
381 {
382 if (infoPtr->state & BUTTON_HIGHLIGHTED) return 0;
383 infoPtr->state |= BUTTON_HIGHLIGHTED;
384 } else
385 {
386 if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) return 0;
387 infoPtr->state &= ~BUTTON_HIGHLIGHTED;
388 }
389 PAINT_BUTTON(hwnd,style,ODA_SELECT);
390
391 return 0;
392}
393
394/***********************************************************************
395 * ButtonWndProc
396 */
397LRESULT WINAPI ButtonWndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
398{
399 switch (uMsg)
400 {
401 case WM_GETDLGCODE:
402 return BUTTON_GetDlgCode(hwnd,wParam,lParam);
403
404 case WM_ENABLE:
405 return BUTTON_Enable(hwnd,wParam,lParam);
406
407 case WM_CREATE:
408 return BUTTON_Create(hwnd,wParam,lParam);
409
410 case WM_DESTROY:
411 return BUTTON_Destroy(hwnd,wParam,lParam);
412
413 case WM_ERASEBKGND:
414 return BUTTON_EraseBkgnd(hwnd,wParam,lParam);
415
416 case WM_PAINT:
417 return BUTTON_Paint(hwnd,wParam,lParam);
418
419 case WM_LBUTTONDOWN:
420 case WM_LBUTTONDBLCLK:
421 return BUTTON_LButtonDown(hwnd,wParam,lParam);
422
423 case WM_LBUTTONUP:
424 return BUTTON_LButtonUp(hwnd,wParam,lParam);
425
426 case WM_MOUSEMOVE:
427 return BUTTON_MouseMove(hwnd,wParam,lParam);
428
429 case WM_NCHITTEST:
430 return BUTTON_NCHitTest(hwnd,wParam,lParam);
431
432 case WM_SETTEXT:
433 return BUTTON_SetText(hwnd,wParam,lParam);
434
435 case WM_SETFONT:
436 return BUTTON_SetFont(hwnd,wParam,lParam);
437
438 case WM_GETFONT:
439 return BUTTON_GetFont(hwnd,wParam,lParam);
440
441 case WM_SETFOCUS:
442 return BUTTON_SetFocus(hwnd,wParam,lParam);
443
444 case WM_KILLFOCUS:
445 return BUTTON_KillFocus(hwnd,wParam,lParam);
446
447 case WM_SYSCOLORCHANGE:
448 return BUTTON_SysColorChange(hwnd,wParam,lParam);
449
450 case BM_SETSTYLE:
451 return BUTTON_SetStyle(hwnd,wParam,lParam);
452
453 case BM_SETIMAGE:
454 return BUTTON_SetImage(hwnd,wParam,lParam);
455
456 case BM_GETIMAGE:
457 return BUTTON_GetImage(hwnd,wParam,lParam);
458
459 case BM_GETCHECK:
460 return BUTTON_GetCheck(hwnd,wParam,lParam);
461
462 case BM_SETCHECK:
463 return BUTTON_SetCheck(hwnd,wParam,lParam);
464
465 case BM_GETSTATE:
466 return BUTTON_GetState(hwnd,wParam,lParam);
467
468 case BM_SETSTATE:
469 return BUTTON_SetState(hwnd,wParam,lParam);
470
471 default:
472 return DefWindowProcA(hwnd,uMsg,wParam,lParam);
473 }
474
475 return 0;
476}
477
478
479/**********************************************************************
480 * Push Button Functions
481 */
482
483static void PB_Paint(HWND hwnd,HDC hDC,WORD action)
484{
485 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
486 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
487 RECT rc;
488 HPEN hOldPen;
489 HBRUSH hOldBrush;
490 int xBorderOffset, yBorderOffset;
491 xBorderOffset = yBorderOffset = 0;
492 INT textLen;
493 char* text;
494
495 GetClientRect(hwnd,&rc );
496
497 /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
498 if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
499 SendMessageA(GetParent(hwnd),WM_CTLCOLORBTN,hDC,hwnd);
500
501 hOldPen = (HPEN)SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME));
502 hOldBrush =(HBRUSH)SelectObject(hDC,GetSysColorBrush(COLOR_BTNFACE));
503 SetBkMode(hDC, TRANSPARENT);
504 Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
505/* if (action == ODA_DRAWENTIRE)*/
506 {
507 SetPixel( hDC, rc.left, rc.top, GetSysColor(COLOR_WINDOW) );
508 SetPixel( hDC, rc.left, rc.bottom-1, GetSysColor(COLOR_WINDOW) );
509 SetPixel( hDC, rc.right-1, rc.top, GetSysColor(COLOR_WINDOW) );
510 SetPixel( hDC, rc.right-1, rc.bottom-1, GetSysColor(COLOR_WINDOW));
511 }
512 InflateRect( &rc, -1, -1 );
513
514 if ((dwStyle & 0x000f) == BS_DEFPUSHBUTTON)
515 {
516 Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);
517 InflateRect( &rc, -1, -1 );
518 }
519
520 if (infoPtr->state & BUTTON_HIGHLIGHTED)
521 {
522 /* draw button shadow: */
523 SelectObject(hDC, GetSysColorBrush(COLOR_BTNSHADOW));
524 PatBlt(hDC, rc.left, rc.top, 1, rc.bottom-rc.top, PATCOPY );
525 PatBlt(hDC, rc.left, rc.top, rc.right-rc.left, 1, PATCOPY );
526 rc.left += 2; /* To position the text down and right */
527 rc.top += 2;
528 } else {
529 rc.right++, rc.bottom++;
530 DrawEdge( hDC, &rc, EDGE_RAISED, BF_RECT );
531
532 /* To place de bitmap correctly */
533 xBorderOffset += GetSystemMetrics(SM_CXEDGE);
534 yBorderOffset += GetSystemMetrics(SM_CYEDGE);
535
536 rc.right--, rc.bottom--;
537 }
538
539 /* draw button label, if any: */
540 textLen = GetWindowTextLengthA(hwnd);
541 if (textLen > 0)
542 {
543 LOGBRUSH lb;
544
545 textLen++;
546 text = (char*)malloc(textLen);
547 GetWindowTextA(hwnd,text,textLen);
548 GetObjectA( GetSysColorBrush(COLOR_BTNFACE), sizeof(lb), &lb );
549 if (dwStyle & WS_DISABLED &&
550 GetSysColor(COLOR_GRAYTEXT) == lb.lbColor)
551 /* don't write gray text on gray background */
552 PaintGrayOnGray( hDC,infoPtr->hFont,&rc,text,
553 DT_CENTER | DT_VCENTER );
554 else
555 {
556 SetTextColor( hDC, (dwStyle & WS_DISABLED) ?
557 GetSysColor(COLOR_GRAYTEXT) :
558 GetSysColor(COLOR_BTNTEXT) );
559 DrawTextA( hDC, text, -1, &rc,
560 DT_SINGLELINE | DT_CENTER | DT_VCENTER );
561 /* do we have the focus? */
562 if (infoPtr->state & BUTTON_HASFOCUS)
563 {
564 RECT r = { 0, 0, 0, 0 };
565 INT xdelta, ydelta;
566
567 DrawTextA( hDC, text, -1, &r,
568 DT_SINGLELINE | DT_CALCRECT );
569 xdelta = ((rc.right - rc.left) - (r.right - r.left) - 1) / 2;
570 ydelta = ((rc.bottom - rc.top) - (r.bottom - r.top) - 1) / 2;
571 if (xdelta < 0) xdelta = 0;
572 if (ydelta < 0) ydelta = 0;
573 InflateRect( &rc, -xdelta, -ydelta );
574 DrawFocusRect( hDC, &rc );
575 }
576 }
577 free(text);
578 }
579
580 if((dwStyle & BS_BITMAP) && (infoPtr->hImage != NULL))
581 {
582 BITMAP bm;
583 HDC hdcMem;
584 int yOffset, xOffset, imageWidth, imageHeight;
585
586 GetObjectA (infoPtr->hImage, sizeof(BITMAP), &bm);
587
588 /* Center the bitmap */
589 xOffset = (((rc.right - rc.left) - 2*xBorderOffset) - bm.bmWidth ) / 2;
590 yOffset = (((rc.bottom - rc.top) - 2*yBorderOffset) - bm.bmHeight ) / 2;
591
592 imageWidth = bm.bmWidth;
593 imageHeight = bm.bmHeight;
594
595 /* If the image is to big for the button */
596 if (xOffset < 0)
597 {
598 imageWidth = rc.right - rc.left - 2*xBorderOffset -1;
599 xOffset = xBorderOffset;
600 }
601
602 if (yOffset < 0)
603 {
604 imageHeight = rc.bottom - rc.top - 2*yBorderOffset -1;
605 yOffset = yBorderOffset;
606 }
607
608 /* Let minimum 1 space from border */
609 xOffset++, yOffset++;
610
611 hdcMem = CreateCompatibleDC (hDC);
612 SelectObject (hdcMem, (HBITMAP)infoPtr->hImage);
613 BitBlt(hDC, rc.left + xOffset,
614 rc.top + yOffset,
615 imageWidth, imageHeight,
616 hdcMem, 0, 0, SRCCOPY);
617
618 DeleteDC (hdcMem);
619 }
620
621 SelectObject( hDC, hOldPen );
622 SelectObject( hDC, hOldBrush );
623}
624
625
626/**********************************************************************
627 * PB_Paint & CB_Paint sub function [internal]
628 * Paint text using a raster brush to avoid gray text on gray
629 * background. 'format' can be a combination of DT_CENTER and
630 * DT_VCENTER to use this function in both PB_PAINT and
631 * CB_PAINT. - Dirk Thierbach
632 *
633 * FIXME: This and TEXT_GrayString should be eventually combined,
634 * so calling one common function from PB_Paint, CB_Paint and
635 * TEXT_GrayString will be enough. Also note that this
636 * function ignores the CACHE_GetPattern funcs.
637 */
638
639static void PaintGrayOnGray(HDC hDC,HFONT hFont,RECT *rc,char *text,
640 UINT format)
641{
642/* This is the standard gray on gray pattern:
643 static const WORD Pattern[] = {0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55};
644*/
645/* This pattern gives better readability with X Fonts.
646 FIXME: Maybe the user should be allowed to decide which he wants. */
647 static const WORD Pattern[] = {0x55,0xFF,0xAA,0xFF,0x55,0xFF,0xAA,0xFF};
648
649 HBITMAP hbm = CreateBitmap( 8, 8, 1, 1, Pattern );
650 HDC hdcMem = CreateCompatibleDC(hDC);
651 HBITMAP hbmMem;
652 HBRUSH hBr;
653 RECT rect,rc2;
654
655 rect=*rc;
656 DrawTextA( hDC, text, -1, &rect, DT_SINGLELINE | DT_CALCRECT);
657 /* now text width and height are in rect.right and rect.bottom */
658 rc2=rect;
659 rect.left = rect.top = 0; /* drawing pos in hdcMem */
660 if (format & DT_CENTER) rect.left=(rc->right-rect.right)/2;
661 if (format & DT_VCENTER) rect.top=(rc->bottom-rect.bottom)/2;
662 hbmMem = CreateCompatibleBitmap( hDC,rect.right,rect.bottom );
663 SelectObject( hdcMem, hbmMem);
664 PatBlt( hdcMem,0,0,rect.right,rect.bottom,WHITENESS);
665 /* will be overwritten by DrawText, but just in case */
666 if (hFont) SelectObject( hdcMem, hFont);
667 DrawTextA( hdcMem, text, -1, &rc2, DT_SINGLELINE);
668 /* After draw: foreground = 0 bits, background = 1 bits */
669 hBr = SelectObject( hdcMem, CreatePatternBrush(hbm) );
670 DeleteObject( hbm );
671 PatBlt( hdcMem,0,0,rect.right,rect.bottom,0xAF0229);
672 /* only keep the foreground bits where pattern is 1 */
673 DeleteObject( SelectObject( hdcMem,hBr) );
674 BitBlt(hDC,rect.left,rect.top,rect.right,rect.bottom,hdcMem,0,0,SRCAND);
675 /* keep the background of the dest */
676 DeleteDC( hdcMem);
677 DeleteObject( hbmMem );
678}
679
680
681/**********************************************************************
682 * Check Box & Radio Button Functions
683 */
684
685static void CB_Paint(HWND hwnd,HDC hDC,WORD action)
686{
687 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
688 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
689 RECT rbox, rtext, client;
690 HBRUSH hBrush;
691 int textLen, delta;
692 char* text = NULL;
693
694 textLen = 0;
695 GetClientRect(hwnd, &client);
696 rbox = rtext = client;
697
698 if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
699
700 /* Something is still not right, checkboxes (and edit controls)
701 * in wsping32 have white backgrounds instead of dark grey.
702 * BUTTON_SEND_CTLCOLOR() is even worse since it returns 0 in this
703 * particular case and the background is not painted at all.
704 */
705
706 hBrush = GetSysColorBrush(COLOR_BTNFACE);
707
708 if (dwStyle & BS_LEFTTEXT)
709 {
710 /* magic +4 is what CTL3D expects */
711
712 rtext.right -= checkBoxWidth + 4;
713 rbox.left = rbox.right - checkBoxWidth;
714 }
715 else
716 {
717 rtext.left += checkBoxWidth + 4;
718 rbox.right = checkBoxWidth;
719 }
720
721 /* Draw the check-box bitmap */
722
723 textLen = GetWindowTextLengthA(hwnd);
724 if (textLen > 0)
725 {
726 textLen++;
727 text = (char*)malloc(textLen);
728 GetWindowTextA(hwnd,text,textLen);
729 }
730 if (action == ODA_DRAWENTIRE || action == ODA_SELECT)
731 {
732 HDC hMemDC = CreateCompatibleDC( hDC );
733 int x = 0, y = 0;
734 delta = (rbox.bottom - rbox.top - checkBoxHeight) >> 1;
735
736 if (action == ODA_SELECT) FillRect( hDC, &rbox, hBrush );
737 else FillRect( hDC, &client, hBrush );
738
739 if (infoPtr->state & BUTTON_HIGHLIGHTED) x += 2 * checkBoxWidth;
740 if (infoPtr->state & (BUTTON_CHECKED | BUTTON_3STATE)) x += checkBoxWidth;
741 if (((dwStyle & 0x0f) == BS_RADIOBUTTON) ||
742 ((dwStyle & 0x0f) == BS_AUTORADIOBUTTON)) y += checkBoxHeight;
743 else if (infoPtr->state & BUTTON_3STATE) y += 2 * checkBoxHeight;
744
745 SelectObject( hMemDC, hbitmapCheckBoxes );
746 BitBlt( hDC, rbox.left, rbox.top + delta, checkBoxWidth,
747 checkBoxHeight, hMemDC, x, y, SRCCOPY );
748 DeleteDC( hMemDC );
749
750 if( text && action != ODA_SELECT )
751 {
752 if (dwStyle & WS_DISABLED &&
753 GetSysColor(COLOR_GRAYTEXT) == GetBkColor(hDC)) {
754 /* don't write gray text on gray background */
755 PaintGrayOnGray( hDC, infoPtr->hFont, &rtext, text,
756 DT_VCENTER);
757 } else {
758 if (dwStyle & WS_DISABLED)
759 SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) );
760 DrawTextA( hDC, text, -1, &rtext,
761 DT_SINGLELINE | DT_VCENTER );
762 textLen = 0; /* skip DrawText() below */
763 }
764 }
765 }
766
767 if ((action == ODA_FOCUS) ||
768 ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS)))
769 {
770 /* again, this is what CTL3D expects */
771
772 SetRectEmpty(&rbox);
773 if(textLen > 0)
774 DrawTextA( hDC, text, -1, &rbox,
775 DT_SINGLELINE | DT_CALCRECT );
776 textLen = rbox.bottom - rbox.top;
777 delta = ((rtext.bottom - rtext.top) - textLen)/2;
778 rbox.bottom = (rbox.top = rtext.top + delta - 1) + textLen + 2;
779 textLen = rbox.right - rbox.left;
780 rbox.right = (rbox.left += --rtext.left) + textLen + 2;
781 IntersectRect(&rbox, &rbox, &rtext);
782 DrawFocusRect( hDC, &rbox );
783 }
784 if (text) free(text);
785}
786
787
788/**********************************************************************
789 * BUTTON_CheckAutoRadioButton
790 *
791 * wndPtr is checked, uncheck every other auto radio button in group
792 */
793static void BUTTON_CheckAutoRadioButton(HWND hwnd)
794{
795 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
796 HWND parent, sibling, start;
797
798 if (!(dwStyle & WS_CHILD)) return;
799 parent = GetParent(hwnd);
800 /* assure that starting control is not disabled or invisible */
801 start = sibling = GetNextDlgGroupItem( parent, hwnd, TRUE );
802 do
803 {
804 if (!sibling) break;
805 if ((hwnd != sibling) &&
806 ((GetWindowLongA(sibling,GWL_STYLE) & 0x0f) == BS_AUTORADIOBUTTON))
807 SendMessageA( sibling, BM_SETCHECK, BUTTON_UNCHECKED, 0 );
808 sibling = GetNextDlgGroupItem( parent, sibling, FALSE );
809 } while (sibling != start);
810}
811
812
813/**********************************************************************
814 * Group Box Functions
815 */
816
817static void GB_Paint(HWND hwnd,HDC hDC,WORD action)
818{
819 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
820 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
821 RECT rc, rcFrame;
822 TEXTMETRICA tm;
823 INT textLen;
824 char* text;
825
826 if (action != ODA_DRAWENTIRE) return;
827
828 SendMessageA(GetParent(hwnd),WM_CTLCOLORBTN,hDC,hwnd);
829
830 GetClientRect(hwnd,&rc);
831
832 rcFrame = rc;
833
834 if (infoPtr->hFont)
835 SelectObject (hDC, infoPtr->hFont);
836 GetTextMetricsA (hDC, &tm);
837 rcFrame.top += (tm.tmHeight / 2) - 1;
838 DrawEdge (hDC, &rcFrame, EDGE_ETCHED, BF_RECT);
839
840 textLen = GetWindowTextLengthA(hwnd);
841 if (textLen > 0)
842 {
843 textLen++;
844 text = (char*)malloc(textLen);
845 GetWindowTextA(hwnd,text,textLen);
846 if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
847 if (dwStyle & WS_DISABLED)
848 SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) );
849 rc.left += 10;
850 DrawTextA( hDC, text, -1, &rc, DT_SINGLELINE | DT_NOCLIP );
851 free(text);
852 }
853}
854
855
856/**********************************************************************
857 * User Button Functions
858 */
859
860static void UB_Paint(HWND hwnd,HDC hDC,WORD action)
861{
862 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
863 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
864 RECT rc;
865 HBRUSH hBrush;
866 if (action == ODA_SELECT) return;
867
868 GetClientRect(hwnd,&rc);
869
870 if (infoPtr->hFont) SelectObject( hDC, infoPtr->hFont );
871 hBrush = GetSysColorBrush(COLOR_BTNFACE);
872
873 FillRect( hDC, &rc, hBrush );
874 if ((action == ODA_FOCUS) ||
875 ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS)))
876 DrawFocusRect( hDC, &rc );
877}
878
879
880/**********************************************************************
881 * Ownerdrawn Button Functions
882 */
883
884static void OB_Paint(HWND hwnd,HDC hDC,WORD action)
885{
886 BUTTONINFO* infoPtr = (BUTTONINFO*)GetInfoPtr(hwnd);
887 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
888 DRAWITEMSTRUCT dis;
889
890 dis.CtlType = ODT_BUTTON;
891 dis.CtlID = GetWindowLongA(hwnd,GWL_ID);
892 dis.itemID = 0;
893 dis.itemAction = action;
894 dis.itemState = ((infoPtr->state & BUTTON_HASFOCUS) ? ODS_FOCUS : 0) |
895 ((infoPtr->state & BUTTON_HIGHLIGHTED) ? ODS_SELECTED : 0) |
896 ((dwStyle & WS_DISABLED) ? ODS_DISABLED : 0);
897 dis.hwndItem = hwnd;
898 dis.hDC = hDC;
899 dis.itemData = 0;
900 GetClientRect( hwnd, &dis.rcItem );
901 SendMessageA( GetParent(hwnd), WM_DRAWITEM,
902 GetWindowLongA(hwnd,GWL_ID), (LPARAM)&dis );
903}
904
905BOOL BUTTON_Register()
906{
907 WNDCLASSA wndClass;
908
909 if (GlobalFindAtomA (ODINBUTTONCLASSNAME)) return FALSE;
910
911 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
912 wndClass.style = CS_GLOBALCLASS;
913 wndClass.lpfnWndProc = (WNDPROC)ButtonWndProc;
914 wndClass.cbClsExtra = 0;
915 wndClass.cbWndExtra = sizeof(BUTTONINFO*);
916 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
917 wndClass.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
918 wndClass.lpszClassName = ODINBUTTONCLASSNAME;
919
920 return RegisterClassA (&wndClass);
921}
922
923
924BOOL BUTTON_Unregister()
925{
926 if (GlobalFindAtomA (ODINBUTTONCLASSNAME))
927 UnregisterClassA (ODINBUTTONCLASSNAME, (HINSTANCE)NULL);
928 return TRUE; //always TRUE
929}
Note: See TracBrowser for help on using the repository browser.