win32u: Move PopupMenuWndProc implementation from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
This commit is contained in:
Jacek Caban 2022-06-11 01:42:50 +02:00 committed by Alexandre Julliard
parent e13145c893
commit d4b8ca7853
6 changed files with 194 additions and 160 deletions

View file

@ -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 );

View file

@ -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;
}

View file

@ -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:

View file

@ -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,

View file

@ -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 );
}

View file

@ -204,6 +204,7 @@ struct render_synthesized_format_params
/* NtUserMessageCall codes */
enum
{
NtUserPopupMenuWndProc = 0x029c,
NtUserDesktopWindowProc = 0x029d,
NtUserDefWindowProc = 0x029e,
NtUserCallWindowProc = 0x02ab,