win32u: Move NtUserDrawMenuBarTemp implementation from user32.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
This commit is contained in:
Jacek Caban 2022-06-10 20:15:53 +02:00 committed by Alexandre Julliard
parent 05b29423e5
commit af00521e29
11 changed files with 659 additions and 145 deletions

View file

@ -119,8 +119,6 @@ static HMENU top_popup_hmenu;
/* Flag set by EndMenu() to force an exit from menu tracking */
static BOOL fEndMenu = FALSE;
DWORD WINAPI DrawMenuBarTemp(HWND hwnd, HDC hDC, LPRECT lprect, HMENU hMenu, HFONT hFont);
static BOOL is_win_menu_disallowed(HWND hwnd)
{
return (GetWindowLongW(hwnd, GWL_STYLE) & (WS_CHILD | WS_POPUP)) == WS_CHILD;
@ -1198,81 +1196,6 @@ static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, UINT max_height )
}
/***********************************************************************
* MENU_MenuBarCalcSize
*
* FIXME: Word 6 implements its own MDI and its own 'close window' bitmap
* height is off by 1 pixel which causes lengthy window relocations when
* active document window is maximized/restored.
*
* Calculate the size of the menu bar.
*/
static void MENU_MenuBarCalcSize( HDC hdc, LPRECT lprect,
LPPOPUPMENU lppop, HWND hwndOwner )
{
MENUITEM *lpitem;
UINT start, i, helpPos;
int orgX, orgY;
if ((lprect == NULL) || (lppop == NULL)) return;
if (lppop->nItems == 0) return;
TRACE("lprect %p %s\n", lprect, wine_dbgstr_rect( lprect));
/* Start with a 1 pixel top border.
This corresponds to the difference between SM_CYMENU and SM_CYMENUSIZE. */
SetRect(&lppop->items_rect, 0, 0, lprect->right - lprect->left, 1);
start = 0;
helpPos = ~0U;
lppop->textOffset = 0;
while (start < lppop->nItems)
{
lpitem = &lppop->items[start];
orgX = lppop->items_rect.left;
orgY = lppop->items_rect.bottom;
/* Parse items until line break or end of menu */
for (i = start; i < lppop->nItems; i++, lpitem++)
{
if ((helpPos == ~0U) && (lpitem->fType & MF_RIGHTJUSTIFY)) helpPos = i;
if ((i != start) &&
(lpitem->fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break;
TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", orgX, orgY );
debug_print_menuitem (" item: ", lpitem, "");
MENU_CalcItemSize( hdc, lpitem, hwndOwner, orgX, orgY, TRUE, lppop );
if (lpitem->rect.right > lppop->items_rect.right)
{
if (i != start) break;
else lpitem->rect.right = lppop->items_rect.right;
}
lppop->items_rect.bottom = max( lppop->items_rect.bottom, lpitem->rect.bottom );
orgX = lpitem->rect.right;
}
/* Finish the line (set all items to the largest height found) */
while (start < i) lppop->items[start++].rect.bottom = lppop->items_rect.bottom;
}
OffsetRect(&lppop->items_rect, lprect->left, lprect->top);
lppop->Width = lppop->items_rect.right - lppop->items_rect.left;
lppop->Height = lppop->items_rect.bottom - lppop->items_rect.top;
lprect->bottom = lppop->items_rect.bottom;
/* Flush right all items between the MF_RIGHTJUSTIFY and */
/* the last item (if several lines, only move the last line) */
if (helpPos == ~0U) return;
lpitem = &lppop->items[lppop->nItems-1];
orgY = lpitem->rect.top;
orgX = lprect->right - lprect->left;
for (i = lppop->nItems - 1; i >= helpPos; i--, lpitem--) {
if (lpitem->rect.top != orgY) break; /* Other line */
if (lpitem->rect.right >= orgX) break; /* Too far right already */
lpitem->rect.left += orgX - lpitem->rect.right;
lpitem->rect.right = orgX;
orgX = lpitem->rect.left;
}
}
static void draw_scroll_arrow(HDC hdc, int x, int top, int height, BOOL up, BOOL enabled)
{
RECT rect, light_rect;
@ -1787,7 +1710,7 @@ UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd )
return GetSystemMetrics(SM_CYMENU);
}
return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL);
return NtUserDrawMenuBarTemp( hwnd, hDC, lprect, hMenu, NULL );
}
@ -4028,67 +3951,6 @@ BOOL WINAPI DrawMenuBar( HWND hwnd )
return NtUserDrawMenuBar( hwnd );
}
/***********************************************************************
* DrawMenuBarTemp (USER32.@)
*
* UNDOCUMENTED !!
*
* called by W98SE desk.cpl Control Panel Applet
*
* Not 100% sure about the param names, but close.
*/
DWORD WINAPI DrawMenuBarTemp(HWND hwnd, HDC hDC, LPRECT lprect, HMENU hMenu, HFONT hFont)
{
LPPOPUPMENU lppop;
UINT i,retvalue;
HFONT hfontOld = 0;
BOOL flat_menu = FALSE;
SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0);
if (!hMenu)
hMenu = GetMenu(hwnd);
if (!hFont)
hFont = get_menu_font(FALSE);
lppop = MENU_GetMenu( hMenu );
if (lppop == NULL || lprect == NULL)
{
retvalue = GetSystemMetrics(SM_CYMENU);
goto END;
}
TRACE("(%p, %p, %p, %p, %p)\n", hwnd, hDC, lprect, hMenu, hFont);
hfontOld = SelectObject( hDC, hFont);
if (lppop->Height == 0)
MENU_MenuBarCalcSize(hDC, lprect, lppop, hwnd);
lprect->bottom = lprect->top + lppop->Height;
FillRect(hDC, lprect, GetSysColorBrush(flat_menu ? COLOR_MENUBAR : COLOR_MENU) );
SelectObject( hDC, SYSCOLOR_GetPen(COLOR_3DFACE));
MoveToEx( hDC, lprect->left, lprect->bottom, NULL );
LineTo( hDC, lprect->right, lprect->bottom );
if (lppop->nItems == 0)
{
retvalue = GetSystemMetrics(SM_CYMENU);
goto END;
}
for (i = 0; i < lppop->nItems; i++)
MENU_DrawMenuItem( hwnd, lppop, hwnd, hDC, &lppop->items[i], TRUE, ODA_DRAWENTIRE );
retvalue = lppop->Height;
END:
if (hfontOld) SelectObject (hDC, hfontOld);
return retvalue;
}
/***********************************************************************
* EndMenu (USER.187)

View file

@ -194,7 +194,7 @@
@ stdcall DrawIcon(long long long long)
@ stdcall DrawIconEx(long long long long long long long long long) NtUserDrawIconEx
@ stdcall DrawMenuBar(long)
@ stdcall DrawMenuBarTemp(long long ptr long long)
@ stdcall DrawMenuBarTemp(long long ptr long long) NtUserDrawMenuBarTemp
@ stdcall DrawStateA(long long ptr long long long long long long long)
@ stdcall DrawStateW(long long ptr long long long long long long long)
@ stdcall DrawTextA(long str long ptr long)

View file

@ -1103,6 +1103,19 @@ BOOL WINAPI NtGdiSetBrushOrg( HDC hdc, INT x, INT y, POINT *oldorg )
}
BOOL set_viewport_org( HDC hdc, INT x, INT y, POINT *point )
{
DC *dc;
if (!(dc = get_dc_ptr( hdc ))) return FALSE;
if (point) *point = dc->attr->vport_org;
dc->attr->vport_org.x = x;
dc->attr->vport_org.y = y;
release_dc_ptr( dc );
return NtGdiComputeXformCoefficients( hdc );
}
/***********************************************************************
* NtGdiGetTransform (win32u.@)
*

View file

@ -138,7 +138,7 @@ static const signed char ltrb_inner_mono[] = {
-1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
};
static BOOL draw_rect_edge( HDC hdc, RECT *rc, UINT type, UINT flags, UINT width )
BOOL draw_rect_edge( HDC hdc, RECT *rc, UINT type, UINT flags, UINT width )
{
int lbi_offset = 0, lti_offset = 0, rti_offset = 0, rbi_offset = 0;
signed char lt_inner, lt_outer, rb_inner, rb_outer;
@ -1016,7 +1016,7 @@ static void draw_caption_bar( HDC hdc, const RECT *rect, DWORD style, BOOL activ
}
/* Draw the system icon */
static BOOL draw_nc_sys_button( HWND hwnd, HDC hdc, BOOL down )
BOOL draw_nc_sys_button( HWND hwnd, HDC hdc, BOOL down )
{
HICON icon = get_nc_icon_for_window( hwnd );
@ -1122,7 +1122,7 @@ static BOOL draw_push_button( HDC dc, RECT *r, UINT flags )
return TRUE;
}
static BOOL draw_frame_caption( HDC dc, RECT *r, UINT flags )
BOOL draw_frame_caption( HDC dc, RECT *r, UINT flags )
{
RECT rect;
int small_diam = make_square_rect( r, &rect ) - 2;
@ -1181,6 +1181,77 @@ static BOOL draw_frame_caption( HDC dc, RECT *r, UINT flags )
return TRUE;
}
BOOL draw_frame_menu( HDC dc, RECT *r, UINT flags )
{
RECT rect;
int dmall_diam = make_square_rect( r, &rect );
HBRUSH prev_brush;
HPEN prev_pen;
POINT points[6];
int xe, ye;
int xc, yc;
BOOL retval = TRUE;
ULONG count;
int i;
fill_rect( dc, r, GetStockObject( WHITE_BRUSH ));
prev_brush = NtGdiSelectBrush( dc, GetStockObject( BLACK_BRUSH ));
prev_pen = NtGdiSelectPen( dc, GetStockObject( BLACK_PEN ));
switch (flags & 0xff)
{
case DFCS_MENUARROW:
i = 187 * dmall_diam / 750;
points[2].x = rect.left + 468 * dmall_diam/ 750;
points[2].y = rect.top + 352 * dmall_diam/ 750 + 1;
points[0].y = points[2].y - i;
points[1].y = points[2].y + i;
points[0].x = points[1].x = points[2].x - i;
count = 3;
NtGdiPolyPolyDraw( dc, points, &count, 1, NtGdiPolyPolygon );
break;
case DFCS_MENUBULLET:
xe = rect.left;
ye = rect.top + dmall_diam - dmall_diam / 2;
xc = rect.left + dmall_diam - dmall_diam / 2;
yc = rect.top + dmall_diam - dmall_diam / 2;
i = 234 * dmall_diam / 750;
i = i < 1 ? 1 : i;
SetRect( &rect, xc - i + i / 2, yc - i + i / 2, xc + i / 2, yc + i / 2 );
NtGdiArcInternal( NtGdiPie, dc, rect.left, rect.top, rect.right, rect.bottom,
xe, ye, xe, ye );
break;
case DFCS_MENUCHECK:
points[0].x = rect.left + 253 * dmall_diam / 1000;
points[0].y = rect.top + 445 * dmall_diam / 1000;
points[1].x = rect.left + 409 * dmall_diam / 1000;
points[1].y = points[0].y + (points[1].x - points[0].x);
points[2].x = rect.left + 690 * dmall_diam / 1000;
points[2].y = points[1].y - (points[2].x - points[1].x);
points[3].x = points[2].x;
points[3].y = points[2].y + 3 * dmall_diam / 16;
points[4].x = points[1].x;
points[4].y = points[1].y + 3 * dmall_diam / 16;
points[5].x = points[0].x;
points[5].y = points[0].y + 3 * dmall_diam / 16;
count = 6;
NtGdiPolyPolyDraw( dc, points, &count, 1, NtGdiPolyPolygon );
break;
default:
WARN( "Invalid menu; flags=0x%04x\n", flags );
retval = FALSE;
break;
}
NtGdiSelectPen( dc, prev_pen );
NtGdiSelectBrush( dc, prev_brush );
return retval;
}
static void draw_close_button( HWND hwnd, HDC hdc, BOOL down, BOOL grayed )
{
RECT rect;

View file

@ -1160,6 +1160,7 @@ static struct unix_funcs unix_funcs =
NtUserDispatchMessage,
NtUserDragDetect,
NtUserDrawIconEx,
NtUserDrawMenuBarTemp,
NtUserEmptyClipboard,
NtUserEnableMenuItem,
NtUserEndDeferWindowPosEx,

View file

@ -24,7 +24,7 @@
#endif
#define OEMRESOURCE
#include "win32u_private.h"
#include "ntgdi_private.h"
#include "ntuser_private.h"
#include "wine/server.h"
#include "wine/debug.h"
@ -48,6 +48,9 @@ struct accelerator
/* (other menu->FocusedItem values give the position of the focused item) */
#define NO_SELECTED_ITEM 0xffff
/* Space between 2 columns */
#define MENU_COL_SPACE 4
/* macro to test that flags do not indicate bitmap, ownerdraw or separator */
#define IS_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1))
@ -1672,3 +1675,554 @@ UINT get_menu_bar_height( HWND hwnd, UINT width, INT org_x, INT org_y )
NtUserReleaseDC( hwnd, hdc );
return menu->Height;
}
static void draw_popup_arrow( HDC hdc, RECT rect, UINT arrow_width, UINT arrow_height )
{
HDC mem_hdc = NtGdiCreateCompatibleDC( hdc );
HBITMAP prev_bitmap;
prev_bitmap = NtGdiSelectBitmap( mem_hdc, get_arrow_bitmap() );
NtGdiBitBlt( hdc, rect.right - arrow_width - 1,
(rect.top + rect.bottom - arrow_height) / 2,
arrow_width, arrow_height, mem_hdc, 0, 0, SRCCOPY, 0, 0 );
NtGdiSelectBitmap( mem_hdc, prev_bitmap );
NtGdiDeleteObjectApp( mem_hdc );
}
static void draw_bitmap_item( HDC hdc, MENUITEM *item, const RECT *rect,
POPUPMENU *menu, HWND owner, UINT odaction )
{
int w = rect->right - rect->left;
int h = rect->bottom - rect->top;
int bmp_xoffset = 0, left, top;
HBITMAP bmp_to_draw = item->hbmpItem;
HBITMAP bmp = bmp_to_draw;
BITMAP bm;
DWORD rop;
HDC mem_hdc;
/* Check if there is a magic menu item associated with this item */
if (IS_MAGIC_BITMAP( bmp_to_draw ))
{
UINT flags = 0;
WCHAR bmchr = 0;
RECT r;
switch ((INT_PTR)bmp_to_draw)
{
case (INT_PTR)HBMMENU_SYSTEM:
if (item->dwItemData)
{
bmp = (HBITMAP)item->dwItemData;
if (!NtGdiExtGetObjectW( bmp, sizeof(bm), &bm )) return;
}
else
{
static HBITMAP sys_menu_bmp;
if (!sys_menu_bmp)
sys_menu_bmp = LoadImageW( 0, MAKEINTRESOURCEW(OBM_CLOSE), IMAGE_BITMAP, 0, 0, 0 );
bmp = sys_menu_bmp;
if (!NtGdiExtGetObjectW( bmp, sizeof(bm), &bm )) return;
/* only use right half of the bitmap */
bmp_xoffset = bm.bmWidth / 2;
bm.bmWidth -= bmp_xoffset;
}
goto got_bitmap;
case (INT_PTR)HBMMENU_MBAR_RESTORE:
flags = DFCS_CAPTIONRESTORE;
break;
case (INT_PTR)HBMMENU_MBAR_MINIMIZE:
flags = DFCS_CAPTIONMIN;
break;
case (INT_PTR)HBMMENU_MBAR_MINIMIZE_D:
flags = DFCS_CAPTIONMIN | DFCS_INACTIVE;
break;
case (INT_PTR)HBMMENU_MBAR_CLOSE:
flags = DFCS_CAPTIONCLOSE;
break;
case (INT_PTR)HBMMENU_MBAR_CLOSE_D:
flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE;
break;
case (INT_PTR)HBMMENU_CALLBACK:
{
DRAWITEMSTRUCT drawItem;
drawItem.CtlType = ODT_MENU;
drawItem.CtlID = 0;
drawItem.itemID = item->wID;
drawItem.itemAction = odaction;
drawItem.itemState = 0;
if (item->fState & MF_CHECKED) drawItem.itemState |= ODS_CHECKED;
if (item->fState & MF_DEFAULT) drawItem.itemState |= ODS_DEFAULT;
if (item->fState & MF_DISABLED) drawItem.itemState |= ODS_DISABLED;
if (item->fState & MF_GRAYED) drawItem.itemState |= ODS_GRAYED|ODS_DISABLED;
if (item->fState & MF_HILITE) drawItem.itemState |= ODS_SELECTED;
drawItem.hwndItem = (HWND)menu->obj.handle;
drawItem.hDC = hdc;
drawItem.itemData = item->dwItemData;
drawItem.rcItem = *rect;
send_message( owner, WM_DRAWITEM, 0, (LPARAM)&drawItem );
return;
}
break;
case (INT_PTR)HBMMENU_POPUP_CLOSE:
bmchr = 0x72;
break;
case (INT_PTR)HBMMENU_POPUP_RESTORE:
bmchr = 0x32;
break;
case (INT_PTR)HBMMENU_POPUP_MAXIMIZE:
bmchr = 0x31;
break;
case (INT_PTR)HBMMENU_POPUP_MINIMIZE:
bmchr = 0x30;
break;
default:
FIXME( "Magic %p not implemented\n", bmp_to_draw );
return;
}
if (bmchr)
{
/* draw the magic bitmaps using marlett font characters */
/* FIXME: fontsize and the position (x,y) could probably be better */
HFONT hfont, prev_font;
LOGFONTW logfont = { 0, 0, 0, 0, FW_NORMAL, 0, 0, 0, SYMBOL_CHARSET, 0, 0, 0, 0,
{'M','a','r','l','e','t','t'}};
logfont.lfHeight = min( h, w) - 5 ;
TRACE( " height %d rect %s\n", logfont.lfHeight, wine_dbgstr_rect( rect ));
hfont = NtGdiHfontCreate( &logfont, sizeof(logfont), 0, 0, NULL );
prev_font = NtGdiSelectFont( hdc, hfont );
NtGdiExtTextOutW( hdc, rect->left, rect->top + 2, 0, NULL, &bmchr, 1, NULL, 0 );
NtGdiSelectFont( hdc, prev_font );
NtGdiDeleteObjectApp( hfont );
}
else
{
r = *rect;
InflateRect( &r, -1, -1 );
if (item->fState & MF_HILITE) flags |= DFCS_PUSHED;
draw_frame_caption( hdc, &r, flags );
}
return;
}
if (!bmp || !NtGdiExtGetObjectW( bmp, sizeof(bm), &bm )) return;
got_bitmap:
mem_hdc = NtGdiCreateCompatibleDC( hdc );
NtGdiSelectBitmap( mem_hdc, bmp );
/* handle fontsize > bitmap_height */
top = (h>bm.bmHeight) ? rect->top + (h - bm.bmHeight) / 2 : rect->top;
left=rect->left;
rop= ((item->fState & MF_HILITE) && !IS_MAGIC_BITMAP(bmp_to_draw)) ? NOTSRCCOPY : SRCCOPY;
if ((item->fState & MF_HILITE) && item->hbmpItem)
NtGdiGetAndSetDCDword( hdc, NtGdiSetBkColor, get_sys_color( COLOR_HIGHLIGHT ), NULL );
NtGdiBitBlt( hdc, left, top, w, h, mem_hdc, bmp_xoffset, 0, rop, 0, 0 );
NtGdiDeleteObjectApp( mem_hdc );
}
/* Adjust menu item rectangle according to scrolling state */
static void adjust_menu_item_rect( const POPUPMENU *menu, RECT *rect )
{
INT scroll_offset = menu->bScrolling ? menu->nScrollPos : 0;
OffsetRect( rect, menu->items_rect.left, menu->items_rect.top - scroll_offset );
}
/* Draw a single menu item */
static void draw_menu_item( HWND hwnd, POPUPMENU *menu, HWND owner, HDC hdc,
MENUITEM *item, BOOL menu_bar, UINT odaction )
{
UINT arrow_width = 0, arrow_height = 0;
HRGN old_clip = NULL, clip;
BOOL flat_menu = FALSE;
RECT rect, bmprc;
int bkgnd;
TRACE( "%s\n", debugstr_menuitem( item ));
if (!menu_bar)
{
BITMAP bmp;
NtGdiExtGetObjectW( get_arrow_bitmap(), sizeof(bmp), &bmp );
arrow_width = bmp.bmWidth;
arrow_height = bmp.bmHeight;
}
if (item->fType & MF_SYSMENU)
{
if (!is_iconic( hwnd ))
draw_nc_sys_button( hwnd, hdc, item->fState & (MF_HILITE | MF_MOUSESELECT) );
return;
}
TRACE( "rect=%s\n", wine_dbgstr_rect( &item->rect ));
rect = item->rect;
adjust_menu_item_rect( menu, &rect );
if (!intersect_rect( &bmprc, &rect, &menu->items_rect )) /* bmprc is used as a dummy */
return;
NtUserSystemParametersInfo( SPI_GETFLATMENU, 0, &flat_menu, 0 );
bkgnd = (menu_bar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU;
/* Setup colors */
if (item->fState & MF_HILITE)
{
if (menu_bar && !flat_menu)
{
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, get_sys_color(COLOR_MENUTEXT), NULL );
NtGdiGetAndSetDCDword( hdc, NtGdiSetBkColor, get_sys_color(COLOR_MENU), NULL );
}
else
{
if (item->fState & MF_GRAYED)
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, get_sys_color( COLOR_GRAYTEXT ), NULL );
else
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, get_sys_color( COLOR_HIGHLIGHTTEXT ), NULL );
NtGdiGetAndSetDCDword( hdc, NtGdiSetBkColor, get_sys_color( COLOR_HIGHLIGHT ), NULL );
}
}
else
{
if (item->fState & MF_GRAYED)
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, get_sys_color( COLOR_GRAYTEXT ), NULL );
else
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, get_sys_color( COLOR_MENUTEXT ), NULL );
NtGdiGetAndSetDCDword( hdc, NtGdiSetBkColor, get_sys_color( bkgnd ), NULL );
}
old_clip = NtGdiCreateRectRgn( 0, 0, 0, 0 );
if (NtGdiGetRandomRgn( hdc, old_clip, NTGDI_RGN_MIRROR_RTL | 1 ) <= 0)
{
NtGdiDeleteObjectApp( old_clip );
old_clip = NULL;
}
clip = NtGdiCreateRectRgn( menu->items_rect.left, menu->items_rect.top,
menu->items_rect.right, menu->items_rect.bottom );
NtGdiExtSelectClipRgn( hdc, clip, RGN_AND );
NtGdiDeleteObjectApp( clip );
if (item->fType & MF_OWNERDRAW)
{
/*
* Experimentation under Windows reveals that an owner-drawn
* menu is given the rectangle which includes the space it requested
* in its response to WM_MEASUREITEM _plus_ width for a checkmark
* and a popup-menu arrow. This is the value of item->rect.
* Windows will leave all drawing to the application except for
* the popup-menu arrow. Windows always draws that itself, after
* the menu owner has finished drawing.
*/
DRAWITEMSTRUCT dis;
DWORD old_bk, old_text;
dis.CtlType = ODT_MENU;
dis.CtlID = 0;
dis.itemID = item->wID;
dis.itemData = item->dwItemData;
dis.itemState = 0;
if (item->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED;
if (item->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED|ODS_DISABLED;
if (item->fState & MF_HILITE) dis.itemState |= ODS_SELECTED;
dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */
dis.hwndItem = (HWND)menu->obj.handle;
dis.hDC = hdc;
dis.rcItem = rect;
TRACE( "Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, "
"hwndItem=%p, hdc=%p, rcItem=%s\n", owner,
dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem,
dis.hDC, wine_dbgstr_rect( &dis.rcItem ));
NtGdiGetDCDword( hdc, NtGdiGetBkColor, &old_bk );
NtGdiGetDCDword( hdc, NtGdiGetTextColor, &old_text );
send_message( owner, WM_DRAWITEM, 0, (LPARAM)&dis );
/* Draw the popup-menu arrow */
NtGdiGetAndSetDCDword( hdc, NtGdiGetBkColor, old_bk, NULL );
NtGdiGetAndSetDCDword( hdc, NtGdiGetTextColor, old_text, NULL );
if (item->fType & MF_POPUP)
draw_popup_arrow( hdc, rect, arrow_width, arrow_height );
goto done;
}
if (menu_bar && (item->fType & MF_SEPARATOR)) goto done;
if (item->fState & MF_HILITE)
{
if (flat_menu)
{
InflateRect (&rect, -1, -1);
fill_rect( hdc, &rect, get_sys_color_brush( COLOR_MENUHILIGHT ));
InflateRect (&rect, 1, 1);
fill_rect( hdc, &rect, get_sys_color_brush( COLOR_HIGHLIGHT ));
}
else
{
if (menu_bar)
draw_rect_edge( hdc, &rect, BDR_SUNKENOUTER, BF_RECT, 1 );
else
fill_rect( hdc, &rect, get_sys_color_brush( COLOR_HIGHLIGHT ));
}
}
else
fill_rect( hdc, &rect, get_sys_color_brush(bkgnd) );
NtGdiGetAndSetDCDword( hdc, NtGdiSetBkMode, TRANSPARENT, NULL );
/* vertical separator */
if (!menu_bar && (item->fType & MF_MENUBARBREAK))
{
HPEN oldPen;
RECT rc = rect;
rc.left -= MENU_COL_SPACE / 2 + 1;
rc.top = 3;
rc.bottom = menu->Height - 3;
if (flat_menu)
{
oldPen = NtGdiSelectPen( hdc, get_sys_color_pen( COLOR_BTNSHADOW ));
NtGdiMoveTo( hdc, rc.left, rc.top, NULL );
NtGdiLineTo( hdc, rc.left, rc.bottom );
NtGdiSelectPen( hdc, oldPen );
}
else
draw_rect_edge( hdc, &rc, EDGE_ETCHED, BF_LEFT, 1 );
}
/* horizontal separator */
if (item->fType & MF_SEPARATOR)
{
HPEN oldPen;
RECT rc = rect;
InflateRect( &rc, -1, 0 );
rc.top = ( rc.top + rc.bottom) / 2;
if (flat_menu)
{
oldPen = NtGdiSelectPen( hdc, get_sys_color_pen( COLOR_BTNSHADOW ));
NtGdiMoveTo( hdc, rc.left, rc.top, NULL );
NtGdiLineTo( hdc, rc.right, rc.top );
NtGdiSelectPen( hdc, oldPen );
}
else
draw_rect_edge( hdc, &rc, EDGE_ETCHED, BF_TOP, 1 );
goto done;
}
if (item->hbmpItem)
{
/* calculate the bitmap rectangle in coordinates relative
* to the item rectangle */
if (menu_bar)
{
if (item->hbmpItem == HBMMENU_CALLBACK)
bmprc.left = 3;
else
bmprc.left = item->text ? menucharsize.cx : 0;
}
else if (menu->dwStyle & MNS_NOCHECK)
bmprc.left = 4;
else if (menu->dwStyle & MNS_CHECKORBMP)
bmprc.left = 2;
else
bmprc.left = 4 + get_system_metrics( SM_CXMENUCHECK );
bmprc.right = bmprc.left + item->bmpsize.cx;
if (menu_bar && !(item->hbmpItem == HBMMENU_CALLBACK))
bmprc.top = 0;
else
bmprc.top = (rect.bottom - rect.top - item->bmpsize.cy) / 2;
bmprc.bottom = bmprc.top + item->bmpsize.cy;
}
if (!menu_bar)
{
HBITMAP bm;
INT y = rect.top + rect.bottom;
BOOL checked = FALSE;
UINT check_bitmap_width = get_system_metrics( SM_CXMENUCHECK );
UINT check_bitmap_height = get_system_metrics( SM_CYMENUCHECK );
/* Draw the check mark */
if (!(menu->dwStyle & MNS_NOCHECK))
{
bm = (item->fState & MF_CHECKED) ? item->hCheckBit :
item->hUnCheckBit;
if (bm) /* we have a custom bitmap */
{
HDC mem_hdc = NtGdiCreateCompatibleDC( hdc );
NtGdiSelectBitmap( mem_hdc, bm );
NtGdiBitBlt( hdc, rect.left, (y - check_bitmap_height) / 2,
check_bitmap_width, check_bitmap_height,
mem_hdc, 0, 0, SRCCOPY, 0, 0 );
NtGdiDeleteObjectApp( mem_hdc );
checked = TRUE;
}
else if (item->fState & MF_CHECKED) /* standard bitmaps */
{
RECT r;
HBITMAP bm = NtGdiCreateBitmap( check_bitmap_width,
check_bitmap_height, 1, 1, NULL );
HDC mem_hdc = NtGdiCreateCompatibleDC( hdc );
NtGdiSelectBitmap( mem_hdc, bm );
SetRect( &r, 0, 0, check_bitmap_width, check_bitmap_height);
draw_frame_menu( mem_hdc, &r,
(item->fType & MFT_RADIOCHECK) ? DFCS_MENUBULLET : DFCS_MENUCHECK );
NtGdiBitBlt( hdc, rect.left, (y - r.bottom) / 2, r.right, r.bottom,
mem_hdc, 0, 0, SRCCOPY, 0, 0 );
NtGdiDeleteObjectApp( mem_hdc );
NtGdiDeleteObjectApp( bm );
checked = TRUE;
}
}
if (item->hbmpItem && !(checked && (menu->dwStyle & MNS_CHECKORBMP)))
{
POINT origorg;
/* some applications make this assumption on the DC's origin */
set_viewport_org( hdc, rect.left, rect.top, &origorg );
draw_bitmap_item( hdc, item, &bmprc, menu, owner, odaction );
set_viewport_org( hdc, origorg.x, origorg.y, NULL );
}
/* Draw the popup-menu arrow */
if (item->fType & MF_POPUP)
draw_popup_arrow( hdc, rect, arrow_width, arrow_height);
rect.left += 4;
if (!(menu->dwStyle & MNS_NOCHECK))
rect.left += check_bitmap_width;
rect.right -= arrow_width;
}
else if (item->hbmpItem)
{ /* Draw the bitmap */
POINT origorg;
set_viewport_org( hdc, rect.left, rect.top, &origorg);
draw_bitmap_item( hdc, item, &bmprc, menu, owner, odaction );
set_viewport_org( hdc, origorg.x, origorg.y, NULL);
}
/* process text if present */
if (item->text)
{
int i;
HFONT prev_font = 0;
UINT format = menu_bar ?
DT_CENTER | DT_VCENTER | DT_SINGLELINE :
DT_LEFT | DT_VCENTER | DT_SINGLELINE;
if (!(menu->dwStyle & MNS_CHECKORBMP))
rect.left += menu->textOffset;
if (item->fState & MFS_DEFAULT)
{
prev_font = NtGdiSelectFont(hdc, get_menu_font( TRUE ));
}
if (menu_bar)
{
if (item->hbmpItem)
rect.left += item->bmpsize.cx;
if (item->hbmpItem != HBMMENU_CALLBACK)
rect.left += menucharsize.cx;
rect.right -= menucharsize.cx;
}
for (i = 0; item->text[i]; i++)
if ((item->text[i] == '\t') || (item->text[i] == '\b'))
break;
if (item->fState & MF_GRAYED)
{
if (!(item->fState & MF_HILITE) )
{
++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, RGB(0xff, 0xff, 0xff), NULL );
DrawTextW( hdc, item->text, i, &rect, format );
--rect.left; --rect.top; --rect.right; --rect.bottom;
}
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, RGB(0x80, 0x80, 0x80), NULL );
}
DrawTextW( hdc, item->text, i, &rect, format );
/* paint the shortcut text */
if (!menu_bar && item->text[i]) /* There's a tab or flush-right char */
{
if (item->text[i] == '\t')
{
rect.left = item->xTab;
format = DT_LEFT | DT_VCENTER | DT_SINGLELINE;
}
else
{
rect.right = item->xTab;
format = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
}
if (item->fState & MF_GRAYED)
{
if (!(item->fState & MF_HILITE) )
{
++rect.left; ++rect.top; ++rect.right; ++rect.bottom;
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, RGB(0xff, 0xff, 0xff), NULL );
DrawTextW( hdc, item->text + i + 1, -1, &rect, format );
--rect.left; --rect.top; --rect.right; --rect.bottom;
}
NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, RGB(0x80, 0x80, 0x80), NULL );
}
DrawTextW( hdc, item->text + i + 1, -1, &rect, format );
}
if (prev_font) NtGdiSelectFont( hdc, prev_font );
}
done:
NtGdiExtSelectClipRgn( hdc, old_clip, RGN_COPY );
if (old_clip) NtGdiDeleteObjectApp( old_clip );
}
/***********************************************************************
* NtUserDrawMenuBarTemp (win32u.@)
*/
DWORD WINAPI NtUserDrawMenuBarTemp( HWND hwnd, HDC hdc, RECT *rect, HMENU handle, HFONT font )
{
BOOL flat_menu = FALSE;
HFONT prev_font = 0;
POPUPMENU *menu;
UINT i, retvalue;
NtUserSystemParametersInfo( SPI_GETFLATMENU, 0, &flat_menu, 0 );
if (!handle) handle = get_menu( hwnd );
if (!font) font = get_menu_font(FALSE);
menu = unsafe_menu_ptr( handle );
if (!menu || !rect) return get_system_metrics( SM_CYMENU );
TRACE( "(%p, %p, %p, %p, %p)\n", hwnd, hdc, rect, handle, font );
prev_font = NtGdiSelectFont( hdc, font );
if (!menu->Height) calc_menu_bar_size( hdc, rect, menu, hwnd );
rect->bottom = rect->top + menu->Height;
fill_rect( hdc, rect, get_sys_color_brush( flat_menu ? COLOR_MENUBAR : COLOR_MENU ));
NtGdiSelectPen( hdc, get_sys_color_pen( COLOR_3DFACE ));
NtGdiMoveTo( hdc, rect->left, rect->bottom, NULL );
NtGdiLineTo( hdc, rect->right, rect->bottom );
if (menu->nItems)
{
for (i = 0; i < menu->nItems; i++)
draw_menu_item( hwnd, menu, hwnd, hdc, &menu->items[i], TRUE, ODA_DRAWENTIRE );
retvalue = menu->Height;
}
else
{
retvalue = get_system_metrics( SM_CYMENU );
}
if (prev_font) NtGdiSelectFont( hdc, prev_font );
return retvalue;
}

