[PATCH v2 4/5] win32u: Move PopupMenuWndProc implementation from user32.
Jacek Caban
wine at gitlab.winehq.org
Tue Jun 14 02:08:29 CDT 2022
From: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
dlls/user32/menu.c | 165 ++-----------------------------
dlls/win32u/menu.c | 181 ++++++++++++++++++++++++++++++++++-
dlls/win32u/message.c | 2 +
dlls/win32u/win32u_private.h | 3 +
dlls/win32u/window.c | 2 +-
include/ntuser.h | 1 +
6 files changed, 194 insertions(+), 160 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..8367af32395 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -567,7 +567,7 @@ BOOL WINAPI NtUserEnableMenuItem( HMENU handle, UINT id, UINT flags )
/* Get the Popupmenu to access the owner menu */
if (!(menu = find_menu_item( handle, id, flags, &pos )))
- return ~0u;
+ return ~0u;
item = &menu->items[pos];
oldflags = item->fState & (MF_GRAYED | MF_DISABLED);
@@ -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,
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/240
More information about the wine-devel
mailing list