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
12 #include "wine/winuser16.h"
15 static void PB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
);
16 static void PB_PaintGrayOnGray(HDC hDC
,HFONT hFont
,RECT
*rc
,char *text
);
17 static void CB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
);
18 static void GB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
);
19 static void UB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
);
20 static void OB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
);
21 static void BUTTON_CheckAutoRadioButton( WND
*wndPtr
);
23 #define MAX_BTN_TYPE 12
25 static const WORD maxCheckState
[MAX_BTN_TYPE
] =
27 BUTTON_UNCHECKED
, /* BS_PUSHBUTTON */
28 BUTTON_UNCHECKED
, /* BS_DEFPUSHBUTTON */
29 BUTTON_CHECKED
, /* BS_CHECKBOX */
30 BUTTON_CHECKED
, /* BS_AUTOCHECKBOX */
31 BUTTON_CHECKED
, /* BS_RADIOBUTTON */
32 BUTTON_3STATE
, /* BS_3STATE */
33 BUTTON_3STATE
, /* BS_AUTO3STATE */
34 BUTTON_UNCHECKED
, /* BS_GROUPBOX */
35 BUTTON_UNCHECKED
, /* BS_USERBUTTON */
36 BUTTON_CHECKED
, /* BS_AUTORADIOBUTTON */
37 BUTTON_UNCHECKED
, /* Not defined */
38 BUTTON_UNCHECKED
/* BS_OWNERDRAW */
41 typedef void (*pfPaint
)( WND
*wndPtr
, HDC hdc
, WORD action
);
43 static const pfPaint btnPaintFunc
[MAX_BTN_TYPE
] =
45 PB_Paint
, /* BS_PUSHBUTTON */
46 PB_Paint
, /* BS_DEFPUSHBUTTON */
47 CB_Paint
, /* BS_CHECKBOX */
48 CB_Paint
, /* BS_AUTOCHECKBOX */
49 CB_Paint
, /* BS_RADIOBUTTON */
50 CB_Paint
, /* BS_3STATE */
51 CB_Paint
, /* BS_AUTO3STATE */
52 GB_Paint
, /* BS_GROUPBOX */
53 UB_Paint
, /* BS_USERBUTTON */
54 CB_Paint
, /* BS_AUTORADIOBUTTON */
55 NULL
, /* Not defined */
56 OB_Paint
/* BS_OWNERDRAW */
59 #define PAINT_BUTTON(wndPtr,style,action) \
60 if (btnPaintFunc[style]) { \
61 HDC hdc = GetDC( (wndPtr)->hwndSelf ); \
62 (btnPaintFunc[style])(wndPtr,hdc,action); \
63 ReleaseDC( (wndPtr)->hwndSelf, hdc ); }
65 #define BUTTON_SEND_CTLCOLOR(wndPtr,hdc) \
66 SendMessageA( GetParent((wndPtr)->hwndSelf), WM_CTLCOLORBTN, \
67 (hdc), (wndPtr)->hwndSelf )
69 static HBITMAP hbitmapCheckBoxes
= 0;
70 static WORD checkBoxWidth
= 0, checkBoxHeight
= 0;
73 /***********************************************************************
76 LRESULT WINAPI
ButtonWndProc( HWND hWnd
, UINT uMsg
,
77 WPARAM wParam
, LPARAM lParam
)
80 POINT pt
= { LOWORD(lParam
), HIWORD(lParam
) };
81 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
82 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
83 LONG style
= wndPtr
->dwStyle
& 0x0f;
90 case BS_PUSHBUTTON
: return DLGC_BUTTON
| DLGC_UNDEFPUSHBUTTON
;
91 case BS_DEFPUSHBUTTON
: return DLGC_BUTTON
| DLGC_DEFPUSHBUTTON
;
93 case BS_AUTORADIOBUTTON
: return DLGC_BUTTON
| DLGC_RADIOBUTTON
;
94 default: return DLGC_BUTTON
;
98 PAINT_BUTTON( wndPtr
, style
, ODA_DRAWENTIRE
);
102 if (!hbitmapCheckBoxes
)
105 hbitmapCheckBoxes
= LoadBitmapA(0, MAKEINTRESOURCEA(OBM_CHECKBOXES
));
106 GetObjectA( hbitmapCheckBoxes
, sizeof(bmp
), &bmp
);
107 checkBoxWidth
= bmp
.bmWidth
/ 4;
108 checkBoxHeight
= bmp
.bmHeight
/ 3;
110 if (style
< 0L || style
>= MAX_BTN_TYPE
) return -1; /* abort */
111 infoPtr
->state
= BUTTON_UNCHECKED
;
119 if (btnPaintFunc
[style
])
122 HDC hdc
= wParam
? (HDC
)wParam
: BeginPaint( hWnd
, &ps
);
123 SetBkMode( hdc
, OPAQUE
);
124 (btnPaintFunc
[style
])( wndPtr
, hdc
, ODA_DRAWENTIRE
);
125 if( !wParam
) EndPaint( hWnd
, &ps
);
130 case WM_LBUTTONDBLCLK
:
131 SendMessageA( hWnd
, BM_SETSTATE
, TRUE
, 0 );
138 if (!(infoPtr
->state
& BUTTON_HIGHLIGHTED
)) break;
139 SendMessageA( hWnd
, BM_SETSTATE
, FALSE
, 0 );
140 GetClientRect( hWnd
, &rect
);
141 if (PtInRect( &rect
, pt
))
145 case BS_AUTOCHECKBOX
:
146 SendMessageA( hWnd
, BM_SETCHECK
,
147 !(infoPtr
->state
& BUTTON_CHECKED
), 0 );
149 case BS_AUTORADIOBUTTON
:
150 SendMessageA( hWnd
, BM_SETCHECK
, TRUE
, 0 );
153 SendMessageA( hWnd
, BM_SETCHECK
,
154 (infoPtr
->state
& BUTTON_3STATE
) ? 0 :
155 ((infoPtr
->state
& 3) + 1), 0 );
158 SendMessageA( GetParent(hWnd
), WM_COMMAND
,
159 MAKEWPARAM( wndPtr
->wIDmenu
, BN_CLICKED
), hWnd
);
164 if (GetCapture() == hWnd
)
166 GetClientRect( hWnd
, &rect
);
167 SendMessageA( hWnd
, BM_SETSTATE
, PtInRect(&rect
, pt
), 0 );
172 if(style
== BS_GROUPBOX
) return HTTRANSPARENT
;
173 return DefWindowProcA( hWnd
, uMsg
, wParam
, lParam
);
176 DEFWND_SetText( wndPtr
, (LPCSTR
)lParam
);
177 if( wndPtr
->dwStyle
& WS_VISIBLE
)
178 PAINT_BUTTON( wndPtr
, style
, ODA_DRAWENTIRE
);
182 infoPtr
->hFont
= (HFONT16
)wParam
;
183 if (lParam
&& (wndPtr
->dwStyle
& WS_VISIBLE
))
184 PAINT_BUTTON( wndPtr
, style
, ODA_DRAWENTIRE
);
188 return infoPtr
->hFont
;
191 infoPtr
->state
|= BUTTON_HASFOCUS
;
192 if (style
== BS_AUTORADIOBUTTON
)
194 SendMessageA( hWnd
, BM_SETCHECK
, 1, 0 );
196 PAINT_BUTTON( wndPtr
, style
, ODA_FOCUS
);
200 infoPtr
->state
&= ~BUTTON_HASFOCUS
;
201 PAINT_BUTTON( wndPtr
, style
, ODA_FOCUS
);
202 InvalidateRect( hWnd
, NULL
, TRUE
);
205 case WM_SYSCOLORCHANGE
:
206 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( wndPtr
, style
, ODA_DRAWENTIRE
);
220 return infoPtr
->state
& 3;
224 if (wParam
> maxCheckState
[style
]) wParam
= maxCheckState
[style
];
225 if ((infoPtr
->state
& 3) != wParam
)
227 if ((style
== BS_RADIOBUTTON
) || (style
== BS_AUTORADIOBUTTON
))
230 wndPtr
->dwStyle
|= WS_TABSTOP
;
232 wndPtr
->dwStyle
&= ~WS_TABSTOP
;
234 infoPtr
->state
= (infoPtr
->state
& ~3) | wParam
;
235 PAINT_BUTTON( wndPtr
, style
, ODA_SELECT
);
237 if ((style
== BS_AUTORADIOBUTTON
) && (wParam
== BUTTON_CHECKED
))
238 BUTTON_CheckAutoRadioButton( wndPtr
);
243 return infoPtr
->state
;
249 if (infoPtr
->state
& BUTTON_HIGHLIGHTED
) break;
250 infoPtr
->state
|= BUTTON_HIGHLIGHTED
;
254 if (!(infoPtr
->state
& BUTTON_HIGHLIGHTED
)) break;
255 infoPtr
->state
&= ~BUTTON_HIGHLIGHTED
;
257 PAINT_BUTTON( wndPtr
, style
, ODA_SELECT
);
261 return DefWindowProcA(hWnd
, uMsg
, wParam
, lParam
);
267 /**********************************************************************
268 * Push Button Functions
271 static void PB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
)
276 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
278 GetClientRect( wndPtr
->hwndSelf
, &rc
);
280 /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */
281 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
282 BUTTON_SEND_CTLCOLOR( wndPtr
, hDC
);
283 hOldPen
= (HPEN
)SelectObject(hDC
, GetSysColorPen(COLOR_WINDOWFRAME
));
284 hOldBrush
=(HBRUSH
)SelectObject(hDC
,GetSysColorBrush(COLOR_BTNFACE
));
285 SetBkMode(hDC
, TRANSPARENT
);
286 Rectangle(hDC
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
287 if (action
== ODA_DRAWENTIRE
)
289 SetPixel( hDC
, rc
.left
, rc
.top
, GetSysColor(COLOR_WINDOW
) );
290 SetPixel( hDC
, rc
.left
, rc
.bottom
-1, GetSysColor(COLOR_WINDOW
) );
291 SetPixel( hDC
, rc
.right
-1, rc
.top
, GetSysColor(COLOR_WINDOW
) );
292 SetPixel( hDC
, rc
.right
-1, rc
.bottom
-1, GetSysColor(COLOR_WINDOW
));
294 InflateRect( &rc
, -1, -1 );
296 if ((wndPtr
->dwStyle
& 0x000f) == BS_DEFPUSHBUTTON
)
298 Rectangle(hDC
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
299 InflateRect( &rc
, -1, -1 );
302 if (infoPtr
->state
& BUTTON_HIGHLIGHTED
)
304 /* draw button shadow: */
305 SelectObject(hDC
, GetSysColorBrush(COLOR_BTNSHADOW
));
306 PatBlt(hDC
, rc
.left
, rc
.top
, 1, rc
.bottom
-rc
.top
, PATCOPY
);
307 PatBlt(hDC
, rc
.left
, rc
.top
, rc
.right
-rc
.left
, 1, PATCOPY
);
308 rc
.left
+= 2; /* To position the text down and right */
311 rc
.right
++, rc
.bottom
++;
312 DrawEdge( hDC
, &rc
, EDGE_RAISED
, BF_RECT
);
313 rc
.right
--, rc
.bottom
--;
316 /* draw button label, if any: */
317 if (wndPtr
->text
&& wndPtr
->text
[0])
320 GetObjectA( GetSysColorBrush(COLOR_BTNFACE
), sizeof(lb
), &lb
);
321 if (wndPtr
->dwStyle
& WS_DISABLED
&&
322 GetSysColor(COLOR_GRAYTEXT
)==lb
.lbColor
)
323 /* don't write gray text on gray bkg */
324 PB_PaintGrayOnGray(hDC
,infoPtr
->hFont
,&rc
,wndPtr
->text
);
327 SetTextColor( hDC
, (wndPtr
->dwStyle
& WS_DISABLED
) ?
328 GetSysColor(COLOR_GRAYTEXT
) :
329 GetSysColor(COLOR_BTNTEXT
) );
330 DrawTextA( hDC
, wndPtr
->text
, -1, &rc
,
331 DT_SINGLELINE
| DT_CENTER
| DT_VCENTER
);
332 /* do we have the focus? */
333 if (infoPtr
->state
& BUTTON_HASFOCUS
)
335 RECT r
= { 0, 0, 0, 0 };
338 DrawTextA( hDC
, wndPtr
->text
, -1, &r
,
339 DT_SINGLELINE
| DT_CALCRECT
);
340 xdelta
= ((rc
.right
- rc
.left
) - (r
.right
- r
.left
) - 1) / 2;
341 ydelta
= ((rc
.bottom
- rc
.top
) - (r
.bottom
- r
.top
) - 1) / 2;
342 if (xdelta
< 0) xdelta
= 0;
343 if (ydelta
< 0) ydelta
= 0;
344 InflateRect( &rc
, -xdelta
, -ydelta
);
345 DrawFocusRect( hDC
, &rc
);
350 SelectObject( hDC
, hOldPen
);
351 SelectObject( hDC
, hOldBrush
);
355 /**********************************************************************
356 * Push Button sub function [internal]
357 * using a raster brush to avoid gray text on gray background
360 void PB_PaintGrayOnGray(HDC hDC
,HFONT hFont
,RECT
*rc
,char *text
)
362 static const int Pattern
[] = {0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55};
363 HBITMAP hbm
= CreateBitmap( 8, 8, 1, 1, Pattern
);
364 HDC hdcMem
= CreateCompatibleDC(hDC
);
370 DrawTextA( hDC
, text
, -1, &rect
, DT_SINGLELINE
| DT_CALCRECT
);
372 rect
.left
=(rc
->right
-rect
.right
)/2; /* for centering text bitmap */
373 rect
.top
=(rc
->bottom
-rect
.bottom
)/2;
374 hbmMem
= CreateCompatibleBitmap( hDC
,rect
.right
,rect
.bottom
);
375 SelectObject( hdcMem
, hbmMem
);
376 hBr
= SelectObject( hdcMem
, CreatePatternBrush(hbm
) );
378 PatBlt( hdcMem
,0,0,rect
.right
,rect
.bottom
,WHITENESS
);
379 if (hFont
) SelectObject( hdcMem
, hFont
);
380 DrawTextA( hdcMem
, text
, -1, &rc2
, DT_SINGLELINE
);
381 PatBlt( hdcMem
,0,0,rect
.right
,rect
.bottom
,0xFA0089);
382 DeleteObject( SelectObject( hdcMem
,hBr
) );
383 BitBlt(hDC
,rect
.left
,rect
.top
,rect
.right
,rect
.bottom
,hdcMem
,0,0,0x990000);
385 DeleteObject( hbmMem
);
389 /**********************************************************************
390 * Check Box & Radio Button Functions
393 static void CB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
)
395 RECT rbox
, rtext
, client
;
398 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
401 GetClientRect(wndPtr
->hwndSelf
, &client
);
402 rbox
= rtext
= client
;
404 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
406 /* Something is still not right, checkboxes (and edit controls)
407 * in wsping32 have white backgrounds instead of dark grey.
408 * BUTTON_SEND_CTLCOLOR() is even worse since it returns 0 in this
409 * particular case and the background is not painted at all.
412 hBrush
= GetControlBrush16( wndPtr
->hwndSelf
, hDC
, CTLCOLOR_BTN
);
414 if (wndPtr
->dwStyle
& BS_LEFTTEXT
)
416 /* magic +4 is what CTL3D expects */
418 rtext
.right
-= checkBoxWidth
+ 4;
419 rbox
.left
= rbox
.right
- checkBoxWidth
;
423 rtext
.left
+= checkBoxWidth
+ 4;
424 rbox
.right
= checkBoxWidth
;
427 /* Draw the check-box bitmap */
429 if (wndPtr
->text
) textlen
= strlen( wndPtr
->text
);
430 if (action
== ODA_DRAWENTIRE
|| action
== ODA_SELECT
)
432 HDC hMemDC
= CreateCompatibleDC( hDC
);
434 delta
= (rbox
.bottom
- rbox
.top
- checkBoxHeight
) >> 1;
436 if (action
== ODA_SELECT
) FillRect( hDC
, &rbox
, hBrush
);
437 else FillRect( hDC
, &client
, hBrush
);
439 if (infoPtr
->state
& BUTTON_HIGHLIGHTED
) x
+= 2 * checkBoxWidth
;
440 if (infoPtr
->state
& (BUTTON_CHECKED
| BUTTON_3STATE
)) x
+= checkBoxWidth
;
441 if (((wndPtr
->dwStyle
& 0x0f) == BS_RADIOBUTTON
) ||
442 ((wndPtr
->dwStyle
& 0x0f) == BS_AUTORADIOBUTTON
)) y
+= checkBoxHeight
;
443 else if (infoPtr
->state
& BUTTON_3STATE
) y
+= 2 * checkBoxHeight
;
445 SelectObject( hMemDC
, hbitmapCheckBoxes
);
446 BitBlt( hDC
, rbox
.left
, rbox
.top
+ delta
, checkBoxWidth
,
447 checkBoxHeight
, hMemDC
, x
, y
, SRCCOPY
);
450 if( textlen
&& action
!= ODA_SELECT
)
452 if (wndPtr
->dwStyle
& WS_DISABLED
)
453 SetTextColor( hDC
, GetSysColor(COLOR_GRAYTEXT
) );
454 DrawTextA( hDC
, wndPtr
->text
, textlen
, &rtext
,
455 DT_SINGLELINE
| DT_VCENTER
);
456 textlen
= 0; /* skip DrawText() below */
460 if ((action
== ODA_FOCUS
) ||
461 ((action
== ODA_DRAWENTIRE
) && (infoPtr
->state
& BUTTON_HASFOCUS
)))
463 /* again, this is what CTL3D expects */
467 DrawTextA( hDC
, wndPtr
->text
, textlen
, &rbox
,
468 DT_SINGLELINE
| DT_CALCRECT
);
469 textlen
= rbox
.bottom
- rbox
.top
;
470 delta
= ((rtext
.bottom
- rtext
.top
) - textlen
)/2;
471 rbox
.bottom
= (rbox
.top
= rtext
.top
+ delta
- 1) + textlen
+ 2;
472 textlen
= rbox
.right
- rbox
.left
;
473 rbox
.right
= (rbox
.left
+= --rtext
.left
) + textlen
+ 2;
474 IntersectRect(&rbox
, &rbox
, &rtext
);
475 DrawFocusRect( hDC
, &rbox
);
480 /**********************************************************************
481 * BUTTON_CheckAutoRadioButton
483 * wndPtr is checked, uncheck every other auto radio button in group
485 static void BUTTON_CheckAutoRadioButton( WND
*wndPtr
)
487 HWND parent
, sibling
, start
;
488 if (!(wndPtr
->dwStyle
& WS_CHILD
)) return;
489 parent
= wndPtr
->parent
->hwndSelf
;
490 /* assure that starting control is not disabled or invisible */
491 start
= sibling
= GetNextDlgGroupItem( parent
, wndPtr
->hwndSelf
, TRUE
);
495 if ((wndPtr
->hwndSelf
!= sibling
) &&
496 ((WIN_FindWndPtr(sibling
)->dwStyle
& 0x0f) == BS_AUTORADIOBUTTON
))
497 SendMessageA( sibling
, BM_SETCHECK
, BUTTON_UNCHECKED
, 0 );
498 sibling
= GetNextDlgGroupItem( parent
, sibling
, FALSE
);
499 } while (sibling
!= start
);
503 /**********************************************************************
504 * Group Box Functions
507 static void GB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
)
510 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
512 if (action
!= ODA_DRAWENTIRE
) return;
514 BUTTON_SEND_CTLCOLOR( wndPtr
, hDC
);
516 GetClientRect( wndPtr
->hwndSelf
, &rc
);
517 if (TWEAK_WineLook
== WIN31_LOOK
) {
518 HPEN hPrevPen
= SelectObject( hDC
,
519 GetSysColorPen(COLOR_WINDOWFRAME
));
520 HBRUSH hPrevBrush
= SelectObject( hDC
,
521 GetStockObject(NULL_BRUSH
) );
523 Rectangle( hDC
, rc
.left
, rc
.top
+ 2, rc
.right
- 1, rc
.bottom
- 1 );
524 SelectObject( hDC
, hPrevBrush
);
525 SelectObject( hDC
, hPrevPen
);
531 SelectObject (hDC
, infoPtr
->hFont
);
532 GetTextMetricsA (hDC
, &tm
);
533 rcFrame
.top
+= (tm
.tmHeight
/ 2) - 1;
534 DrawEdge (hDC
, &rcFrame
, EDGE_ETCHED
, BF_RECT
);
539 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
540 if (wndPtr
->dwStyle
& WS_DISABLED
)
541 SetTextColor( hDC
, GetSysColor(COLOR_GRAYTEXT
) );
543 DrawTextA( hDC
, wndPtr
->text
, -1, &rc
, DT_SINGLELINE
| DT_NOCLIP
);
548 /**********************************************************************
549 * User Button Functions
552 static void UB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
)
556 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
558 if (action
== ODA_SELECT
) return;
560 GetClientRect( wndPtr
->hwndSelf
, &rc
);
562 if (infoPtr
->hFont
) SelectObject( hDC
, infoPtr
->hFont
);
563 hBrush
= GetControlBrush16( wndPtr
->hwndSelf
, hDC
, CTLCOLOR_BTN
);
565 FillRect( hDC
, &rc
, hBrush
);
566 if ((action
== ODA_FOCUS
) ||
567 ((action
== ODA_DRAWENTIRE
) && (infoPtr
->state
& BUTTON_HASFOCUS
)))
568 DrawFocusRect( hDC
, &rc
);
572 /**********************************************************************
573 * Ownerdrawn Button Functions
576 static void OB_Paint( WND
*wndPtr
, HDC hDC
, WORD action
)
578 BUTTONINFO
*infoPtr
= (BUTTONINFO
*)wndPtr
->wExtra
;
581 dis
.CtlType
= ODT_BUTTON
;
582 dis
.CtlID
= wndPtr
->wIDmenu
;
584 dis
.itemAction
= action
;
585 dis
.itemState
= ((infoPtr
->state
& BUTTON_HASFOCUS
) ? ODS_FOCUS
: 0) |
586 ((infoPtr
->state
& BUTTON_HIGHLIGHTED
) ? ODS_SELECTED
: 0) |
587 ((wndPtr
->dwStyle
& WS_DISABLED
) ? ODS_DISABLED
: 0);
588 dis
.hwndItem
= wndPtr
->hwndSelf
;
591 GetClientRect( wndPtr
->hwndSelf
, &dis
.rcItem
);
592 SendMessageA( GetParent(wndPtr
->hwndSelf
), WM_DRAWITEM
,
593 wndPtr
->wIDmenu
, (LPARAM
)&dis
);