View file

@ -181,6 +181,7 @@ extern struct dce *get_dc_dce( HDC hdc ) DECLSPEC_HIDDEN;
extern void set_dc_dce( HDC hdc, struct dce *dce ) DECLSPEC_HIDDEN;
extern WORD set_dce_flags( HDC hdc, WORD flags ) DECLSPEC_HIDDEN;
extern DWORD set_stretch_blt_mode( HDC hdc, DWORD mode ) DECLSPEC_HIDDEN;
extern BOOL set_viewport_org( HDC hdc, INT x, INT y, POINT *point ) DECLSPEC_HIDDEN;
extern void DC_InitDC( DC * dc ) DECLSPEC_HIDDEN;
extern void DC_UpdateXforms( DC * dc ) DECLSPEC_HIDDEN;

View file

@ -851,7 +851,7 @@
@ stub NtUserDrawCaption
@ stub NtUserDrawCaptionTemp
@ stdcall NtUserDrawIconEx(long long long long long long long long long)
@ stub NtUserDrawMenuBarTemp
@ stdcall NtUserDrawMenuBarTemp(long long ptr long long)
@ stub NtUserDwmGetRemoteSessionOcclusionEvent
@ stub NtUserDwmGetRemoteSessionOcclusionState
@ stub NtUserDwmKernelShutdown

