From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/button.c | 104 ++++++++++++++----------------------- dlls/user32/user_private.h | 10 ++++ dlls/win32u/window.c | 10 ++++ include/ntuser.h | 2 + server/protocol.def | 1 + server/window.c | 1 + 6 files changed, 63 insertions(+), 65 deletions(-) diff --git a/dlls/user32/button.c b/dlls/user32/button.c index f4dbec7767c..0ffaa2d32db 100644 --- a/dlls/user32/button.c +++ b/dlls/user32/button.c @@ -45,12 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(button); -/* GetWindowLong offsets for window extra information */ -#define STATE_GWL_OFFSET 0 -#define HFONT_GWL_OFFSET (sizeof(LONG)) -#define HIMAGE_GWL_OFFSET (HFONT_GWL_OFFSET+sizeof(HFONT)) -#define NB_EXTRA_BYTES (HIMAGE_GWL_OFFSET+sizeof(HANDLE)) - /* undocumented flags */ #define BUTTON_NSTATES 0x0F #define BUTTON_BTNPRESSED 0x40 @@ -109,27 +103,6 @@ static const pfPaint btnPaintFunc[MAX_BTN_TYPE] = OB_Paint /* BS_OWNERDRAW */ }; - -static inline LONG get_button_state( HWND hwnd ) -{ - return GetWindowLongW( hwnd, STATE_GWL_OFFSET ); -} - -static inline void set_button_state( HWND hwnd, LONG state ) -{ - SetWindowLongW( hwnd, STATE_GWL_OFFSET, state ); -} - -static inline HFONT get_button_font( HWND hwnd ) -{ - return (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ); -} - -static inline void set_button_font( HWND hwnd, HFONT font ) -{ - SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, (LONG_PTR)font ); -} - static inline UINT get_button_type( LONG window_style ) { return (window_style & BS_TYPEMASK); @@ -168,6 +141,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, HANDLE oldHbitmap; if (!IsWindow( hWnd )) return 0; + if (uMsg == WM_NCCREATE) NtUserSetWindowFNID( hWnd, MAKE_FNID(NTUSER_WNDPROC_BUTTON) ); pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam); @@ -196,7 +170,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */ if (btn_type == BS_USERBUTTON ) NtUserAlterWindowStyle( hWnd, BS_TYPEMASK, BS_PUSHBUTTON ); - set_button_state( hWnd, BST_UNCHECKED ); + set_control_state( hWnd, BST_UNCHECKED ); return 0; case WM_ERASEBKGND: @@ -235,7 +209,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, if (wParam == VK_SPACE) { SendMessageW( hWnd, BM_SETSTATE, TRUE, 0 ); - set_button_state( hWnd, get_button_state( hWnd ) | BUTTON_BTNPRESSED ); + set_control_state( hWnd, get_control_state( hWnd ) | BUTTON_BTNPRESSED ); NtUserSetCapture( hWnd ); } break; @@ -252,7 +226,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, /* fall through */ case WM_LBUTTONDOWN: NtUserSetCapture( hWnd ); - set_button_state( hWnd, get_button_state( hWnd ) | BUTTON_BTNPRESSED ); + set_control_state( hWnd, get_control_state( hWnd ) | BUTTON_BTNPRESSED ); NtUserSetFocus( hWnd ); SendMessageW( hWnd, BM_SETSTATE, TRUE, 0 ); break; @@ -262,10 +236,10 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, break; /* fall through */ case WM_LBUTTONUP: - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); if (!(state & BUTTON_BTNPRESSED)) break; state &= BUTTON_NSTATES; - set_button_state( hWnd, state ); + set_control_state( hWnd, state ); if (!(state & BST_PUSHED)) { NtUserReleaseCapture(); @@ -275,7 +249,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, GetClientRect( hWnd, &rect ); if (uMsg == WM_KEYUP || PtInRect( &rect, pt )) { - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); switch(btn_type) { case BS_AUTOCHECKBOX: @@ -301,11 +275,11 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, case WM_CAPTURECHANGED: TRACE("WM_CAPTURECHANGED %p\n", hWnd); if (hWnd == (HWND)lParam) break; - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); if (state & BUTTON_BTNPRESSED) { state &= BUTTON_NSTATES; - set_button_state( hWnd, state ); + set_control_state( hWnd, state ); if (state & BST_PUSHED) SendMessageW( hWnd, BM_SETSTATE, FALSE, 0 ); } break; @@ -363,22 +337,22 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, } case WM_SETFONT: - set_button_font( hWnd, (HFONT)wParam ); + set_control_font( hWnd, (HFONT)wParam ); if (lParam) NtUserInvalidateRect(hWnd, NULL, TRUE); break; case WM_GETFONT: - return (LRESULT)get_button_font( hWnd ); + return (LRESULT)get_control_font( hWnd ); case WM_SETFOCUS: TRACE("WM_SETFOCUS %p\n",hWnd); - set_button_state( hWnd, get_button_state(hWnd) | BST_FOCUS ); + set_control_state( hWnd, get_control_state(hWnd) | BST_FOCUS ); paint_button( hWnd, btn_type, ODA_FOCUS ); if (style & BS_NOTIFY) BUTTON_NOTIFY_PARENT(hWnd, BN_SETFOCUS); if (((btn_type == BS_RADIOBUTTON) || (btn_type == BS_AUTORADIOBUTTON)) && - !(get_button_state(hWnd) & (BST_CHECKED | BUTTON_BTNPRESSED))) + !(get_control_state(hWnd) & (BST_CHECKED | BUTTON_BTNPRESSED))) { BUTTON_NOTIFY_PARENT(hWnd, BN_CLICKED); } @@ -386,8 +360,8 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, case WM_KILLFOCUS: TRACE("WM_KILLFOCUS %p\n",hWnd); - state = get_button_state( hWnd ); - set_button_state( hWnd, state & ~BST_FOCUS ); + state = get_control_state( hWnd ); + set_control_state( hWnd, state & ~BST_FOCUS ); paint_button( hWnd, btn_type, ODA_FOCUS ); if ((state & BUTTON_BTNPRESSED) && GetCapture() == hWnd) @@ -432,19 +406,19 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, default: return 0; } - oldHbitmap = (HBITMAP)SetWindowLongPtrW( hWnd, HIMAGE_GWL_OFFSET, lParam ); + oldHbitmap = set_control_icon( hWnd, (HBITMAP)lParam ); NtUserInvalidateRect( hWnd, NULL, FALSE ); return (LRESULT)oldHbitmap; case BM_GETIMAGE: - return GetWindowLongPtrW( hWnd, HIMAGE_GWL_OFFSET ); + return (LRESULT)get_control_icon( hWnd ); case BM_GETCHECK: - return get_button_state( hWnd ) & 3; + return get_control_state( hWnd ) & 3; case BM_SETCHECK: if (wParam > maxCheckState[btn_type]) wParam = maxCheckState[btn_type]; - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); if ((btn_type == BS_RADIOBUTTON) || (btn_type == BS_AUTORADIOBUTTON)) { if (wParam) NtUserAlterWindowStyle( hWnd, WS_TABSTOP, WS_TABSTOP ); @@ -452,7 +426,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, } if ((state & 3) != wParam) { - set_button_state( hWnd, (state & ~3) | wParam ); + set_control_state( hWnd, (state & ~3) | wParam ); paint_button( hWnd, btn_type, ODA_SELECT ); NtUserNotifyWinEvent( EVENT_OBJECT_STATECHANGE, hWnd, OBJID_CLIENT, 0 ); @@ -460,14 +434,14 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, break; case BM_GETSTATE: - return get_button_state( hWnd ); + return get_control_state( hWnd ); case BM_SETSTATE: - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); if (wParam) - set_button_state( hWnd, state | BST_PUSHED ); + set_control_state( hWnd, state | BST_PUSHED ); else - set_button_state( hWnd, state & ~BST_PUSHED ); + set_control_state( hWnd, state & ~BST_PUSHED ); paint_button( hWnd, btn_type, ODA_SELECT ); @@ -568,7 +542,7 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc) goto empty_rect; } - if ((hFont = get_button_font( hwnd ))) hPrevFont = SelectObject( hdc, hFont ); + if ((hFont = get_control_font( hwnd ))) hPrevFont = SelectObject( hdc, hFont ); DrawTextW(hdc, text, -1, &r, dtStyle | DT_CALCRECT); if (hPrevFont) SelectObject( hdc, hPrevFont ); HeapFree( GetProcessHeap(), 0, text ); @@ -576,7 +550,7 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc) } case BS_ICON: - if (!GetIconInfo((HICON)GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ), &iconInfo)) + if (!GetIconInfo(get_control_icon( hwnd ), &iconInfo)) goto empty_rect; GetObjectW (iconInfo.hbmColor, sizeof(BITMAP), &bm); @@ -589,7 +563,7 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc) break; case BS_BITMAP: - if (!GetObjectW( (HANDLE)GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ), sizeof(BITMAP), &bm)) + if (!GetObjectW( get_control_icon( hwnd ), sizeof(BITMAP), &bm)) goto empty_rect; r.right = r.left + bm.bmWidth; @@ -664,7 +638,7 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, const RECT *rc) WPARAM wp = 0; HBRUSH hbr = 0; UINT flags = IsWindowEnabled(hwnd) ? DSS_NORMAL : DSS_DISABLED; - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); LONG style = GetWindowLongW( hwnd, GWL_STYLE ); WCHAR *text = NULL; @@ -691,12 +665,12 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, const RECT *rc) case BS_ICON: flags |= DST_ICON; - lp = GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ); + lp = (LPARAM)get_control_icon( hwnd ); break; case BS_BITMAP: flags |= DST_BITMAP; - lp = GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ); + lp = (LPARAM)get_control_icon( hwnd ); break; default: @@ -720,7 +694,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action ) INT oldBkMode; COLORREF oldTxtColor; HFONT hFont; - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); LONG style = GetWindowLongW( hwnd, GWL_STYLE ); BOOL pushedState = (state & BST_PUSHED); HWND parent; @@ -729,7 +703,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action ) GetClientRect( hwnd, &rc ); /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */ - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); parent = GetParent(hwnd); if (!parent) parent = hwnd; SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd ); @@ -809,7 +783,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) int delta, text_offset, checkBoxWidth, checkBoxHeight; UINT dtFlags; HFONT hFont; - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); LONG style = GetWindowLongW( hwnd, GWL_STYLE ); LONG ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE ); HWND parent; @@ -827,7 +801,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) checkBoxWidth = 12 * GetDpiForWindow( hwnd ) / 96 + 1; checkBoxHeight = 12 * GetDpiForWindow( hwnd ) / 96 + 1; - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); GetCharWidthW( hDC, '0', '0', &text_offset ); text_offset /= 2; @@ -969,7 +943,7 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action ) HWND parent; HRGN hrgn; - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); /* GroupBox acts like static control, so it sends CTLCOLORSTATIC */ parent = GetParent(hwnd); if (!parent) parent = hwnd; @@ -1016,12 +990,12 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action ) RECT rc; HBRUSH hBrush; HFONT hFont; - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); HWND parent; GetClientRect( hwnd, &rc); - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); parent = GetParent(hwnd); if (!parent) parent = hwnd; @@ -1057,7 +1031,7 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action ) static void OB_Paint( HWND hwnd, HDC hDC, UINT action ) { - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); DRAWITEMSTRUCT dis; LONG_PTR id = GetWindowLongPtrW( hwnd, GWLP_ID ); HWND parent; @@ -1076,7 +1050,7 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action ) dis.itemData = 0; GetClientRect( hwnd, &dis.rcItem ); - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); parent = GetParent(hwnd); if (!parent) parent = hwnd; SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd ); diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 1302d8decd9..c667a566df9 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -208,4 +208,14 @@ static inline HFONT set_control_font( HWND hwnd, HFONT font ) return (HFONT)NtUserCallHwndParam( hwnd, (LONG_PTR)font, NtUserCallHwndParam_SetControlFont ); } +static inline LONG get_control_state( HWND hwnd ) +{ + return NtUserCallHwndParam( hwnd, 0, NtUserCallHwndParam_GetControlState ); +} + +static inline LONG set_control_state( HWND hwnd, LONG state ) +{ + return NtUserCallHwndParam( hwnd, state, NtUserCallHwndParam_SetControlState ); +} + #endif /* __WINE_USER_PRIVATE_H */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 92b22da29c0..771d82eba05 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -6280,6 +6280,16 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) case NtUserCallHwndParam_SetControlIcon: return server_set_control_info( hwnd, offsetof(struct control_info, icon), param ); + case NtUserCallHwndParam_GetControlState: + { + struct control_info info = {0}; + get_control_info( hwnd, &info ); + return info.state; + } + + case NtUserCallHwndParam_SetControlState: + return server_set_control_info( hwnd, offsetof(struct control_info, state), param ); + default: FIXME( "invalid code %u\n", code ); return 0; diff --git a/include/ntuser.h b/include/ntuser.h index fa1c2a0339e..5aa71c32dd6 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1421,6 +1421,8 @@ enum NtUserCallHwndParam_SetControlFont, NtUserCallHwndParam_GetControlIcon, NtUserCallHwndParam_SetControlIcon, + NtUserCallHwndParam_GetControlState, + NtUserCallHwndParam_SetControlState, }; struct get_window_rects_params diff --git a/server/protocol.def b/server/protocol.def index d917a50fc33..75103c53ccc 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1068,6 +1068,7 @@ struct control_info unsigned int fnid; /* builtin control FNID, or 0 */ user_handle_t font; /* control font handle */ user_handle_t icon; /* control icon handle */ + unsigned int state; /* control state */ }; typedef volatile struct diff --git a/server/window.c b/server/window.c index e5a87c1bd6e..61e8d30fdcd 100644 --- a/server/window.c +++ b/server/window.c @@ -692,6 +692,7 @@ static struct window *create_window( struct window *parent, struct window *owner shared->control.fnid = get_class_fnid( class ); shared->control.icon = 0; shared->control.font = 0; + shared->control.state = 0; } SHARED_WRITE_END; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999