Commit af00521e authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

win32u: Move NtUserDrawMenuBarTemp implementation from user32.

parent 05b29423
...@@ -119,8 +119,6 @@ static HMENU top_popup_hmenu; ...@@ -119,8 +119,6 @@ static HMENU top_popup_hmenu;
/* Flag set by EndMenu() to force an exit from menu tracking */ /* Flag set by EndMenu() to force an exit from menu tracking */
static BOOL fEndMenu = FALSE; 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) static BOOL is_win_menu_disallowed(HWND hwnd)
{ {
return (GetWindowLongW(hwnd, GWL_STYLE) & (WS_CHILD | WS_POPUP)) == WS_CHILD; return (GetWindowLongW(hwnd, GWL_STYLE) & (WS_CHILD | WS_POPUP)) == WS_CHILD;
...@@ -1198,81 +1196,6 @@ static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, UINT max_height ) ...@@ -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) static void draw_scroll_arrow(HDC hdc, int x, int top, int height, BOOL up, BOOL enabled)
{ {
RECT rect, light_rect; RECT rect, light_rect;
...@@ -1787,7 +1710,7 @@ UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd ) ...@@ -1787,7 +1710,7 @@ UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd )
return GetSystemMetrics(SM_CYMENU); 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 ) ...@@ -4028,67 +3951,6 @@ BOOL WINAPI DrawMenuBar( HWND hwnd )
return NtUserDrawMenuBar( 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) * EndMenu (USER.187)
......
...@@ -194,7 +194,7 @@ ...@@ -194,7 +194,7 @@
@ stdcall DrawIcon(long long long long) @ stdcall DrawIcon(long long long long)
@ stdcall DrawIconEx(long long long long long long long long long) NtUserDrawIconEx @ stdcall DrawIconEx(long long long long long long long long long) NtUserDrawIconEx
@ stdcall DrawMenuBar(long) @ 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 DrawStateA(long long ptr long long long long long long long)
@ stdcall DrawStateW(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) @ stdcall DrawTextA(long str long ptr long)
......
...@@ -1103,6 +1103,19 @@ BOOL WINAPI NtGdiSetBrushOrg( HDC hdc, INT x, INT y, POINT *oldorg ) ...@@ -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.@) * NtGdiGetTransform (win32u.@)
* *
......
...@@ -138,7 +138,7 @@ static const signed char ltrb_inner_mono[] = { ...@@ -138,7 +138,7 @@ static const signed char ltrb_inner_mono[] = {
-1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, -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; int lbi_offset = 0, lti_offset = 0, rti_offset = 0, rbi_offset = 0;
signed char lt_inner, lt_outer, rb_inner, rb_outer; 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 ...@@ -1016,7 +1016,7 @@ static void draw_caption_bar( HDC hdc, const RECT *rect, DWORD style, BOOL activ
} }
/* Draw the system icon */ /* 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 ); HICON icon = get_nc_icon_for_window( hwnd );
...@@ -1122,7 +1122,7 @@ static BOOL draw_push_button( HDC dc, RECT *r, UINT flags ) ...@@ -1122,7 +1122,7 @@ static BOOL draw_push_button( HDC dc, RECT *r, UINT flags )
return TRUE; 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; RECT rect;
int small_diam = make_square_rect( r, &rect ) - 2; int small_diam = make_square_rect( r, &rect ) - 2;
...@@ -1181,6 +1181,77 @@ static BOOL draw_frame_caption( HDC dc, RECT *r, UINT flags ) ...@@ -1181,6 +1181,77 @@ static BOOL draw_frame_caption( HDC dc, RECT *r, UINT flags )
return TRUE; 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 ) static void draw_close_button( HWND hwnd, HDC hdc, BOOL down, BOOL grayed )
{ {
RECT rect; RECT rect;
......
...@@ -1160,6 +1160,7 @@ static struct unix_funcs unix_funcs = ...@@ -1160,6 +1160,7 @@ static struct unix_funcs unix_funcs =
NtUserDispatchMessage, NtUserDispatchMessage,
NtUserDragDetect, NtUserDragDetect,
NtUserDrawIconEx, NtUserDrawIconEx,
NtUserDrawMenuBarTemp,
NtUserEmptyClipboard, NtUserEmptyClipboard,
NtUserEnableMenuItem, NtUserEnableMenuItem,
NtUserEndDeferWindowPosEx, NtUserEndDeferWindowPosEx,
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#endif #endif
#define OEMRESOURCE #define OEMRESOURCE
#include "win32u_private.h" #include "ntgdi_private.h"
#include "ntuser_private.h" #include "ntuser_private.h"
#include "wine/server.h" #include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"
...@@ -48,6 +48,9 @@ struct accelerator ...@@ -48,6 +48,9 @@ struct accelerator
/* (other menu->FocusedItem values give the position of the focused item) */ /* (other menu->FocusedItem values give the position of the focused item) */
#define NO_SELECTED_ITEM 0xffff #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 */ /* 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_STRING_ITEM(flags) (MENU_ITEM_TYPE ((flags)) == MF_STRING)
#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1)) #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 ) ...@@ -1672,3 +1675,554 @@ UINT get_menu_bar_height( HWND hwnd, UINT width, INT org_x, INT org_y )
NtUserReleaseDC( hwnd, hdc ); NtUserReleaseDC( hwnd, hdc );
return menu->Height; 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;
}
...@@ -181,6 +181,7 @@ extern struct dce *get_dc_dce( HDC hdc ) DECLSPEC_HIDDEN; ...@@ -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 void set_dc_dce( HDC hdc, struct dce *dce ) DECLSPEC_HIDDEN;
extern WORD set_dce_flags( HDC hdc, WORD flags ) 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 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_InitDC( DC * dc ) DECLSPEC_HIDDEN;
extern void DC_UpdateXforms( DC * dc ) DECLSPEC_HIDDEN; extern void DC_UpdateXforms( DC * dc ) DECLSPEC_HIDDEN;
......
...@@ -851,7 +851,7 @@ ...@@ -851,7 +851,7 @@
@ stub NtUserDrawCaption @ stub NtUserDrawCaption
@ stub NtUserDrawCaptionTemp @ stub NtUserDrawCaptionTemp
@ stdcall NtUserDrawIconEx(long long long long long long long long long) @ stdcall NtUserDrawIconEx(long long long long long long long long long)
@ stub NtUserDrawMenuBarTemp @ stdcall NtUserDrawMenuBarTemp(long long ptr long long)
@ stub NtUserDwmGetRemoteSessionOcclusionEvent @ stub NtUserDwmGetRemoteSessionOcclusionEvent
@ stub NtUserDwmGetRemoteSessionOcclusionState @ stub NtUserDwmGetRemoteSessionOcclusionState
@ stub NtUserDwmKernelShutdown @ stub NtUserDwmKernelShutdown
......
...@@ -217,6 +217,7 @@ struct unix_funcs ...@@ -217,6 +217,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserDragDetect)( HWND hwnd, int x, int y ); BOOL (WINAPI *pNtUserDragDetect)( HWND hwnd, int x, int y );
BOOL (WINAPI *pNtUserDrawIconEx)( HDC hdc, INT x0, INT y0, HICON icon, INT width, BOOL (WINAPI *pNtUserDrawIconEx)( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags ); 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 *pNtUserEmptyClipboard)(void);
BOOL (WINAPI *pNtUserEnableMenuItem)( HMENU handle, UINT id, UINT flags ); BOOL (WINAPI *pNtUserEnableMenuItem)( HMENU handle, UINT id, UINT flags );
BOOL (WINAPI *pNtUserEndDeferWindowPosEx)( HDWP hdwp, BOOL async ); BOOL (WINAPI *pNtUserEndDeferWindowPosEx)( HDWP hdwp, BOOL async );
...@@ -365,6 +366,10 @@ extern void register_window_surface( struct window_surface *old, ...@@ -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, extern LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
BOOL ansi ) DECLSPEC_HIDDEN; BOOL ansi ) DECLSPEC_HIDDEN;
extern LRESULT desktop_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) 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; extern void fill_rect( HDC dc, const RECT *rect, HBRUSH hbrush ) DECLSPEC_HIDDEN;
/* hook.c */ /* hook.c */
......
...@@ -868,6 +868,12 @@ BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width, ...@@ -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 ); 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 ) BOOL WINAPI NtUserEnableMenuItem( HMENU handle, UINT id, UINT flags )
{ {
if (!unix_funcs) return FALSE; if (!unix_funcs) return FALSE;
......
...@@ -539,6 +539,7 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg ); ...@@ -539,6 +539,7 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg );
BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y ); BOOL WINAPI NtUserDragDetect( HWND hwnd, int x, int y );
BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width, BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags ); 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 NtUserEmptyClipboard(void);
BOOL WINAPI NtUserEnableMenuItem( HMENU handle, UINT id, UINT flags ); BOOL WINAPI NtUserEnableMenuItem( HMENU handle, UINT id, UINT flags );
BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async ); BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment