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
13 #include "stackframe.h"
15 extern void DEFWND_SetText( HWND hwnd
, LPSTR text
); /* windows/defwnd.c */
17 static void PB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
18 static void CB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
19 static void GB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
20 static void UB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
21 static void OB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
22 static void BUTTON_CheckAutoRadioButton(HWND hWnd
);
25 #define MAX_BTN_TYPE 12
27 static WORD maxCheckState
[MAX_BTN_TYPE
] =
29 BUTTON_UNCHECKED
, /* BS_PUSHBUTTON */
30 BUTTON_UNCHECKED
, /* BS_DEFPUSHBUTTON */
31 BUTTON_CHECKED
, /* BS_CHECKBOX */
32 BUTTON_CHECKED
, /* BS_AUTOCHECKBOX */
33 BUTTON_CHECKED
, /* BS_RADIOBUTTON */
34 BUTTON_3STATE
, /* BS_3STATE */
35 BUTTON_3STATE
, /* BS_AUTO3STATE */
36 BUTTON_UNCHECKED
, /* BS_GROUPBOX */
37 BUTTON_UNCHECKED
, /* BS_USERBUTTON */
38 BUTTON_CHECKED
, /* BS_AUTORADIOBUTTON */
39 BUTTON_UNCHECKED
, /* Not defined */
40 BUTTON_UNCHECKED
/* BS_OWNERDRAW */
43 typedef void (*pfPaint
)(HWND
,HDC
,WORD
);
45 static pfPaint btnPaintFunc
[MAX_BTN_TYPE
] =
47 PB_Paint
, /* BS_PUSHBUTTON */
48 PB_Paint
, /* BS_DEFPUSHBUTTON */
49 CB_Paint
, /* BS_CHECKBOX */
50 CB_Paint
, /* BS_AUTOCHECKBOX */
51 CB_Paint
, /* BS_RADIOBUTTON */
52 CB_Paint
, /* BS_3STATE */
53 CB_Paint
, /* BS_AUTO3STATE */
54 GB_Paint
, /* BS_GROUPBOX */
55 UB_Paint
, /* BS_USERBUTTON */
56 CB_Paint
, /* BS_AUTORADIOBUTTON */
57 NULL
, /* Not defined */
58 OB_Paint
/* BS_OWNERDRAW */
61 #define PAINT_BUTTON(hwnd,style,action) \
62 if (btnPaintFunc[style]) { \
63 HDC hdc = GetDC( hwnd ); \
64 (btnPaintFunc[style])(hwnd,hdc,action); \
65 ReleaseDC( hwnd, hdc ); }
67 static HBITMAP hbitmapCheckBoxes
= 0;
68 static WORD checkBoxWidth
= 0, checkBoxHeight
= 0;
71 LRESULT
ButtonWndProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
76 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
77 LONG style
= wndPtr
->dwStyle
& 0x0000000F;
78 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
85 return DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
;
86 case BS_DEFPUSHBUTTON
:
87 return DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
;
89 case BS_AUTORADIOBUTTON
:
90 return DLGC_BUTTON
| DLGC_RADIOBUTTON
;
96 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
100 if (!hbitmapCheckBoxes
)
103 hbitmapCheckBoxes
= LoadBitmap( 0, MAKEINTRESOURCE(OBM_CHECKBOXES
) );
104 GetObject( hbitmapCheckBoxes
, sizeof(bmp
), (LPSTR
)&bmp
);
105 checkBoxWidth
= bmp
.bmWidth
/ 4;
106 checkBoxHeight
= bmp
.bmHeight
/ 3;
109 if (style
< 0L || style
>= MAX_BTN_TYPE
)
113 infoPtr
->state
= BUTTON_UNCHECKED
;
123 if (btnPaintFunc
[style
])
126 HDC hdc
= BeginPaint( hWnd
, &ps
);
127 (btnPaintFunc
[style
])( hWnd
, hdc
, ODA_DRAWENTIRE
);
128 ReleaseDC( hWnd
, hdc
);
133 SendMessage( hWnd
, BM_SETSTATE
, TRUE
, 0 );
140 if (!(infoPtr
->state
& BUTTON_HIGHLIGHTED
)) break;
141 SendMessage( hWnd
, BM_SETSTATE
, FALSE
, 0 );
142 GetClientRect( hWnd
, &rect
);
143 pt
.x
= LOWORD(lParam
);
144 pt
.y
= HIWORD(lParam
);
145 if (PtInRect( &rect
, pt
))
149 case BS_AUTOCHECKBOX
:
150 SendMessage( hWnd
, BM_SETCHECK
,
151 !(infoPtr
->state
& BUTTON_CHECKED
), 0 );
153 case BS_AUTORADIOBUTTON
:
154 SendMessage( hWnd
, BM_SETCHECK
, TRUE
, 0 );
157 SendMessage( hWnd
, BM_SETCHECK
,
158 (infoPtr
->state
& BUTTON_3STATE
) ? 0 :
159 ((infoPtr
->state
& 3) + 1), 0 );
163 SendMessage( GetParent(hWnd
), WM_COMMAND
,
164 MAKEWPARAM(wndPtr
->wIDmenu
,BN_CLICKED
),
167 SendMessage( GetParent(hWnd
), WM_COMMAND
,
168 wndPtr
->wIDmenu
, MAKELPARAM(hWnd
,BN_CLICKED
));
174 if (GetCapture() == hWnd
)
176 GetClientRect( hWnd
, &rect
);
177 pt
.x
= LOWORD(lParam
);
178 pt
.y
= HIWORD(lParam
);
179 if (PtInRect( &rect
, pt
) )
180 SendMessage( hWnd
, BM_SETSTATE
, TRUE
, 0 );
181 else SendMessage( hWnd
, BM_SETSTATE
, FALSE
, 0 );
186 if(style
== BS_GROUPBOX
) return HTTRANSPARENT
;
187 lResult
= DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
191 DEFWND_SetText( hWnd
, (LPSTR
)PTR_SEG_TO_LIN(lParam
) );
192 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
196 infoPtr
->hFont
= (HFONT
) wParam
;
198 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
202 return (LONG
) infoPtr
->hFont
;
205 infoPtr
->state
|= BUTTON_HASFOCUS
;
206 PAINT_BUTTON( hWnd
, style
, ODA_FOCUS
);
210 infoPtr
->state
&= ~BUTTON_HASFOCUS
;
211 PAINT_BUTTON( hWnd
, style
, ODA_FOCUS
);
214 case WM_SYSCOLORCHANGE
:
215 InvalidateRect(hWnd
, NULL
, FALSE
);
219 if ((wParam
& 0x0f) >= MAX_BTN_TYPE
) break;
220 wndPtr
->dwStyle
= (wndPtr
->dwStyle
& 0xfffffff0)
221 | (wParam
& 0x0000000f);
222 style
= wndPtr
->dwStyle
& 0x0000000f;
223 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
227 lResult
= infoPtr
->state
& 3;
231 if (wParam
> maxCheckState
[style
])
232 wParam
= maxCheckState
[style
];
233 if ((infoPtr
->state
& 3) != wParam
)
235 infoPtr
->state
= (infoPtr
->state
& ~3) | wParam
;
236 PAINT_BUTTON( hWnd
, style
, ODA_SELECT
);
238 if(style
== BS_AUTORADIOBUTTON
&& wParam
==BUTTON_CHECKED
)
239 BUTTON_CheckAutoRadioButton(hWnd
);
243 lResult
= infoPtr
->state
;
247 if (!wParam
!= !(infoPtr
->state
& BUTTON_HIGHLIGHTED
))
249 if (wParam
) infoPtr
->state
|= BUTTON_HIGHLIGHTED
;
250 else infoPtr
->state
&= ~BUTTON_HIGHLIGHTED
;
251 PAINT_BUTTON( hWnd
, style
, ODA_SELECT
);
256 lResult
= DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
264 /**********************************************************************
265 * Push Button Functions
268 static void PB_Paint( HWND hButton
, HDC hDC
, WORD action
)
276 WND
*wndPtr
= WIN_FindWndPtr( hButton
);
277 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
279 GetClientRect(hButton
, &rc
);
281 /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
282 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
284 SendMessage( GetParent(hButton
), WM_CTLCOLORBTN
,
285 (WPARAM
)hDC
, (LPARAM
)hButton
);
287 SendMessage( GetParent(hButton
), WM_CTLCOLOR
, (WORD
)hDC
,
288 MAKELPARAM(hButton
, CTLCOLOR_BTN
) );
290 hOldPen
= (HPEN
)SelectObject(hDC
, sysColorObjects
.hpenWindowFrame
);
291 hOldBrush
= (HBRUSH
)SelectObject(hDC
, sysColorObjects
.hbrushBtnFace
);
292 SetBkMode(hDC
, TRANSPARENT
);
293 Rectangle(hDC
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
294 if (action
== ODA_DRAWENTIRE
)
296 SetPixel( hDC
, rc
.left
, rc
.top
, GetSysColor(COLOR_WINDOW
) );
297 SetPixel( hDC
, rc
.left
, rc
.bottom
-1, GetSysColor(COLOR_WINDOW
) );
298 SetPixel( hDC
, rc
.right
-1, rc
.top
, GetSysColor(COLOR_WINDOW
) );
299 SetPixel( hDC
, rc
.right
-1, rc
.bottom
-1, GetSysColor(COLOR_WINDOW
) );
301 InflateRect( &rc
, -1, -1 );
303 if ((wndPtr
->dwStyle
& 0x000f) == BS_DEFPUSHBUTTON
)
305 Rectangle(hDC
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
306 InflateRect( &rc
, -1, -1 );
309 if (infoPtr
->state
& BUTTON_HIGHLIGHTED
)
311 /* draw button shadow: */
312 SelectObject(hDC
, sysColorObjects
.hbrushBtnShadow
);
313 PatBlt(hDC
, rc
.left
, rc
.top
, 1, rc
.bottom
-rc
.top
, PATCOPY
);
314 PatBlt(hDC
, rc
.left
, rc
.top
, rc
.right
-rc
.left
, 1, PATCOPY
);
315 rc
.left
+= 2; /* To position the text down and right */
318 else GRAPH_DrawReliefRect( hDC
, &rc
, 2, 2, FALSE
);
320 /* draw button label, if any: */
321 text
= (char*) USER_HEAP_LIN_ADDR( wndPtr
->hText
);
324 SetTextColor( hDC
, (wndPtr
->dwStyle
& WS_DISABLED
) ?
325 GetSysColor(COLOR_GRAYTEXT
) : GetSysColor(COLOR_BTNTEXT
));
326 DrawText(hDC
, text
, -1, &rc
,
327 DT_SINGLELINE
| DT_CENTER
| DT_VCENTER
);
328 /* do we have the focus? */
329 if (infoPtr
->state
& BUTTON_HASFOCUS
)
331 short xdelta
, ydelta
;
332 dwTextSize
= GetTextExtent( hDC
, text
, strlen(text
) );
333 GetTextMetrics( hDC
, &tm
);
334 xdelta
= ((rc
.right
- rc
.left
) - LOWORD(dwTextSize
) - 1) / 2;
335 ydelta
= ((rc
.bottom
- rc
.top
) - tm
.tmHeight
- 1) / 2;
336 if (xdelta
< 0) xdelta
= 0;
337 if (ydelta
< 0) ydelta
= 0;
338 InflateRect( &rc
, -xdelta
, -ydelta
);
339 DrawFocusRect( hDC
, &rc
);
343 SelectObject(hDC
, (HANDLE
)hOldPen
);
344 SelectObject(hDC
, (HANDLE
)hOldBrush
);
348 /**********************************************************************
349 * Check Box & Radio Button Functions
352 static void CB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
356 int textlen
, delta
, x
, y
;
360 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
361 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
363 GetClientRect(hWnd
, &rc
);
365 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
366 #ifdef WINELIB32 /* JBP: Different in Win32 */
367 hBrush
= (HBRUSH
) SendMessage(GetParent(hWnd
), WM_CTLCOLORBTN
, (WPARAM
)hDC
,
370 hBrush
= SendMessage(GetParent(hWnd
), WM_CTLCOLOR
, (WORD
)hDC
,
371 MAKELPARAM(hWnd
, CTLCOLOR_BTN
));
373 if (action
== ODA_DRAWENTIRE
) FillRect(hDC
, &rc
, hBrush
);
375 GetTextMetrics(hDC
, &tm
);
376 delta
= (rc
.bottom
- rc
.top
- tm
.tmHeight
) >> 1;
378 /* Draw the check-box bitmap */
380 if (infoPtr
->state
& BUTTON_HIGHLIGHTED
) x
+= 2 * checkBoxWidth
;
381 if (infoPtr
->state
& (BUTTON_CHECKED
| BUTTON_3STATE
)) x
+= checkBoxWidth
;
382 if (((wndPtr
->dwStyle
& 0x0f) == BS_RADIOBUTTON
) ||
383 ((wndPtr
->dwStyle
& 0x0f) == BS_AUTORADIOBUTTON
)) y
+= checkBoxHeight
;
384 else if (infoPtr
->state
& BUTTON_3STATE
) y
+= 2 * checkBoxHeight
;
385 GRAPH_DrawBitmap( hDC
, hbitmapCheckBoxes
, rc
.left
, rc
.top
+ delta
,
386 x
, y
, checkBoxWidth
, checkBoxHeight
);
387 rc
.left
+= checkBoxWidth
+ tm
.tmAveCharWidth
/ 2;
389 if (!(text
= (char*) USER_HEAP_LIN_ADDR( wndPtr
->hText
))) return;
390 textlen
= strlen( text
);
392 if (action
== ODA_DRAWENTIRE
)
394 if (wndPtr
->dwStyle
& WS_DISABLED
)
395 SetTextColor( hDC
, GetSysColor(COLOR_GRAYTEXT
) );
396 DrawText(hDC
, text
, textlen
, &rc
, DT_SINGLELINE
| DT_VCENTER
);
399 if ((action
== ODA_FOCUS
) ||
400 ((action
== ODA_DRAWENTIRE
) && (infoPtr
->state
& BUTTON_HASFOCUS
)))
402 GetTextExtentPoint(hDC
, text
, textlen
, &size
);
406 rc
.bottom
-= delta
+ 1;
409 rc
.right
= MIN( rc
.left
+ size
.cx
+ 2, rc
.right
);
410 DrawFocusRect(hDC
, &rc
);
415 /**********************************************************************
416 * BUTTON_CheckAutoRadioButton
418 * hWnd is checked, uncheck everything else in group
420 static void BUTTON_CheckAutoRadioButton(HWND hWnd
)
422 HWND parent
= GetParent(hWnd
);
424 for(sibling
= GetNextDlgGroupItem(parent
,hWnd
,FALSE
);
426 sibling
= GetNextDlgGroupItem(parent
,sibling
,FALSE
))
427 SendMessage(sibling
,BM_SETCHECK
,BUTTON_UNCHECKED
,0);
431 /**********************************************************************
432 * Group Box Functions
435 static void GB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
440 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
441 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
443 if (action
!= ODA_DRAWENTIRE
) return;
445 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
447 SendMessage( GetParent(hWnd
), WM_CTLCOLORBTN
, (WPARAM
)hDC
, (LPARAM
)hWnd
);
449 SendMessage( GetParent(hWnd
), WM_CTLCOLOR
, (WORD
)hDC
,
450 MAKELPARAM(hWnd
, CTLCOLOR_BTN
));
452 SelectObject( hDC
, sysColorObjects
.hpenWindowFrame
);
454 GetClientRect(hWnd
, &rc
);
456 MoveTo( hDC
, rc
.left
, rc
.top
+2 );
457 LineTo( hDC
, rc
.right
-1, rc
.top
+2 );
458 LineTo( hDC
, rc
.right
-1, rc
.bottom
-1 );
459 LineTo( hDC
, rc
.left
, rc
.bottom
-1 );
460 LineTo( hDC
, rc
.left
, rc
.top
+2 );
462 if (!(text
= (char*) USER_HEAP_LIN_ADDR( wndPtr
->hText
))) return;
463 GetTextExtentPoint(hDC
, text
, strlen(text
), &size
);
465 rc
.right
= rc
.left
+ size
.cx
+ 1;
467 if (wndPtr
->dwStyle
& WS_DISABLED
)
468 SetTextColor( hDC
, GetSysColor(COLOR_GRAYTEXT
) );
469 DrawText(hDC
, text
, -1, &rc
, DT_SINGLELINE
);
473 /**********************************************************************
474 * User Button Functions
477 static void UB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
481 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
482 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
484 if (action
== ODA_SELECT
) return;
486 GetClientRect(hWnd
, &rc
);
488 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
490 hBrush
= (HBRUSH
) SendMessage(GetParent(hWnd
), WM_CTLCOLORBTN
, (WPARAM
)hDC
,
493 hBrush
= SendMessage(GetParent(hWnd
), WM_CTLCOLOR
, (WORD
)hDC
,
494 MAKELPARAM(hWnd
, CTLCOLOR_BTN
));
496 FillRect(hDC
, &rc
, hBrush
);
498 if ((action
== ODA_FOCUS
) ||
499 ((action
== ODA_DRAWENTIRE
) && (infoPtr
->state
& BUTTON_HASFOCUS
)))
500 DrawFocusRect(hDC
, &rc
);
504 /**********************************************************************
505 * Ownerdrawn Button Functions
508 static void OB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
511 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
512 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
514 dis
.CtlType
= ODT_BUTTON
;
515 dis
.CtlID
= wndPtr
->wIDmenu
;
517 dis
.itemAction
= action
;
518 dis
.itemState
= (infoPtr
->state
& BUTTON_HASFOCUS
) ? ODS_FOCUS
: 0 |
519 (infoPtr
->state
& BUTTON_HIGHLIGHTED
) ? ODS_SELECTED
: 0 |
520 (wndPtr
->dwStyle
& WS_DISABLED
) ? ODS_DISABLED
: 0;
523 GetClientRect( hWnd
, &dis
.rcItem
);
525 SendMessage(GetParent(hWnd
), WM_DRAWITEM
, 1, (LPARAM
) MAKE_SEGPTR(&dis
) );