1 /* File: button.c -- Button type widgets
3 * Copyright (C) 1993 Johannes Ruscheinski
4 * Copyright (C) 1993 David Metcalfe
5 * Copyright (C) 1994 Alexandre Julliard
8 static char Copyright1
[] = "Copyright Johannes Ruscheinski, 1993";
9 static char Copyright2
[] = "Copyright David Metcalfe, 1993";
10 static char Copyright3
[] = "Copyright Alexandre Julliard, 1994";
18 extern BOOL
GRAPH_DrawBitmap( HDC hdc
, HBITMAP hbitmap
, int xdest
, int ydest
,
19 int xsrc
, int ysrc
, int width
, int height
,
20 int rop
); /* windows/graphics.c */
21 extern void GRAPH_DrawReliefRect( HDC hdc
, RECT
*rect
, int thickness
,
22 BOOL pressed
); /* windows/graphics.c */
24 extern void DEFWND_SetText( HWND hwnd
, LPSTR text
); /* windows/defwnd.c */
26 static void PB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
27 static void CB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
28 static void GB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
29 static void UB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
30 static void OB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
33 #define MAX_BTN_TYPE 12
35 static WORD maxCheckState
[MAX_BTN_TYPE
] =
37 BUTTON_UNCHECKED
, /* BS_PUSHBUTTON */
38 BUTTON_UNCHECKED
, /* BS_DEFPUSHBUTTON */
39 BUTTON_CHECKED
, /* BS_CHECKBOX */
40 BUTTON_CHECKED
, /* BS_AUTOCHECKBOX */
41 BUTTON_CHECKED
, /* BS_RADIOBUTTON */
42 BUTTON_3STATE
, /* BS_3STATE */
43 BUTTON_3STATE
, /* BS_AUTO3STATE */
44 BUTTON_UNCHECKED
, /* BS_GROUPBOX */
45 BUTTON_UNCHECKED
, /* BS_USERBUTTON */
46 BUTTON_CHECKED
, /* BS_AUTORADIOBUTTON */
47 BUTTON_UNCHECKED
, /* Not defined */
48 BUTTON_UNCHECKED
/* BS_OWNERDRAW */
51 typedef void (*pfPaint
)(HWND
,HDC
,WORD
);
53 static pfPaint btnPaintFunc
[MAX_BTN_TYPE
] =
55 PB_Paint
, /* BS_PUSHBUTTON */
56 PB_Paint
, /* BS_DEFPUSHBUTTON */
57 CB_Paint
, /* BS_CHECKBOX */
58 CB_Paint
, /* BS_AUTOCHECKBOX */
59 CB_Paint
, /* BS_RADIOBUTTON */
60 CB_Paint
, /* BS_3STATE */
61 CB_Paint
, /* BS_AUTO3STATE */
62 GB_Paint
, /* BS_GROUPBOX */
63 UB_Paint
, /* BS_USERBUTTON */
64 CB_Paint
, /* BS_AUTORADIOBUTTON */
65 NULL
, /* Not defined */
66 OB_Paint
/* BS_OWNERDRAW */
69 #define PAINT_BUTTON(hwnd,style,action) \
70 if (btnPaintFunc[style]) { \
71 HDC hdc = GetDC( hwnd ); \
72 (btnPaintFunc[style])(hwnd,hdc,action); \
73 ReleaseDC( hwnd, hdc ); }
75 static HBITMAP hbitmapCheckBoxes
= 0;
76 static WORD checkBoxWidth
= 0, checkBoxHeight
= 0;
79 LONG
ButtonWndProc(HWND hWnd
, WORD uMsg
, WORD wParam
, LONG lParam
)
83 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
84 LONG style
= wndPtr
->dwStyle
& 0x0000000F;
85 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
92 return DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
;
93 case BS_DEFPUSHBUTTON
:
94 return DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
;
96 case BS_AUTORADIOBUTTON
:
97 return DLGC_BUTTON
| DLGC_RADIOBUTTON
;
103 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
107 if (!hbitmapCheckBoxes
)
110 hbitmapCheckBoxes
= LoadBitmap( 0, MAKEINTRESOURCE(OBM_CHECKBOXES
) );
111 GetObject( hbitmapCheckBoxes
, sizeof(bmp
), (LPSTR
)&bmp
);
112 checkBoxWidth
= bmp
.bmWidth
/ 4;
113 checkBoxHeight
= bmp
.bmHeight
/ 3;
116 if (style
< 0L || style
>= MAX_BTN_TYPE
)
120 infoPtr
->state
= BUTTON_UNCHECKED
;
130 if (btnPaintFunc
[style
])
133 HDC hdc
= BeginPaint( hWnd
, &ps
);
134 (btnPaintFunc
[style
])( hWnd
, hdc
, ODA_DRAWENTIRE
);
135 ReleaseDC( hWnd
, hdc
);
140 SendMessage( hWnd
, BM_SETSTATE
, TRUE
, 0 );
147 SendMessage( hWnd
, BM_SETSTATE
, FALSE
, 0 );
148 GetClientRect( hWnd
, &rect
);
149 if (PtInRect( &rect
, MAKEPOINT(lParam
) ))
153 case BS_AUTOCHECKBOX
:
154 SendMessage( hWnd
, BM_SETCHECK
,
155 !(infoPtr
->state
& BUTTON_CHECKED
), 0 );
157 case BS_AUTORADIOBUTTON
:
158 SendMessage( hWnd
, BM_SETCHECK
, TRUE
, 0 );
161 SendMessage( hWnd
, BM_SETCHECK
,
162 (infoPtr
->state
& BUTTON_3STATE
) ? 0 :
163 ((infoPtr
->state
& 3) + 1), 0 );
166 SendMessage( GetParent(hWnd
), WM_COMMAND
,
167 wndPtr
->wIDmenu
, MAKELPARAM(hWnd
,BN_CLICKED
));
172 if (GetCapture() == hWnd
)
174 GetClientRect( hWnd
, &rect
);
175 if (PtInRect( &rect
, MAKEPOINT(lParam
)) )
176 SendMessage( hWnd
, BM_SETSTATE
, TRUE
, 0 );
177 else SendMessage( hWnd
, BM_SETSTATE
, FALSE
, 0 );
182 DEFWND_SetText( hWnd
, (LPSTR
)lParam
);
183 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
187 infoPtr
->hFont
= wParam
;
189 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
193 return infoPtr
->hFont
;
196 infoPtr
->state
|= BUTTON_HASFOCUS
;
197 PAINT_BUTTON( hWnd
, style
, ODA_FOCUS
);
201 infoPtr
->state
&= ~BUTTON_HASFOCUS
;
202 PAINT_BUTTON( hWnd
, style
, ODA_FOCUS
);
205 case WM_SYSCOLORCHANGE
:
206 InvalidateRect(hWnd
, NULL
, FALSE
);
210 if ((wParam
& 0x0f) >= MAX_BTN_TYPE
) break;
211 wndPtr
->dwStyle
= (wndPtr
->dwStyle
& 0xfffffff0)
212 | (wParam
& 0x0000000f);
213 style
= wndPtr
->dwStyle
& 0x0000000f;
214 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
218 lResult
= infoPtr
->state
& 3;
222 if (wParam
> maxCheckState
[style
])
223 wParam
= maxCheckState
[style
];
224 if ((infoPtr
->state
& 3) != wParam
)
226 infoPtr
->state
= (infoPtr
->state
& ~3) | wParam
;
227 PAINT_BUTTON( hWnd
, style
, ODA_SELECT
);
232 lResult
= infoPtr
->state
;
236 if (!wParam
!= !(infoPtr
->state
& BUTTON_HIGHLIGHTED
))
238 if (wParam
) infoPtr
->state
|= BUTTON_HIGHLIGHTED
;
239 else infoPtr
->state
&= ~BUTTON_HIGHLIGHTED
;
240 PAINT_BUTTON( hWnd
, style
, ODA_SELECT
);
245 lResult
= DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
253 /**********************************************************************
254 * Push Button Functions
257 static void PB_Paint( HWND hButton
, HDC hDC
, WORD action
)
266 WND
*wndPtr
= WIN_FindWndPtr( hButton
);
267 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
269 GetClientRect(hButton
, &rc
);
271 /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
272 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
273 SendMessage( GetParent(hButton
), WM_CTLCOLOR
, (WORD
)hDC
,
274 MAKELPARAM(hButton
, CTLCOLOR_BTN
) );
275 hOldPen
= (HPEN
)SelectObject(hDC
, sysColorObjects
.hpenWindowFrame
);
276 hOldBrush
= (HBRUSH
)SelectObject(hDC
, sysColorObjects
.hbrushBtnFace
);
277 SetBkMode(hDC
, TRANSPARENT
);
278 Rectangle(hDC
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
279 if (action
== ODA_DRAWENTIRE
)
281 SetPixel( hDC
, rc
.left
, rc
.top
, GetSysColor(COLOR_WINDOW
) );
282 SetPixel( hDC
, rc
.left
, rc
.bottom
-1, GetSysColor(COLOR_WINDOW
) );
283 SetPixel( hDC
, rc
.right
-1, rc
.top
, GetSysColor(COLOR_WINDOW
) );
284 SetPixel( hDC
, rc
.right
-1, rc
.bottom
-1, GetSysColor(COLOR_WINDOW
) );
286 InflateRect( &rc
, -1, -1 );
288 if ((wndPtr
->dwStyle
& 0x000f) == BS_DEFPUSHBUTTON
)
290 Rectangle(hDC
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
291 InflateRect( &rc
, -1, -1 );
294 if (infoPtr
->state
& BUTTON_HIGHLIGHTED
)
296 /* draw button shadow: */
297 SelectObject(hDC
, sysColorObjects
.hbrushBtnShadow
);
298 PatBlt(hDC
, rc
.left
, rc
.top
, 1, rc
.bottom
-rc
.top
, PATCOPY
);
299 PatBlt(hDC
, rc
.left
, rc
.top
, rc
.right
-rc
.left
, 1, PATCOPY
);
300 rc
.left
+= 2; /* To position the text down and right */
303 else GRAPH_DrawReliefRect( hDC
, &rc
, 2, FALSE
);
305 /* draw button label, if any: */
306 text
= USER_HEAP_ADDR( wndPtr
->hText
);
309 SetTextColor( hDC
, (wndPtr
->dwStyle
& WS_DISABLED
) ?
310 GetSysColor(COLOR_GRAYTEXT
) : GetSysColor(COLOR_BTNTEXT
));
311 DrawText(hDC
, text
, -1, &rc
,
312 DT_SINGLELINE
| DT_CENTER
| DT_VCENTER
);
313 /* do we have the focus? */
314 if (infoPtr
->state
& BUTTON_HASFOCUS
)
316 dwTextSize
= GetTextExtent(hDC
, text
, strlen(text
) );
317 delta
= ((rc
.right
- rc
.left
) - LOWORD(dwTextSize
) - 1) >> 1;
320 GetTextMetrics(hDC
, &tm
);
321 delta
= ((rc
.bottom
- rc
.top
) - tm
.tmHeight
- 1) >> 1;
322 rc
.top
+= delta
; rc
.bottom
-= delta
;
323 DrawFocusRect(hDC
, &rc
);
327 SelectObject(hDC
, (HANDLE
)hOldPen
);
328 SelectObject(hDC
, (HANDLE
)hOldBrush
);
332 /**********************************************************************
333 * Check Box & Radion Button Functions
336 static void CB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
340 int textlen
, delta
, x
, y
;
344 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
345 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
347 GetClientRect(hWnd
, &rc
);
349 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
350 hBrush
= SendMessage(GetParent(hWnd
), WM_CTLCOLOR
, (WORD
)hDC
,
351 MAKELPARAM(hWnd
, CTLCOLOR_BTN
));
352 if (action
== ODA_DRAWENTIRE
) FillRect(hDC
, &rc
, hBrush
);
354 GetTextMetrics(hDC
, &tm
);
355 delta
= (rc
.bottom
- rc
.top
- tm
.tmHeight
) >> 1;
356 text
= USER_HEAP_ADDR( wndPtr
->hText
);
357 textlen
= strlen( text
);
359 /* Draw the check-box bitmap */
361 if (infoPtr
->state
& BUTTON_HIGHLIGHTED
) x
+= 2 * checkBoxWidth
;
362 if (infoPtr
->state
& (BUTTON_CHECKED
| BUTTON_3STATE
)) x
+= checkBoxWidth
;
363 if (((wndPtr
->dwStyle
& 0x0f) == BS_RADIOBUTTON
) ||
364 ((wndPtr
->dwStyle
& 0x0f) == BS_AUTORADIOBUTTON
)) y
+= checkBoxHeight
;
365 else if (infoPtr
->state
& BUTTON_3STATE
) y
+= 2 * checkBoxHeight
;
366 GRAPH_DrawBitmap( hDC
, hbitmapCheckBoxes
, rc
.left
, rc
.top
+ delta
,
367 x
, y
, checkBoxWidth
, checkBoxHeight
, SRCCOPY
);
368 rc
.left
+= checkBoxWidth
+ tm
.tmAveCharWidth
/ 2;
370 if (action
== ODA_DRAWENTIRE
)
372 if (wndPtr
->dwStyle
& WS_DISABLED
)
373 SetTextColor( hDC
, GetSysColor(COLOR_GRAYTEXT
) );
374 DrawText(hDC
, text
, textlen
, &rc
, DT_SINGLELINE
| DT_VCENTER
);
377 if ((action
== ODA_FOCUS
) ||
378 ((action
== ODA_DRAWENTIRE
) && (infoPtr
->state
& BUTTON_HASFOCUS
)))
380 GetTextExtentPoint(hDC
, text
, textlen
, &size
);
382 rc
.bottom
-= delta
+ 1;
384 rc
.right
= rc
.left
+ size
.cx
+ 2;
385 DrawFocusRect(hDC
, &rc
);
390 /**********************************************************************
391 * Group Box Functions
394 static void GB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
399 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
400 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
402 if (action
!= ODA_DRAWENTIRE
) return;
404 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
405 SendMessage( GetParent(hWnd
), WM_CTLCOLOR
, (WORD
)hDC
,
406 MAKELPARAM(hWnd
, CTLCOLOR_BTN
));
407 SelectObject( hDC
, sysColorObjects
.hpenWindowFrame
);
409 GetClientRect(hWnd
, &rc
);
411 MoveTo( hDC
, rc
.left
, rc
.top
+2 );
412 LineTo( hDC
, rc
.right
-1, rc
.top
+2 );
413 LineTo( hDC
, rc
.right
-1, rc
.bottom
-1 );
414 LineTo( hDC
, rc
.left
, rc
.bottom
-1 );
415 LineTo( hDC
, rc
.left
, rc
.top
+2 );
417 text
= USER_HEAP_ADDR( wndPtr
->hText
);
418 GetTextExtentPoint(hDC
, text
, strlen(text
), &size
);
420 rc
.right
= rc
.left
+ size
.cx
+ 1;
422 if (wndPtr
->dwStyle
& WS_DISABLED
)
423 SetTextColor( hDC
, GetSysColor(COLOR_GRAYTEXT
) );
424 DrawText(hDC
, text
, -1, &rc
, DT_SINGLELINE
);
428 /**********************************************************************
429 * User Button Functions
432 static void UB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
436 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
437 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
439 if (action
== ODA_SELECT
) return;
441 GetClientRect(hWnd
, &rc
);
443 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
444 hBrush
= SendMessage(GetParent(hWnd
), WM_CTLCOLOR
, (WORD
)hDC
,
445 MAKELPARAM(hWnd
, CTLCOLOR_BTN
));
446 FillRect(hDC
, &rc
, hBrush
);
448 if ((action
== ODA_FOCUS
) ||
449 ((action
== ODA_DRAWENTIRE
) && (infoPtr
->state
& BUTTON_HASFOCUS
)))
450 DrawFocusRect(hDC
, &rc
);
454 /**********************************************************************
455 * Ownerdrawn Button Functions
458 static void OB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
461 LPDRAWITEMSTRUCT lpdis
;
462 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
463 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
465 if (!(hDis
= USER_HEAP_ALLOC(GMEM_MOVEABLE
, sizeof(DRAWITEMSTRUCT
))))
467 lpdis
= (LPDRAWITEMSTRUCT
)USER_HEAP_ADDR(hDis
);
468 lpdis
->CtlType
= ODT_BUTTON
;
469 lpdis
->CtlID
= wndPtr
->wIDmenu
;
471 lpdis
->itemAction
= action
;
472 lpdis
->itemState
= (infoPtr
->state
& BUTTON_HASFOCUS
) ? ODS_FOCUS
: 0 |
473 (infoPtr
->state
& BUTTON_HIGHLIGHTED
) ? ODS_SELECTED
: 0 |
474 (wndPtr
->dwStyle
& WS_DISABLED
) ? ODS_DISABLED
: 0;
475 lpdis
->hwndItem
= hWnd
;
477 GetClientRect( hWnd
, &lpdis
->rcItem
);
479 SendMessage(GetParent(hWnd
), WM_DRAWITEM
, 1, (LPARAM
)lpdis
);
480 USER_HEAP_FREE(hDis
);