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
7 static char Copyright1[] = "Copyright Johannes Ruscheinski, 1993";
8 static char Copyright2[] = "Copyright David Metcalfe, 1993";
9 static char Copyright3[] = "Copyright Alexandre Julliard, 1994";
18 extern void DEFWND_SetText( HWND hwnd
, LPSTR text
); /* windows/defwnd.c */
20 static void PB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
21 static void CB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
22 static void GB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
23 static void UB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
24 static void OB_Paint( HWND hWnd
, HDC hDC
, WORD action
);
25 static void BUTTON_CheckAutoRadioButton(HWND hWnd
);
28 #define MAX_BTN_TYPE 12
30 static WORD maxCheckState
[MAX_BTN_TYPE
] =
32 BUTTON_UNCHECKED
, /* BS_PUSHBUTTON */
33 BUTTON_UNCHECKED
, /* BS_DEFPUSHBUTTON */
34 BUTTON_CHECKED
, /* BS_CHECKBOX */
35 BUTTON_CHECKED
, /* BS_AUTOCHECKBOX */
36 BUTTON_CHECKED
, /* BS_RADIOBUTTON */
37 BUTTON_3STATE
, /* BS_3STATE */
38 BUTTON_3STATE
, /* BS_AUTO3STATE */
39 BUTTON_UNCHECKED
, /* BS_GROUPBOX */
40 BUTTON_UNCHECKED
, /* BS_USERBUTTON */
41 BUTTON_CHECKED
, /* BS_AUTORADIOBUTTON */
42 BUTTON_UNCHECKED
, /* Not defined */
43 BUTTON_UNCHECKED
/* BS_OWNERDRAW */
46 typedef void (*pfPaint
)(HWND
,HDC
,WORD
);
48 static pfPaint btnPaintFunc
[MAX_BTN_TYPE
] =
50 PB_Paint
, /* BS_PUSHBUTTON */
51 PB_Paint
, /* BS_DEFPUSHBUTTON */
52 CB_Paint
, /* BS_CHECKBOX */
53 CB_Paint
, /* BS_AUTOCHECKBOX */
54 CB_Paint
, /* BS_RADIOBUTTON */
55 CB_Paint
, /* BS_3STATE */
56 CB_Paint
, /* BS_AUTO3STATE */
57 GB_Paint
, /* BS_GROUPBOX */
58 UB_Paint
, /* BS_USERBUTTON */
59 CB_Paint
, /* BS_AUTORADIOBUTTON */
60 NULL
, /* Not defined */
61 OB_Paint
/* BS_OWNERDRAW */
64 #define PAINT_BUTTON(hwnd,style,action) \
65 if (btnPaintFunc[style]) { \
66 HDC hdc = GetDC( hwnd ); \
67 (btnPaintFunc[style])(hwnd,hdc,action); \
68 ReleaseDC( hwnd, hdc ); }
70 static HBITMAP hbitmapCheckBoxes
= 0;
71 static WORD checkBoxWidth
= 0, checkBoxHeight
= 0;
74 LONG
ButtonWndProc(HWND hWnd
, WORD uMsg
, WORD wParam
, LONG lParam
)
78 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
79 LONG style
= wndPtr
->dwStyle
& 0x0000000F;
80 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
87 return DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
;
88 case BS_DEFPUSHBUTTON
:
89 return DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
;
91 case BS_AUTORADIOBUTTON
:
92 return DLGC_BUTTON
| DLGC_RADIOBUTTON
;
98 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
102 if (!hbitmapCheckBoxes
)
105 hbitmapCheckBoxes
= LoadBitmap( 0, MAKEINTRESOURCE(OBM_CHECKBOXES
) );
106 GetObject( hbitmapCheckBoxes
, sizeof(bmp
), (LPSTR
)&bmp
);
107 checkBoxWidth
= bmp
.bmWidth
/ 4;
108 checkBoxHeight
= bmp
.bmHeight
/ 3;
111 if (style
< 0L || style
>= MAX_BTN_TYPE
)
115 infoPtr
->state
= BUTTON_UNCHECKED
;
125 if (btnPaintFunc
[style
])
128 HDC hdc
= BeginPaint( hWnd
, &ps
);
129 (btnPaintFunc
[style
])( hWnd
, hdc
, ODA_DRAWENTIRE
);
130 ReleaseDC( hWnd
, hdc
);
135 SendMessage( hWnd
, BM_SETSTATE
, TRUE
, 0 );
141 if (GetCapture() != hWnd
) break;
143 SendMessage( hWnd
, BM_SETSTATE
, FALSE
, 0 );
144 GetClientRect( hWnd
, &rect
);
145 if (PtInRect( &rect
, MAKEPOINT(lParam
) ))
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 );
162 SendMessage( GetParent(hWnd
), WM_COMMAND
,
163 wndPtr
->wIDmenu
, MAKELPARAM(hWnd
,BN_CLICKED
));
168 if (GetCapture() == hWnd
)
170 GetClientRect( hWnd
, &rect
);
171 if (PtInRect( &rect
, MAKEPOINT(lParam
)) )
172 SendMessage( hWnd
, BM_SETSTATE
, TRUE
, 0 );
173 else SendMessage( hWnd
, BM_SETSTATE
, FALSE
, 0 );
178 if(style
== BS_GROUPBOX
) return HTTRANSPARENT
;
179 lResult
= DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
183 DEFWND_SetText( hWnd
, (LPSTR
)lParam
);
184 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
188 infoPtr
->hFont
= wParam
;
190 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
194 return infoPtr
->hFont
;
197 infoPtr
->state
|= BUTTON_HASFOCUS
;
198 PAINT_BUTTON( hWnd
, style
, ODA_FOCUS
);
202 infoPtr
->state
&= ~BUTTON_HASFOCUS
;
203 PAINT_BUTTON( hWnd
, style
, ODA_FOCUS
);
206 case WM_SYSCOLORCHANGE
:
207 InvalidateRect(hWnd
, NULL
, FALSE
);
211 if ((wParam
& 0x0f) >= MAX_BTN_TYPE
) break;
212 wndPtr
->dwStyle
= (wndPtr
->dwStyle
& 0xfffffff0)
213 | (wParam
& 0x0000000f);
214 style
= wndPtr
->dwStyle
& 0x0000000f;
215 PAINT_BUTTON( hWnd
, style
, ODA_DRAWENTIRE
);
219 lResult
= infoPtr
->state
& 3;
223 if (wParam
> maxCheckState
[style
])
224 wParam
= maxCheckState
[style
];
225 if ((infoPtr
->state
& 3) != wParam
)
227 infoPtr
->state
= (infoPtr
->state
& ~3) | wParam
;
228 PAINT_BUTTON( hWnd
, style
, ODA_SELECT
);
230 if(style
== BS_AUTORADIOBUTTON
&& wParam
==BUTTON_CHECKED
)
231 BUTTON_CheckAutoRadioButton(hWnd
);
235 lResult
= infoPtr
->state
;
239 if (!wParam
!= !(infoPtr
->state
& BUTTON_HIGHLIGHTED
))
241 if (wParam
) infoPtr
->state
|= BUTTON_HIGHLIGHTED
;
242 else infoPtr
->state
&= ~BUTTON_HIGHLIGHTED
;
243 PAINT_BUTTON( hWnd
, style
, ODA_SELECT
);
248 lResult
= DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
256 /**********************************************************************
257 * Push Button Functions
260 static void PB_Paint( HWND hButton
, HDC hDC
, WORD action
)
269 WND
*wndPtr
= WIN_FindWndPtr( hButton
);
270 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
272 GetClientRect(hButton
, &rc
);
274 /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
275 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
276 SendMessage( GetParent(hButton
), WM_CTLCOLOR
, (WORD
)hDC
,
277 MAKELPARAM(hButton
, CTLCOLOR_BTN
) );
278 hOldPen
= (HPEN
)SelectObject(hDC
, sysColorObjects
.hpenWindowFrame
);
279 hOldBrush
= (HBRUSH
)SelectObject(hDC
, sysColorObjects
.hbrushBtnFace
);
280 SetBkMode(hDC
, TRANSPARENT
);
281 Rectangle(hDC
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
282 if (action
== ODA_DRAWENTIRE
)
284 SetPixel( hDC
, rc
.left
, rc
.top
, GetSysColor(COLOR_WINDOW
) );
285 SetPixel( hDC
, rc
.left
, rc
.bottom
-1, GetSysColor(COLOR_WINDOW
) );
286 SetPixel( hDC
, rc
.right
-1, rc
.top
, GetSysColor(COLOR_WINDOW
) );
287 SetPixel( hDC
, rc
.right
-1, rc
.bottom
-1, GetSysColor(COLOR_WINDOW
) );
289 InflateRect( &rc
, -1, -1 );
291 if ((wndPtr
->dwStyle
& 0x000f) == BS_DEFPUSHBUTTON
)
293 Rectangle(hDC
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
294 InflateRect( &rc
, -1, -1 );
297 if (infoPtr
->state
& BUTTON_HIGHLIGHTED
)
299 /* draw button shadow: */
300 SelectObject(hDC
, sysColorObjects
.hbrushBtnShadow
);
301 PatBlt(hDC
, rc
.left
, rc
.top
, 1, rc
.bottom
-rc
.top
, PATCOPY
);
302 PatBlt(hDC
, rc
.left
, rc
.top
, rc
.right
-rc
.left
, 1, PATCOPY
);
303 rc
.left
+= 2; /* To position the text down and right */
306 else GRAPH_DrawReliefRect( hDC
, &rc
, 2, 2, FALSE
);
308 /* draw button label, if any: */
309 text
= USER_HEAP_ADDR( wndPtr
->hText
);
312 SetTextColor( hDC
, (wndPtr
->dwStyle
& WS_DISABLED
) ?
313 GetSysColor(COLOR_GRAYTEXT
) : GetSysColor(COLOR_BTNTEXT
));
314 DrawText(hDC
, text
, -1, &rc
,
315 DT_SINGLELINE
| DT_CENTER
| DT_VCENTER
);
316 /* do we have the focus? */
317 if (infoPtr
->state
& BUTTON_HASFOCUS
)
319 dwTextSize
= GetTextExtent(hDC
, text
, strlen(text
) );
320 delta
= ((rc
.right
- rc
.left
) - LOWORD(dwTextSize
) - 1) >> 1;
323 GetTextMetrics(hDC
, &tm
);
324 delta
= ((rc
.bottom
- rc
.top
) - tm
.tmHeight
- 1) >> 1;
325 rc
.top
+= delta
; rc
.bottom
-= delta
;
326 DrawFocusRect(hDC
, &rc
);
330 SelectObject(hDC
, (HANDLE
)hOldPen
);
331 SelectObject(hDC
, (HANDLE
)hOldBrush
);
335 /**********************************************************************
336 * Check Box & Radio Button Functions
339 static void CB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
343 int textlen
, delta
, x
, y
;
347 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
348 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
350 GetClientRect(hWnd
, &rc
);
352 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
353 hBrush
= SendMessage(GetParent(hWnd
), WM_CTLCOLOR
, (WORD
)hDC
,
354 MAKELPARAM(hWnd
, CTLCOLOR_BTN
));
355 if (action
== ODA_DRAWENTIRE
) FillRect(hDC
, &rc
, hBrush
);
357 GetTextMetrics(hDC
, &tm
);
358 delta
= (rc
.bottom
- rc
.top
- tm
.tmHeight
) >> 1;
359 text
= USER_HEAP_ADDR( wndPtr
->hText
);
360 textlen
= strlen( text
);
362 /* Draw the check-box bitmap */
364 if (infoPtr
->state
& BUTTON_HIGHLIGHTED
) x
+= 2 * checkBoxWidth
;
365 if (infoPtr
->state
& (BUTTON_CHECKED
| BUTTON_3STATE
)) x
+= checkBoxWidth
;
366 if (((wndPtr
->dwStyle
& 0x0f) == BS_RADIOBUTTON
) ||
367 ((wndPtr
->dwStyle
& 0x0f) == BS_AUTORADIOBUTTON
)) y
+= checkBoxHeight
;
368 else if (infoPtr
->state
& BUTTON_3STATE
) y
+= 2 * checkBoxHeight
;
369 GRAPH_DrawBitmap( hDC
, hbitmapCheckBoxes
, rc
.left
, rc
.top
+ delta
,
370 x
, y
, checkBoxWidth
, checkBoxHeight
);
371 rc
.left
+= checkBoxWidth
+ tm
.tmAveCharWidth
/ 2;
373 if (action
== ODA_DRAWENTIRE
)
375 if (wndPtr
->dwStyle
& WS_DISABLED
)
376 SetTextColor( hDC
, GetSysColor(COLOR_GRAYTEXT
) );
377 DrawText(hDC
, text
, textlen
, &rc
, DT_SINGLELINE
| DT_VCENTER
);
380 if ((action
== ODA_FOCUS
) ||
381 ((action
== ODA_DRAWENTIRE
) && (infoPtr
->state
& BUTTON_HASFOCUS
)))
383 GetTextExtentPoint(hDC
, text
, textlen
, &size
);
385 rc
.bottom
-= delta
+ 1;
387 rc
.right
= rc
.left
+ size
.cx
+ 2;
388 DrawFocusRect(hDC
, &rc
);
393 /**********************************************************************
394 * BUTTON_CheckAutoRadioButton
396 * hWnd is checked, uncheck everything else in group
398 static void BUTTON_CheckAutoRadioButton(HWND hWnd
)
400 HWND parent
= GetParent(hWnd
);
402 for(sibling
= GetNextDlgGroupItem(parent
,hWnd
,FALSE
);
404 sibling
= GetNextDlgGroupItem(parent
,sibling
,FALSE
))
405 SendMessage(sibling
,BM_SETCHECK
,BUTTON_UNCHECKED
,0);
409 /**********************************************************************
410 * Group Box Functions
413 static void GB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
418 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
419 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
421 if (action
!= ODA_DRAWENTIRE
) return;
423 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
424 SendMessage( GetParent(hWnd
), WM_CTLCOLOR
, (WORD
)hDC
,
425 MAKELPARAM(hWnd
, CTLCOLOR_BTN
));
426 SelectObject( hDC
, sysColorObjects
.hpenWindowFrame
);
428 GetClientRect(hWnd
, &rc
);
430 MoveTo( hDC
, rc
.left
, rc
.top
+2 );
431 LineTo( hDC
, rc
.right
-1, rc
.top
+2 );
432 LineTo( hDC
, rc
.right
-1, rc
.bottom
-1 );
433 LineTo( hDC
, rc
.left
, rc
.bottom
-1 );
434 LineTo( hDC
, rc
.left
, rc
.top
+2 );
436 text
= USER_HEAP_ADDR( wndPtr
->hText
);
437 GetTextExtentPoint(hDC
, text
, strlen(text
), &size
);
439 rc
.right
= rc
.left
+ size
.cx
+ 1;
441 if (wndPtr
->dwStyle
& WS_DISABLED
)
442 SetTextColor( hDC
, GetSysColor(COLOR_GRAYTEXT
) );
443 DrawText(hDC
, text
, -1, &rc
, DT_SINGLELINE
);
447 /**********************************************************************
448 * User Button Functions
451 static void UB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
455 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
456 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
458 if (action
== ODA_SELECT
) return;
460 GetClientRect(hWnd
, &rc
);
462 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
463 hBrush
= SendMessage(GetParent(hWnd
), WM_CTLCOLOR
, (WORD
)hDC
,
464 MAKELPARAM(hWnd
, CTLCOLOR_BTN
));
465 FillRect(hDC
, &rc
, hBrush
);
467 if ((action
== ODA_FOCUS
) ||
468 ((action
== ODA_DRAWENTIRE
) && (infoPtr
->state
& BUTTON_HASFOCUS
)))
469 DrawFocusRect(hDC
, &rc
);
473 /**********************************************************************
474 * Ownerdrawn Button Functions
477 static void OB_Paint( HWND hWnd
, HDC hDC
, WORD action
)
480 LPDRAWITEMSTRUCT lpdis
;
481 WND
*wndPtr
= WIN_FindWndPtr( hWnd
);
482 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
484 if (!(hDis
= USER_HEAP_ALLOC(GMEM_MOVEABLE
, sizeof(DRAWITEMSTRUCT
))))
486 lpdis
= (LPDRAWITEMSTRUCT
)USER_HEAP_ADDR(hDis
);
487 lpdis
->CtlType
= ODT_BUTTON
;
488 lpdis
->CtlID
= wndPtr
->wIDmenu
;
490 lpdis
->itemAction
= action
;
491 lpdis
->itemState
= (infoPtr
->state
& BUTTON_HASFOCUS
) ? ODS_FOCUS
: 0 |
492 (infoPtr
->state
& BUTTON_HIGHLIGHTED
) ? ODS_SELECTED
: 0 |
493 (wndPtr
->dwStyle
& WS_DISABLED
) ? ODS_DISABLED
: 0;
494 lpdis
->hwndItem
= hWnd
;
496 GetClientRect( hWnd
, &lpdis
->rcItem
);
498 SendMessage(GetParent(hWnd
), WM_DRAWITEM
, 1, (LPARAM
)lpdis
);
499 USER_HEAP_FREE(hDis
);