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

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

Button resources

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