[PATCH 4/5] win32u: Move PopupMenuWndProc implementation from user32.

Jacek Caban wine at gitlab.winehq.org
Mon Jun 13 19:10:53 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           | 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,
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/240



More information about the wine-devel mailing list