diff --git a/reactos/dll/win32/user32/controls/button.c b/reactos/dll/win32/user32/controls/button.c index ff806fe3526..09f0ba73158 100644 --- a/reactos/dll/win32/user32/controls/button.c +++ b/reactos/dll/win32/user32/controls/button.c @@ -72,7 +72,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(button); #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)) +#define UISTATE_GWL_OFFSET (HIMAGE_GWL_OFFSET+sizeof(HFONT)) +#define NB_EXTRA_BYTES (UISTATE_GWL_OFFSET+sizeof(LONG)) /* Button state values */ #define BUTTON_UNCHECKED 0x00 @@ -179,6 +180,16 @@ __inline static void set_button_state( HWND hwnd, LONG state ) SetWindowLongW( hwnd, STATE_GWL_OFFSET, state ); } +static __inline void set_ui_state( HWND hwnd, LONG flags ) +{ + SetWindowLongW( hwnd, UISTATE_GWL_OFFSET, flags ); +} + +static __inline LONG get_ui_state( HWND hwnd ) +{ + return GetWindowLongPtrW( hwnd, UISTATE_GWL_OFFSET ); +} + __inline static HFONT get_button_font( HWND hwnd ) { return (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ); @@ -214,6 +225,27 @@ __inline static WCHAR *get_button_text( HWND hwnd ) return buffer; } +/* Retrieve the UI state for the control */ +static BOOL button_update_uistate(HWND hwnd, BOOL unicode) +{ + LONG flags, prevflags; + + if (unicode) + flags = DefWindowProcW(hwnd, WM_QUERYUISTATE, 0, 0); + else + flags = DefWindowProcA(hwnd, WM_QUERYUISTATE, 0, 0); + + prevflags = get_ui_state(hwnd); + + if (prevflags != flags) + { + set_ui_state(hwnd, flags); + return TRUE; + } + + return FALSE; +} + /*********************************************************************** * ButtonWndProc_common */ @@ -260,6 +292,7 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg, if (btn_type >= MAX_BTN_TYPE) return -1; /* abort */ set_button_state( hWnd, BUTTON_UNCHECKED ); + button_update_uistate( hWnd, unicode ); return 0; case WM_ERASEBKGND: @@ -530,6 +563,16 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg, paint_button( hWnd, btn_type, ODA_SELECT ); break; + case WM_UPDATEUISTATE: + if (unicode) + DefWindowProcW(hWnd, uMsg, wParam, lParam); + else + DefWindowProcA(hWnd, uMsg, wParam, lParam); + + if (button_update_uistate(hWnd, unicode)) + paint_button( hWnd, btn_type, ODA_DRAWENTIRE ); + break; + case WM_NCHITTEST: if(btn_type == BS_GROUPBOX) return HTTRANSPARENT; /* fall through */ @@ -540,6 +583,7 @@ static LRESULT WINAPI ButtonWndProc_common(HWND hWnd, UINT uMsg, return 0; } + /*********************************************************************** * ButtonWndProcW * The button window procedure. This is just a wrapper which locks @@ -643,6 +687,9 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc) } DrawTextW(hdc, text, -1, &r, dtStyle | DT_CALCRECT); HeapFree( GetProcessHeap(), 0, text ); + + if (get_ui_state( hwnd ) & UISF_HIDEACCEL) + dtStyle |= DT_HIDEPREFIX; break; case BS_ICON: @@ -760,6 +807,9 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, RECT *rc) if (!(text = get_button_text( hwnd ))) return; lp = (LPARAM)text; wp = (WPARAM)dtFlags; + + if (dtFlags & DT_HIDEPREFIX) + flags |= DSS_HIDEPREFIX; break; case BS_ICON: @@ -858,9 +908,12 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action ) if (state & BUTTON_HASFOCUS) { - InflateRect( &focus_rect, -1, -1 ); - IntersectRect(&focus_rect, &focus_rect, &rc); - DrawFocusRect( hDC, &focus_rect ); + if (!(get_ui_state(hwnd) & UISF_HIDEFOCUS)) + { + InflateRect( &focus_rect, -1, -1 ); + IntersectRect(&focus_rect, &focus_rect, &rc); + DrawFocusRect( hDC, &focus_rect ); + } } cleanup: @@ -990,10 +1043,13 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) if ((action == ODA_FOCUS) || ((action == ODA_DRAWENTIRE) && (state & BUTTON_HASFOCUS))) { - rtext.left--; - rtext.right++; - IntersectRect(&rtext, &rtext, &client); - DrawFocusRect( hDC, &rtext ); + if (!(get_ui_state(hwnd) & UISF_HIDEFOCUS)) + { + rtext.left--; + rtext.right++; + IntersectRect(&rtext, &rtext, &client); + DrawFocusRect( hDC, &rtext ); + } } } @@ -1099,7 +1155,10 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action ) FillRect( hDC, &rc, hBrush ); if ((action == ODA_FOCUS) || ((action == ODA_DRAWENTIRE) && (state & BUTTON_HASFOCUS))) - DrawFocusRect( hDC, &rc ); + { + if (!(get_ui_state(hwnd) & UISF_HIDEFOCUS)) + DrawFocusRect( hDC, &rc ); + } } diff --git a/reactos/dll/win32/user32/controls/combo.c b/reactos/dll/win32/user32/controls/combo.c index 9525d7e4154..ac4ffe88b64 100644 --- a/reactos/dll/win32/user32/controls/combo.c +++ b/reactos/dll/win32/user32/controls/combo.c @@ -139,6 +139,17 @@ static BOOL COMBO_Init() return FALSE; } + +/* Retrieve the UI state for the control */ +static BOOL COMBO_update_uistate(LPHEADCOMBO lphc) +{ + LONG prev_flags; + + prev_flags = lphc->UIState; + lphc->UIState = DefWindowProcW(lphc->self, WM_QUERYUISTATE, 0, 0); + return prev_flags != lphc->UIState; +} + /*********************************************************************** * COMBO_NCCreate */ @@ -151,6 +162,8 @@ static LRESULT COMBO_NCCreate(HWND hwnd, LONG style) lphc->self = hwnd; SetWindowLongPtrW( hwnd, 0, (LONG_PTR)lphc ); + COMBO_update_uistate(lphc); + /* some braindead apps do try to use scrollbar/border flags */ lphc->dwStyle = style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL); @@ -817,7 +830,8 @@ static void CBPaintText( &rectEdit, pText ? pText : empty_stringW , size, NULL ); - if(lphc->wState & CBF_FOCUSED && !(lphc->wState & CBF_DROPPED)) + if(lphc->wState & CBF_FOCUSED && !(lphc->wState & CBF_DROPPED) && + !(lphc->UIState & UISF_HIDEFOCUS)) DrawFocusRect( hdc, &rectEdit ); } @@ -2337,6 +2351,21 @@ static LRESULT ComboWndProc_common( HWND hwnd, UINT message, if( lphc->wState & CBF_EDIT ) return SendMessageW(lphc->hWndEdit, EM_LIMITTEXT, wParam, lParam); break; + + case WM_UPDATEUISTATE: + if (unicode) + DefWindowProcW(lphc->self, message, wParam, lParam); + else + DefWindowProcA(lphc->self, message, wParam, lParam); + + if (COMBO_update_uistate(lphc)) + { + /* redraw text */ + if( !(lphc->wState & CBF_EDIT) ) + NtUserInvalidateRect(lphc->self, &lphc->textRect, TRUE); + } + break; + default: if (message >= WM_USER) WARN("unknown msg WM_USER+%04x wp=%04x lp=%08lx\n", diff --git a/reactos/dll/win32/user32/controls/listbox.c b/reactos/dll/win32/user32/controls/listbox.c index 19785538af5..f74bba65574 100644 --- a/reactos/dll/win32/user32/controls/listbox.c +++ b/reactos/dll/win32/user32/controls/listbox.c @@ -106,6 +106,7 @@ typedef struct HFONT font; /* Current font */ LCID locale; /* Current locale for string comparisons */ LPHEADCOMBO lphc; /* ComboLBox */ + LONG UIState; } LB_DESCR; @@ -603,7 +604,10 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, if (!item) { if (action == ODA_FOCUS) - DrawFocusRect( hdc, rect ); + { + if (!(descr->UIState & UISF_HIDEFOCUS)) + DrawFocusRect( hdc, rect ); + } else FIXME("called with an out of bounds index %d(%d) in owner draw, Not good.\n",index,descr->nb_items); return; @@ -643,7 +647,8 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, if (action == ODA_FOCUS) { - DrawFocusRect( hdc, rect ); + if (!(descr->UIState & UISF_HIDEFOCUS)) + DrawFocusRect( hdc, rect ); return; } if (item && item->selected) @@ -678,7 +683,8 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, } if (!ignoreFocus && (descr->focus_item == index) && (descr->caret_on) && - (descr->in_focus)) DrawFocusRect( hdc, rect ); + (descr->in_focus) && + !(descr->UIState & UISF_HIDEFOCUS)) DrawFocusRect( hdc, rect ); } } @@ -2545,6 +2551,16 @@ static LRESULT LISTBOX_HandleChar( LB_DESCR *descr, WCHAR charW ) return 0; } +/* Retrieve the UI state for the control */ +static BOOL LISTBOX_update_uistate(LB_DESCR *descr) +{ + LONG prev_flags; + + prev_flags = descr->UIState; + descr->UIState = DefWindowProcW(descr->self, WM_QUERYUISTATE, 0, 0); + return prev_flags != descr->UIState; +} + /*********************************************************************** * LISTBOX_Create @@ -2605,6 +2621,8 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc ) SetWindowLongPtrW( descr->self, 0, (LONG_PTR)descr ); + LISTBOX_update_uistate(descr); + /* if (wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) descr->style &= ~LBS_NOTIFY; */ if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL; @@ -3405,6 +3423,20 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg, if (lphc) return 0; break; + case WM_UPDATEUISTATE: + if (unicode) + DefWindowProcW(descr->self, msg, wParam, lParam); + else + DefWindowProcA(descr->self, msg, wParam, lParam); + + if (LISTBOX_update_uistate(descr)) + { + /* redraw text */ + if (descr->focus_item != -1) + LISTBOX_DrawFocusRect( descr, descr->in_focus ); + } + break; + default: if ((msg >= WM_USER) && (msg < 0xc000)) WARN("[%p]: unknown msg %04x wp %08x lp %08lx\n", diff --git a/reactos/dll/win32/user32/controls/static.c b/reactos/dll/win32/user32/controls/static.c index 39d27404273..5433d9be2ad 100644 --- a/reactos/dll/win32/user32/controls/static.c +++ b/reactos/dll/win32/user32/controls/static.c @@ -63,7 +63,8 @@ static COLORREF color_3dshadow, color_3ddkshadow, color_3dhighlight; /* offsets for GetWindowLong for static private information */ #define HFONT_GWL_OFFSET 0 #define HICON_GWL_OFFSET (sizeof(HFONT)) -#define STATIC_EXTRA_BYTES (HICON_GWL_OFFSET + sizeof(HICON)) +#define UISTATE_GWL_OFFSET (HICON_GWL_OFFSET+sizeof(HICON)) +#define STATIC_EXTRA_BYTES (UISTATE_GWL_OFFSET + sizeof(LONG)) typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style ); @@ -115,6 +116,16 @@ const struct builtin_class_descr STATIC_builtin_class = #endif }; +static __inline void set_ui_state( HWND hwnd, LONG flags ) +{ + SetWindowLongW( hwnd, UISTATE_GWL_OFFSET, flags ); +} + +static __inline LONG get_ui_state( HWND hwnd ) +{ + return GetWindowLongPtrW( hwnd, UISTATE_GWL_OFFSET ); +} + static void setup_clipping(HWND hwnd, HDC hdc, HRGN *orig) { RECT rc; @@ -143,6 +154,27 @@ static void restore_clipping(HDC hdc, HRGN hrgn) DeleteObject(hrgn); } +/* Retrieve the UI state for the control */ +static BOOL STATIC_update_uistate(HWND hwnd, BOOL unicode) +{ + LONG flags, prevflags; + + if (unicode) + flags = DefWindowProcW(hwnd, WM_QUERYUISTATE, 0, 0); + else + flags = DefWindowProcA(hwnd, WM_QUERYUISTATE, 0, 0); + + prevflags = get_ui_state(hwnd); + + if (prevflags != flags) + { + set_ui_state(hwnd, flags); + return TRUE; + } + + return FALSE; +} + /*********************************************************************** * STATIC_SetIcon * @@ -424,6 +456,7 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, ERR("Unknown style 0x%02lx\n", style ); return -1; } + STATIC_update_uistate(hwnd, unicode); STATIC_InitColours(); break; @@ -613,6 +646,18 @@ static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, STATIC_TryPaintFcn( hwnd, full_style ); break; + case WM_UPDATEUISTATE: + if (unicode) + DefWindowProcW(hwnd, uMsg, wParam, lParam); + else + DefWindowProcA(hwnd, uMsg, wParam, lParam); + + if (STATIC_update_uistate(hwnd, unicode) && hasTextStyle( full_style )) + { + RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN ); + } + break; + default: return unicode ? DefWindowProcW(hwnd, uMsg, wParam, lParam) : DefWindowProcA(hwnd, uMsg, wParam, lParam); @@ -666,7 +711,7 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) RECT rc; HBRUSH hBrush; HFONT hFont, hOldFont = NULL; - WORD wFormat; + DWORD wFormat; INT len, buf_size; WCHAR *text; @@ -700,6 +745,8 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style ) if (style & SS_NOPREFIX) wFormat |= DT_NOPREFIX; + else if (get_ui_state(hwnd) & UISF_HIDEACCEL) + wFormat |= DT_HIDEPREFIX; if ((style & SS_TYPEMASK) != SS_SIMPLE) { diff --git a/reactos/dll/win32/user32/include/controls.h b/reactos/dll/win32/user32/include/controls.h index 772424a14d3..fb7499f7390 100644 --- a/reactos/dll/win32/user32/include/controls.h +++ b/reactos/dll/win32/user32/include/controls.h @@ -103,6 +103,7 @@ typedef struct INT fixedOwnerDrawHeight; INT droppedWidth; /* last two are not used unless set */ INT editHeight; /* explicitly */ + LONG UIState; } HEADCOMBO,*LPHEADCOMBO; /* Note, that CBS_DROPDOWNLIST style is actually (CBS_SIMPLE | CBS_DROPDOWN) */