From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/menu.c | 165 ++------------------------------ dlls/win32u/menu.c | 179 +++++++++++++++++++++++++++++++++++ dlls/win32u/message.c | 2 + dlls/win32u/win32u_private.h | 3 + dlls/win32u/window.c | 2 +- include/ntuser.h | 1 + 6 files changed, 193 insertions(+), 159 deletions(-)
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 2d01e01872c..f5b74a24c25 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -1196,62 +1196,6 @@ static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, UINT max_height ) }
-static void draw_scroll_arrow(HDC hdc, int x, int top, int height, BOOL up, BOOL enabled) -{ - RECT rect, light_rect; - HBRUSH brush = GetSysColorBrush( enabled ? COLOR_BTNTEXT : COLOR_BTNSHADOW ); - HBRUSH light = GetSysColorBrush( COLOR_3DLIGHT ); - - if (!up) - { - top = top + height; - if (!enabled) - { - SetRect( &rect, x + 1, top, x + 2, top + 1); - FillRect( hdc, &rect, light ); - } - top--; - } - - SetRect( &rect, x, top, x + 1, top + 1); - while (height--) - { - FillRect( hdc, &rect, brush ); - if (!enabled && !up && height) - { - SetRect( &light_rect, rect.right, rect.top, rect.right + 2, rect.bottom ); - FillRect( hdc, &light_rect, light ); - } - InflateRect( &rect, 1, 0 ); - OffsetRect( &rect, 0, up ? 1 : -1 ); - } - - if (!enabled && up) - { - rect.left += 2; - FillRect( hdc, &rect, light ); - } -} - -/*********************************************************************** - * MENU_DrawScrollArrows - * - * Draw scroll arrows. - */ -static void -MENU_DrawScrollArrows(const POPUPMENU *menu, HDC hdc) -{ - UINT full_height = get_scroll_arrow_height( menu ); - UINT arrow_height = full_height / 3; - BOOL at_end = menu->nScrollPos + menu->items_rect.bottom - menu->items_rect.top == menu->nTotalHeight; - - draw_scroll_arrow( hdc, menu->Width / 3, arrow_height, arrow_height, - TRUE, menu->nScrollPos != 0); - draw_scroll_arrow( hdc, menu->Width / 3, menu->Height - 2 * arrow_height, arrow_height, - FALSE, !at_end ); -} - - /*********************************************************************** * draw_popup_arrow * @@ -1634,66 +1578,6 @@ done: }
-/*********************************************************************** - * MENU_DrawPopupMenu - * - * Paint a popup menu. - */ -static void MENU_DrawPopupMenu( HWND hwnd, HDC hdc, HMENU hmenu ) -{ - HBRUSH hPrevBrush, brush = GetSysColorBrush( COLOR_MENU ); - RECT rect; - POPUPMENU *menu = MENU_GetMenu( hmenu ); - - TRACE("wnd=%p dc=%p menu=%p\n", hwnd, hdc, hmenu); - - GetClientRect( hwnd, &rect ); - - if (menu && menu->hbrBack) brush = menu->hbrBack; - if ((hPrevBrush = SelectObject( hdc, brush )) - && SelectObject( hdc, get_menu_font(FALSE) )) - { - HPEN hPrevPen; - - Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom ); - - hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) ); - if( hPrevPen ) - { - BOOL flat_menu = FALSE; - - SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0); - if (flat_menu) - FrameRect(hdc, &rect, GetSysColorBrush(COLOR_BTNSHADOW)); - else - DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT); - - if (menu) - { - TRACE("hmenu %p Style %08lx\n", hmenu, menu->dwStyle); - /* draw menu items */ - if (menu->nItems) - { - MENUITEM *item; - UINT u; - - item = menu->items; - for (u = menu->nItems; u > 0; u--, item++) - MENU_DrawMenuItem( hwnd, menu, menu->hwndOwner, hdc, - item, FALSE, ODA_DRAWENTIRE ); - } - /* draw scroll arrows */ - if (menu->bScrolling) - MENU_DrawScrollArrows(menu, hdc); - } - } else - { - SelectObject( hdc, hPrevBrush ); - } - } -} - - /*********************************************************************** * MENU_InitPopup * @@ -3347,40 +3231,8 @@ BOOL WINAPI TrackPopupMenu( HMENU hMenu, UINT wFlags, INT x, INT y, */ LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ) { - TRACE("hwnd=%p msg=0x%04x wp=0x%04Ix lp=0x%08Ix\n", hwnd, message, wParam, lParam); - switch(message) { - case WM_CREATE: - { - CREATESTRUCTW *cs = (CREATESTRUCTW*)lParam; - SetWindowLongPtrW( hwnd, 0, (LONG_PTR)cs->lpCreateParams ); - return 0; - } - - case WM_MOUSEACTIVATE: /* We don't want to be activated */ - return MA_NOACTIVATE; - - case WM_PAINT: - { - PAINTSTRUCT ps; - NtUserBeginPaint( hwnd, &ps ); - MENU_DrawPopupMenu( hwnd, ps.hdc, - (HMENU)GetWindowLongPtrW( hwnd, 0 ) ); - NtUserEndPaint( hwnd, &ps ); - return 0; - } - - case WM_PRINTCLIENT: - { - MENU_DrawPopupMenu( hwnd, (HDC)wParam, - (HMENU)GetWindowLongPtrW( hwnd, 0 ) ); - return 0; - } - - case WM_ERASEBKGND: - return 1; - case WM_DESTROY: /* zero out global pointer in case resident popup window was destroyed. */ if (hwnd == top_popup) { @@ -3389,18 +3241,15 @@ LRESULT WINAPI PopupMenuWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM } break;
+ case WM_CREATE: + case WM_MOUSEACTIVATE: + case WM_PAINT: + case WM_PRINTCLIENT: + case WM_ERASEBKGND: case WM_SHOWWINDOW: - - if( wParam ) - { - if (!GetWindowLongPtrW( hwnd, 0 )) ERR("no menu to display\n"); - } - else - SetWindowLongPtrW( hwnd, 0, 0 ); - break; - case MN_GETHMENU: - return GetWindowLongPtrW( hwnd, 0 ); + return NtUserMessageCall( hwnd, message, wParam, lParam, + NULL, NtUserPopupMenuWndProc, FALSE );
default: return DefWindowProcW( hwnd, message, wParam, lParam ); diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c index b794b9a162a..7825e0f416f 100644 --- a/dlls/win32u/menu.c +++ b/dlls/win32u/menu.c @@ -2226,3 +2226,182 @@ DWORD WINAPI NtUserDrawMenuBarTemp( HWND hwnd, HDC hdc, RECT *rect, HMENU handle if (prev_font) NtGdiSelectFont( hdc, prev_font ); return retvalue; } + +static UINT get_scroll_arrow_height( const POPUPMENU *menu ) +{ + return menucharsize.cy + 4; +} + +static void draw_scroll_arrow( HDC hdc, int x, int top, int height, BOOL up, BOOL enabled ) +{ + RECT rect, light_rect; + HBRUSH brush = get_sys_color_brush( enabled ? COLOR_BTNTEXT : COLOR_BTNSHADOW ); + HBRUSH light = get_sys_color_brush( COLOR_3DLIGHT ); + + if (!up) + { + top = top + height; + if (!enabled) + { + SetRect( &rect, x + 1, top, x + 2, top + 1); + fill_rect( hdc, &rect, light ); + } + top--; + } + + SetRect( &rect, x, top, x + 1, top + 1); + while (height--) + { + fill_rect( hdc, &rect, brush ); + if (!enabled && !up && height) + { + SetRect( &light_rect, rect.right, rect.top, rect.right + 2, rect.bottom ); + fill_rect( hdc, &light_rect, light ); + } + InflateRect( &rect, 1, 0 ); + OffsetRect( &rect, 0, up ? 1 : -1 ); + } + + if (!enabled && up) + { + rect.left += 2; + fill_rect( hdc, &rect, light ); + } +} + +static void draw_scroll_arrows( const POPUPMENU *menu, HDC hdc ) +{ + UINT full_height = get_scroll_arrow_height( menu ); + UINT arrow_height = full_height / 3; + BOOL at_end = menu->nScrollPos + menu->items_rect.bottom - menu->items_rect.top == menu->nTotalHeight; + + draw_scroll_arrow( hdc, menu->Width / 3, arrow_height, arrow_height, + TRUE, menu->nScrollPos != 0); + draw_scroll_arrow( hdc, menu->Width / 3, menu->Height - 2 * arrow_height, arrow_height, + FALSE, !at_end ); +} + +static int frame_rect( HDC hdc, const RECT *rect, HBRUSH hbrush ) +{ + HBRUSH prev_brush; + RECT r = *rect; + + if (IsRectEmpty(&r)) return 0; + if (!(prev_brush = NtGdiSelectBrush( hdc, hbrush ))) return 0; + + NtGdiPatBlt( hdc, r.left, r.top, 1, r.bottom - r.top, PATCOPY ); + NtGdiPatBlt( hdc, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY ); + NtGdiPatBlt( hdc, r.left, r.top, r.right - r.left, 1, PATCOPY ); + NtGdiPatBlt( hdc, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY ); + + NtGdiSelectBrush( hdc, prev_brush ); + return TRUE; +} + +static void draw_popup_menu( HWND hwnd, HDC hdc, HMENU hmenu ) +{ + HBRUSH prev_hrush, brush = get_sys_color_brush( COLOR_MENU ); + POPUPMENU *menu = unsafe_menu_ptr( hmenu ); + RECT rect; + + TRACE( "wnd=%p dc=%p menu=%p\n", hwnd, hdc, hmenu ); + + get_client_rect( hwnd, &rect ); + + if (menu && menu->hbrBack) brush = menu->hbrBack; + if ((prev_hrush = NtGdiSelectBrush( hdc, brush )) + && NtGdiSelectFont( hdc, get_menu_font( FALSE ))) + { + HPEN prev_pen; + + NtGdiRectangle( hdc, rect.left, rect.top, rect.right, rect.bottom ); + + prev_pen = NtGdiSelectPen( hdc, GetStockObject( NULL_PEN )); + if (prev_pen) + { + BOOL flat_menu = FALSE; + + NtUserSystemParametersInfo( SPI_GETFLATMENU, 0, &flat_menu, 0 ); + if (flat_menu) + frame_rect( hdc, &rect, get_sys_color_brush( COLOR_BTNSHADOW )); + else + draw_rect_edge( hdc, &rect, EDGE_RAISED, BF_RECT, 1 ); + + if (menu) + { + TRACE( "hmenu %p Style %08x\n", hmenu, menu->dwStyle ); + /* draw menu items */ + if (menu->nItems) + { + MENUITEM *item; + UINT u; + + item = menu->items; + for (u = menu->nItems; u > 0; u--, item++) + draw_menu_item( hwnd, menu, menu->hwndOwner, hdc, + item, FALSE, ODA_DRAWENTIRE ); + } + if (menu->bScrolling) draw_scroll_arrows( menu, hdc ); + } + } + else + { + NtGdiSelectBrush( hdc, prev_hrush ); + } + } +} + +LRESULT popup_menu_window_proc( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam ) +{ + TRACE( "hwnd=%p msg=0x%04x wp=0x%04lx lp=0x%08lx\n", hwnd, message, wparam, lparam ); + + switch(message) + { + case WM_CREATE: + { + CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam; + NtUserSetWindowLongPtr( hwnd, 0, (LONG_PTR)cs->lpCreateParams, FALSE ); + return 0; + } + + case WM_MOUSEACTIVATE: /* We don't want to be activated */ + return MA_NOACTIVATE; + + case WM_PAINT: + { + PAINTSTRUCT ps; + NtUserBeginPaint( hwnd, &ps ); + draw_popup_menu( hwnd, ps.hdc, (HMENU)get_window_long_ptr( hwnd, 0, FALSE )); + NtUserEndPaint( hwnd, &ps ); + return 0; + } + + case WM_PRINTCLIENT: + { + draw_popup_menu( hwnd, (HDC)wparam, (HMENU)get_window_long_ptr( hwnd, 0, FALSE )); + return 0; + } + + case WM_ERASEBKGND: + return 1; + + case WM_DESTROY: + break; + + case WM_SHOWWINDOW: + if (wparam) + { + if (!get_window_long_ptr( hwnd, 0, FALSE )) ERR( "no menu to display\n" ); + } + else + NtUserSetWindowLongPtr( hwnd, 0, 0, FALSE ); + break; + + case MN_GETHMENU: + return get_window_long_ptr( hwnd, 0, FALSE ); + + default: + return default_window_proc( hwnd, message, wparam, lparam, FALSE ); + } + return 0; +} diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index b41d252457d..cea1a33812a 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2890,6 +2890,8 @@ LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa { switch (type) { + case NtUserPopupMenuWndProc: + return popup_menu_window_proc( hwnd, msg, wparam, lparam ); case NtUserDesktopWindowProc: return desktop_window_proc( hwnd, msg, wparam, lparam ); case NtUserDefWindowProc: diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index cf3e5c75b16..d3f060669a4 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -402,6 +402,8 @@ extern BOOL get_menu_info( HMENU handle, MENUINFO *info ) DECLSPEC_HIDDEN; extern INT get_menu_item_count( HMENU handle ) DECLSPEC_HIDDEN; extern UINT get_menu_state( HMENU handle, UINT item_id, UINT flags ) DECLSPEC_HIDDEN; extern BOOL is_menu( HMENU handle ) DECLSPEC_HIDDEN; +extern LRESULT popup_menu_window_proc( HWND hwnd, UINT message, WPARAM wparam, + LPARAM lparam ) DECLSPEC_HIDDEN; extern BOOL set_window_menu( HWND hwnd, HMENU handle ) DECLSPEC_HIDDEN;
/* message.c */ @@ -473,6 +475,7 @@ extern BOOL is_window_unicode( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL is_window_visible( HWND hwnd ) DECLSPEC_HIDDEN; extern BOOL is_zoomed( HWND hwnd ) DECLSPEC_HIDDEN; extern DWORD get_window_long( HWND hwnd, INT offset ) DECLSPEC_HIDDEN; +extern ULONG_PTR get_window_long_ptr( HWND hwnd, INT offset, BOOL ansi ) DECLSPEC_HIDDEN; extern BOOL get_window_rect( HWND hwnd, RECT *rect, UINT dpi ) DECLSPEC_HIDDEN; enum coords_relative; extern BOOL get_window_rects( HWND hwnd, enum coords_relative relative, RECT *window_rect, diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index f98dabe27f3..94f285de2bb 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1097,7 +1097,7 @@ DWORD get_window_long( HWND hwnd, INT offset ) }
/* see GetWindowLongPtr */ -static ULONG_PTR get_window_long_ptr( HWND hwnd, INT offset, BOOL ansi ) +ULONG_PTR get_window_long_ptr( HWND hwnd, INT offset, BOOL ansi ) { return get_window_long_size( hwnd, offset, sizeof(LONG_PTR), ansi ); } diff --git a/include/ntuser.h b/include/ntuser.h index 9cf26534e10..5f744c24906 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -204,6 +204,7 @@ struct render_synthesized_format_params /* NtUserMessageCall codes */ enum { + NtUserPopupMenuWndProc = 0x029c, NtUserDesktopWindowProc = 0x029d, NtUserDefWindowProc = 0x029e, NtUserCallWindowProc = 0x02ab,