View file

@ -217,6 +217,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserDragDetect)( HWND hwnd, int x, int y );
BOOL (WINAPI *pNtUserDrawIconEx)( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags );
DWORD (WINAPI *pNtUserDrawMenuBarTemp)( HWND hwnd, HDC hdc, RECT *rect, HMENU handle, HFONT font );
BOOL (WINAPI *pNtUserEmptyClipboard)(void);
BOOL (WINAPI *pNtUserEnableMenuItem)( HMENU handle, UINT id, UINT flags );
BOOL (WINAPI *pNtUserEndDeferWindowPosEx)( HDWP hdwp, BOOL async );
@ -365,6 +366,10 @@ extern void register_window_surface( struct window_surface *old,
extern LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
BOOL ansi ) DECLSPEC_HIDDEN;
extern LRESULT desktop_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN;
extern BOOL draw_frame_caption( HDC dc, LPRECT r, UINT uFlags ) DECLSPEC_HIDDEN;
extern BOOL draw_frame_menu( HDC dc, RECT *r, UINT flags ) DECLSPEC_HIDDEN;
extern BOOL draw_nc_sys_button( HWND hwnd, HDC hdc, BOOL down ) DECLSPEC_HIDDEN;
extern BOOL draw_rect_edge( HDC hdc, RECT *rc, UINT uType, UINT uFlags, UINT width ) DECLSPEC_HIDDEN;
extern void fill_rect( HDC dc, const RECT *rect, HBRUSH hbrush ) DECLSPEC_HIDDEN;
/* hook.c */

View file

@ -868,6 +868,12 @@ BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
return unix_funcs->pNtUserDrawIconEx( hdc, x0, y0, icon, width, height, istep, hbr, flags );
}
DWORD WINAPI NtUserDrawMenuBarTemp( HWND hwnd, HDC hdc, RECT *rect, HMENU handle, HFONT font )
{
if (!unix_funcs) return 0;
return unix_funcs->pNtUserDrawMenuBarTemp( hwnd, hdc, rect, handle, font );
}
BOOL WINAPI NtUserEnableMenuItem( HMENU handle, UINT id, UINT flags )
{
if (!unix_funcs) return FALSE;

View file

@ -539,6 +539,7 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg );
BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y );
BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags );
DWORD WINAPI NtUserDrawMenuBarTemp( HWND hwnd, HDC hdc, RECT *rect, HMENU handle, HFONT font );
BOOL WINAPI NtUserEmptyClipboard(void);
BOOL WINAPI NtUserEnableMenuItem( HMENU handle, UINT id, UINT flags );
BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async );