From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/win32u/font.c | 29 +++++++++++++++++++---------- dlls/wow64win/gdi.c | 4 ++-- include/ntgdi.h | 2 +- 3 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 571379976a5..6aa46e0949a 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -4478,26 +4478,35 @@ UINT WINAPI NtGdiGetTextCharsetInfo( HDC hdc, FONTSIGNATURE *fs, DWORD flags ) /*********************************************************************** * NtGdiHfontCreate (win32u.@) */ -HFONT WINAPI NtGdiHfontCreate( const ENUMLOGFONTEXDVW *penumex, ULONG size, ULONG type, +HFONT WINAPI NtGdiHfontCreate( const void *logfont, ULONG size, ULONG type, ULONG flags, void *data ) { HFONT hFont; FONTOBJ *fontPtr; const LOGFONTW *plf;
- if (!penumex) return 0; + if (!logfont) return 0;
- if (penumex->elfEnumLogfontEx.elfFullName[0] || - penumex->elfEnumLogfontEx.elfStyle[0] || - penumex->elfEnumLogfontEx.elfScript[0]) + if (size == sizeof(ENUMLOGFONTEXDVW) || size == sizeof(ENUMLOGFONTEXW)) { - FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n", - debugstr_w(penumex->elfEnumLogfontEx.elfFullName), - debugstr_w(penumex->elfEnumLogfontEx.elfStyle), - debugstr_w(penumex->elfEnumLogfontEx.elfScript)); + const ENUMLOGFONTEXW *lfex = logfont; + + if (lfex->elfFullName[0] || lfex->elfStyle[0] || lfex->elfScript[0]) + { + FIXME( "some fields ignored. fullname=%s, style=%s, script=%s\n", + debugstr_w( lfex->elfFullName ), debugstr_w( lfex->elfStyle ), + debugstr_w( lfex->elfScript )); + } + + plf = &lfex->elfLogFont; + } + else if (size != sizeof(LOGFONTW)) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return 0; } + else plf = logfont;
- plf = &penumex->elfEnumLogfontEx.elfLogFont; if (!(fontPtr = malloc( sizeof(*fontPtr) ))) return 0;
fontPtr->logfont = *plf; diff --git a/dlls/wow64win/gdi.c b/dlls/wow64win/gdi.c index c821b90122e..5fdc9906a02 100644 --- a/dlls/wow64win/gdi.c +++ b/dlls/wow64win/gdi.c @@ -403,13 +403,13 @@ NTSTATUS WINAPI wow64_NtGdiSetTextJustification( UINT *args )
NTSTATUS WINAPI wow64_NtGdiHfontCreate( UINT *args ) { - const ENUMLOGFONTEXDVW *enumex = get_ptr( &args ); + const void *logfont = get_ptr( &args ); ULONG unk2 = get_ulong( &args ); ULONG unk3 = get_ulong( &args ); ULONG unk4 = get_ulong( &args ); void *data = get_ptr( &args );
- return HandleToUlong( NtGdiHfontCreate( enumex, unk2, unk3, unk4, data )); + return HandleToUlong( NtGdiHfontCreate( logfont, unk2, unk3, unk4, data )); }
NTSTATUS WINAPI wow64_NtGdiGetFontFileData( UINT *args ) diff --git a/include/ntgdi.h b/include/ntgdi.h index 14b1dde45d5..61ee94071a9 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -371,7 +371,7 @@ BOOL WINAPI NtGdiGetTextMetricsW( HDC hdc, TEXTMETRICW *metrics, ULONG flags BOOL WINAPI NtGdiGetTransform( HDC hdc, DWORD which, XFORM *xform ); BOOL WINAPI NtGdiGradientFill( HDC hdc, TRIVERTEX *vert_array, ULONG nvert, void *grad_array, ULONG ngrad, ULONG mode ); -HFONT WINAPI NtGdiHfontCreate( const ENUMLOGFONTEXDVW *enumex, ULONG unk2, ULONG unk3, +HFONT WINAPI NtGdiHfontCreate( const void *logfont, ULONG unk2, ULONG unk3, ULONG unk4, void *data ); DWORD WINAPI NtGdiInitSpool(void); INT WINAPI NtGdiIntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom );
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/controls.h | 1 - dlls/user32/defwnd.c | 20 - dlls/user32/nonclient.c | 23 - dlls/user32/user_main.c | 9 + dlls/win32u/dc.c | 5 + dlls/win32u/defwnd.c | 786 ++++++++++++++++++++++++++++++++++- dlls/win32u/font.c | 22 + dlls/win32u/menu.c | 2 +- dlls/win32u/ntuser_private.h | 2 + dlls/win32u/sysparams.c | 6 +- dlls/win32u/win32u_private.h | 4 + include/ntgdi.h | 1 + include/ntuser.h | 11 + 13 files changed, 843 insertions(+), 49 deletions(-)
diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index 1e5b1082d50..b12f56dda6e 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -123,7 +123,6 @@ extern void MENU_EndMenu(HWND) DECLSPEC_HIDDEN; extern HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu ) DECLSPEC_HIDDEN;
/* nonclient area */ -extern LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; extern void NC_HandleNCCalcSize( HWND hwnd, WPARAM wParam, RECT *winRect ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index c4263edac93..89bf2c78ce4 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -159,9 +159,6 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa { switch(msg) { - case WM_NCPAINT: - return NC_HandleNCPaint( hwnd, (HRGN)wParam ); - case WM_NCMOUSEMOVE: return NC_HandleNCMouseMove( hwnd, wParam, lParam );
@@ -422,15 +419,6 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa case WM_QUERYENDSESSION: return 1;
- case WM_SETICON: - { - LRESULT res = NtUserMessageCall( hwnd, msg, wParam, lParam, - 0, NtUserDefWindowProc, FALSE ); - if( (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION ) - NC_HandleNCPaint( hwnd , (HRGN)1 ); /* Repaint caption */ - return res; - } - case WM_HELP: SendMessageW( GetParent(hwnd), msg, wParam, lParam ); break; @@ -590,8 +578,6 @@ LRESULT WINAPI DefWindowProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam
case WM_SETTEXT: result = NtUserMessageCall( hwnd, msg, wParam, lParam, 0, NtUserDefWindowProc, TRUE ); - if (result && (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION) - NC_HandleNCPaint( hwnd , (HRGN)1 ); /* Repaint caption */ break;
case WM_IME_CHAR: @@ -767,12 +753,6 @@ LRESULT WINAPI DefWindowProcW( } break;
- case WM_SETTEXT: - result = NtUserMessageCall( hwnd, msg, wParam, lParam, 0, NtUserDefWindowProc, FALSE ); - if (result && (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION) - NC_HandleNCPaint( hwnd , (HRGN)1 ); /* Repaint caption */ - break; - case WM_IME_CHAR: PostMessageW( hwnd, WM_CHAR, wParam, lParam ); break; diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c index 2ad40b8b116..b8703df8fd1 100644 --- a/dlls/user32/nonclient.c +++ b/dlls/user32/nonclient.c @@ -1074,29 +1074,6 @@ static void NC_DoNCPaint( HWND hwnd, HRGN clip ) }
- - -/*********************************************************************** - * NC_HandleNCPaint - * - * Handle a WM_NCPAINT message. Called from DefWindowProc(). - */ -LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip) -{ - HWND parent = NtUserGetAncestor( hwnd, GA_PARENT ); - DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE ); - - if( dwStyle & WS_VISIBLE ) - { - NC_DoNCPaint( hwnd, clip ); - - if (parent == GetDesktopWindow()) - PostMessageW( parent, WM_PARENTNOTIFY, WM_NCPAINT, (LPARAM)hwnd ); - } - return 0; -} - - /*********************************************************************** * NC_HandleNCActivate * diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 755fc3d578e..5344dafd359 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -145,6 +145,8 @@ static const struct user_callbacks user_funcs = ImmProcessKey, ImmTranslateMessage, NtWaitForMultipleObjects, + MENU_DrawMenuBar, + SCROLL_DrawNCScrollBar, free_win_ptr, MENU_GetSysMenu, MENU_IsMenuActive, @@ -164,6 +166,12 @@ static NTSTATUS WINAPI User32CopyImage( const struct copy_image_params *params, return HandleToUlong( ret ); }
+static NTSTATUS WINAPI User32DrawText( const struct draw_text_params *params, ULONG size ) +{ + size -= FIELD_OFFSET( struct draw_text_params, str ); + return DrawTextW( params->hdc, params->str, size / sizeof(WCHAR), params->rect, params->flags ); +} + static NTSTATUS WINAPI User32LoadImage( const struct load_image_params *params, ULONG size ) { HANDLE ret = LoadImageW( params->hinst, params->name, params->type, @@ -198,6 +206,7 @@ static const void *kernel_callback_table[NtUserCallCount] = User32CallWindowProc, User32CallWindowsHook, User32CopyImage, + User32DrawText, User32FreeCachedClipboardData, User32LoadDriver, User32LoadImage, diff --git a/dlls/win32u/dc.c b/dlls/win32u/dc.c index f50c13d18bb..fc112f0d4b1 100644 --- a/dlls/win32u/dc.c +++ b/dlls/win32u/dc.c @@ -966,6 +966,11 @@ BOOL WINAPI NtGdiGetAndSetDCDword( HDC hdc, UINT method, DWORD value, DWORD *pre dc->attr->rop_mode = value; break;
+ case NtGdiSetTextAlign: + prev = dc->attr->text_align; + dc->attr->text_align = value; + break; + default: WARN( "unknown method %u\n", method ); ret = FALSE; diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 3dc0ff1187b..8d94bbaad90 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -24,13 +24,43 @@ #pragma makedep unix #endif
-#include "win32u_private.h" +#include "ntgdi_private.h" #include "ntuser_private.h" #include "wine/server.h"
WINE_DEFAULT_DEBUG_CHANNEL(win);
+static BOOL has_dialog_frame( UINT style, UINT ex_style ) +{ + return (ex_style & WS_EX_DLGMODALFRAME) || ((style & WS_DLGFRAME) && !(style & WS_THICKFRAME)); +} + +static BOOL has_thick_frame( UINT style, UINT ex_style ) +{ + return (style & WS_THICKFRAME) && (style & (WS_DLGFRAME|WS_BORDER)) != WS_DLGFRAME; +} + +static BOOL has_thin_frame( UINT style ) +{ + return (style & WS_BORDER) || !(style & (WS_CHILD | WS_POPUP)); +} + +static BOOL has_big_frame( UINT style, UINT ex_style ) +{ + return (style & (WS_THICKFRAME | WS_DLGFRAME)) || (ex_style & WS_EX_DLGMODALFRAME); +} + +static BOOL has_static_outer_frame( UINT ex_style ) +{ + return (ex_style & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE; +} + +static BOOL has_menu( HWND hwnd, UINT style ) +{ + return (style & (WS_CHILD | WS_POPUP)) != WS_CHILD && get_menu( hwnd ); +} + void fill_rect( HDC dc, const RECT *rect, HBRUSH hbrush ) { HBRUSH prev_brush; @@ -66,6 +96,151 @@ static BOOL draw_focus_rect( HDC hdc, const RECT *rc ) return TRUE; }
+static const signed char lt_inner_normal[] = { + -1, -1, -1, -1, + -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1, + -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1, + -1, -1, -1, -1 +}; + +static const signed char lt_outer_normal[] = { + -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, + COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, + COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, + -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1 +}; + +static const signed char rb_inner_normal[] = { + -1, -1, -1, -1, + -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1, + -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1, + -1, -1, -1, -1 +}; + +static const signed char rb_outer_normal[] = { + -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, + COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, + COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, + -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1 +}; + +static const signed char ltrb_outer_mono[] = { + -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, + COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, + COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, + COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, +}; + +static const signed char ltrb_inner_mono[] = { + -1, -1, -1, -1, + -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, + -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 ) +{ + int lbi_offset = 0, lti_offset = 0, rti_offset = 0, rbi_offset = 0; + signed char lt_inner, lt_outer, rb_inner, rb_outer; + HBRUSH lti_brush, lto_brush, rbi_brush, rbo_brush; + RECT inner_rect = *rc, rect; + BOOL retval; + + retval = !((type & BDR_INNER) == BDR_INNER || (type & BDR_OUTER) == BDR_OUTER) && + !(flags & (BF_FLAT|BF_MONO)); + + lti_brush = lto_brush = rbi_brush = rbo_brush = GetStockObject( NULL_BRUSH ); + + /* Determine the colors of the edges */ + lt_inner = lt_inner_normal[type & (BDR_INNER|BDR_OUTER)]; + lt_outer = lt_outer_normal[type & (BDR_INNER|BDR_OUTER)]; + rb_inner = rb_inner_normal[type & (BDR_INNER|BDR_OUTER)]; + rb_outer = rb_outer_normal[type & (BDR_INNER|BDR_OUTER)]; + + if ((flags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT) lbi_offset = width; + if ((flags & BF_TOPRIGHT) == BF_TOPRIGHT) rti_offset = width; + if ((flags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) rbi_offset = width; + if ((flags & BF_TOPLEFT) == BF_TOPLEFT) lti_offset = width; + + if (lt_inner != -1) lti_brush = get_sys_color_brush( lt_inner ); + if (lt_outer != -1) lto_brush = get_sys_color_brush( lt_outer ); + if (rb_inner != -1) rbi_brush = get_sys_color_brush( rb_inner ); + if (rb_outer != -1) rbo_brush = get_sys_color_brush( rb_outer ); + + /* Draw the outer edge */ + if (flags & BF_TOP) + { + rect = inner_rect; + rect.bottom = rect.top + width; + fill_rect( hdc, &rect, lto_brush ); + } + if (flags & BF_LEFT) + { + rect = inner_rect; + rect.right = rect.left + width; + fill_rect( hdc, &rect, lto_brush ); + } + if (flags & BF_BOTTOM) + { + rect = inner_rect; + rect.top = rect.bottom - width; + fill_rect( hdc, &rect, rbo_brush ); + } + if (flags & BF_RIGHT) + { + rect = inner_rect; + rect.left = rect.right - width; + fill_rect( hdc, &rect, rbo_brush ); + } + + /* Draw the inner edge */ + if (flags & BF_TOP) + { + SetRect( &rect, inner_rect.left + lti_offset, inner_rect.top + width, + inner_rect.right - rti_offset, inner_rect.top + 2 * width ); + fill_rect( hdc, &rect, lti_brush ); + } + if (flags & BF_LEFT) + { + SetRect( &rect, inner_rect.left + width, inner_rect.top + lti_offset, + inner_rect.left + 2 * width, inner_rect.bottom - lbi_offset ); + fill_rect( hdc, &rect, lti_brush ); + } + if (flags & BF_BOTTOM) + { + SetRect( &rect, inner_rect.left + lbi_offset, inner_rect.bottom - 2 * width, + inner_rect.right - rbi_offset, inner_rect.bottom - width ); + fill_rect( hdc, &rect, rbi_brush ); + } + if (flags & BF_RIGHT) + { + SetRect( &rect, inner_rect.right - 2 * width, inner_rect.top + rti_offset, + inner_rect.right - width, inner_rect.bottom - rbi_offset ); + fill_rect( hdc, &rect, rbi_brush ); + } + + if (((flags & BF_MIDDLE) && retval) || (flags & BF_ADJUST)) + { + int add = (ltrb_inner_mono[type & (BDR_INNER|BDR_OUTER)] != -1 ? width : 0) + + (ltrb_outer_mono[type & (BDR_INNER|BDR_OUTER)] != -1 ? width : 0); + + if (flags & BF_LEFT) inner_rect.left += add; + if (flags & BF_RIGHT) inner_rect.right -= add; + if (flags & BF_TOP) inner_rect.top += add; + if (flags & BF_BOTTOM) inner_rect.bottom -= add; + + if ((flags & BF_MIDDLE) && retval) + { + fill_rect( hdc, &inner_rect, get_sys_color_brush( flags & BF_MONO ? + COLOR_WINDOW : COLOR_BTNFACE )); + } + + if (flags & BF_ADJUST) *rc = inner_rect; + } + + return retval; +} + /*********************************************************************** * AdjustWindowRectEx (win32u.so) */ @@ -686,6 +861,608 @@ static LRESULT handle_sys_command( HWND hwnd, WPARAM wparam, LPARAM lparam ) return 0; }
+/* Get the 'inside' rectangle of a window, i.e. the whole window rectangle + * but without the borders (if any). */ +static void get_inside_rect( HWND hwnd, enum coords_relative relative, RECT *rect, + DWORD style, DWORD ex_style ) +{ + get_window_rects( hwnd, relative, rect, NULL, get_thread_dpi() ); + + /* Remove frame from rectangle */ + if (has_thick_frame( style, ex_style )) + { + InflateRect( rect, -get_system_metrics( SM_CXFRAME ), -get_system_metrics( SM_CYFRAME )); + } + else if (has_dialog_frame( style, ex_style )) + { + InflateRect( rect, -get_system_metrics( SM_CXDLGFRAME ), -get_system_metrics( SM_CYDLGFRAME )); + } + else if (has_thin_frame( style )) + { + InflateRect( rect, -get_system_metrics( SM_CXBORDER ), -get_system_metrics( SM_CYBORDER )); + } + + /* We have additional border information if the window + * is a child (but not an MDI child) */ + if ((style & WS_CHILD) && !(ex_style & WS_EX_MDICHILD)) + { + if (ex_style & WS_EX_CLIENTEDGE) + InflateRect( rect, -get_system_metrics( SM_CXEDGE ), -get_system_metrics( SM_CYEDGE )); + if (ex_style & WS_EX_STATICEDGE) + InflateRect( rect, -get_system_metrics( SM_CXBORDER ), -get_system_metrics( SM_CYBORDER )); + } +} + +/* Draw a window frame inside the given rectangle, and update the rectangle. */ +static void draw_nc_frame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD ex_style ) +{ + INT width, height; + + if (style & WS_THICKFRAME) + { + width = get_system_metrics( SM_CXFRAME ) - get_system_metrics( SM_CXDLGFRAME ); + height = get_system_metrics( SM_CYFRAME ) - get_system_metrics( SM_CYDLGFRAME ); + + NtGdiSelectBrush( hdc, get_sys_color_brush( active ? COLOR_ACTIVEBORDER : + COLOR_INACTIVEBORDER )); + /* Draw frame */ + NtGdiPatBlt( hdc, rect->left, rect->top, rect->right - rect->left, height, PATCOPY ); + NtGdiPatBlt( hdc, rect->left, rect->top, width, rect->bottom - rect->top, PATCOPY ); + NtGdiPatBlt( hdc, rect->left, rect->bottom - 1, rect->right - rect->left, -height, PATCOPY ); + NtGdiPatBlt( hdc, rect->right - 1, rect->top, -width, rect->bottom - rect->top, PATCOPY ); + + InflateRect( rect, -width, -height ); + } + + /* Now the other bit of the frame */ + if ((style & (WS_BORDER|WS_DLGFRAME)) || (ex_style & WS_EX_DLGMODALFRAME)) + { + DWORD color; + + width = get_system_metrics( SM_CXDLGFRAME ) - get_system_metrics( SM_CXEDGE ); + height = get_system_metrics( SM_CYDLGFRAME ) - get_system_metrics( SM_CYEDGE ); + /* This should give a value of 1 that should also work for a border */ + + if (ex_style & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) color = COLOR_3DFACE; + else if (ex_style & WS_EX_STATICEDGE) color = COLOR_WINDOWFRAME; + else if (style & (WS_DLGFRAME|WS_THICKFRAME)) color = COLOR_3DFACE; + else color = COLOR_WINDOWFRAME; + NtGdiSelectBrush( hdc, get_sys_color_brush( color )); + + /* Draw frame */ + NtGdiPatBlt( hdc, rect->left, rect->top, + rect->right - rect->left, height, PATCOPY ); + NtGdiPatBlt( hdc, rect->left, rect->top, + width, rect->bottom - rect->top, PATCOPY ); + NtGdiPatBlt( hdc, rect->left, rect->bottom - 1, + rect->right - rect->left, -height, PATCOPY ); + NtGdiPatBlt( hdc, rect->right - 1, rect->top, + -width, rect->bottom - rect->top, PATCOPY ); + + InflateRect( rect, -width, -height ); + } +} + +static HICON get_nc_icon_for_window( HWND hwnd ) +{ + HICON icon = 0; + WND *win = get_win_ptr( hwnd ); + + if (win && win != WND_OTHER_PROCESS && win != WND_DESKTOP) + { + icon = win->hIconSmall; + if (!icon) icon = win->hIcon; + release_win_ptr( win ); + } + if (!icon) icon = (HICON) get_class_long_ptr( hwnd, GCLP_HICONSM, FALSE ); + if (!icon) icon = (HICON) get_class_long_ptr( hwnd, GCLP_HICON, FALSE ); + + /* If there is no icon specified and this is not a modal dialog, get the default one. */ + if (!icon && !(get_window_long( hwnd, GWL_EXSTYLE ) & WS_EX_DLGMODALFRAME)) + icon = LoadImageW( 0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, get_system_metrics( SM_CXSMICON ), + get_system_metrics( SM_CYSMICON ), LR_DEFAULTCOLOR | LR_SHARED ); + return icon; +} + +/* Draws the bar part (ie the big rectangle) of the caption */ +static void draw_caption_bar( HDC hdc, const RECT *rect, DWORD style, BOOL active, BOOL gradient ) +{ + if (gradient) + { + TRIVERTEX vertices[4]; + DWORD left, right; + int buttons_size = get_system_metrics( SM_CYCAPTION ) - 1; + + static GRADIENT_RECT mesh[] = {{0, 1}, {1, 2}, {2, 3}}; + + left = get_sys_color( active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION ); + right = get_sys_color( active ? COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION ); + vertices[0].Red = vertices[1].Red = GetRValue( left ) << 8; + vertices[0].Green = vertices[1].Green = GetGValue( left ) << 8; + vertices[0].Blue = vertices[1].Blue = GetBValue( left ) << 8; + vertices[0].Alpha = vertices[1].Alpha = 0xff00; + vertices[2].Red = vertices[3].Red = GetRValue( right ) << 8; + vertices[2].Green = vertices[3].Green = GetGValue( right ) << 8; + vertices[2].Blue = vertices[3].Blue = GetBValue( right ) << 8; + vertices[2].Alpha = vertices[3].Alpha = 0xff00; + + if ((style & WS_SYSMENU) && ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))) + buttons_size += 2 * (get_system_metrics( SM_CXSIZE ) + 1); + + /* area behind icon; solid filled with left color */ + vertices[0].x = rect->left; + vertices[0].y = rect->top; + if (style & WS_SYSMENU) + vertices[1].x = min( rect->left + get_system_metrics( SM_CXSMICON ), rect->right ); + else + vertices[1].x = vertices[0].x; + vertices[1].y = rect->bottom; + + /* area behind text; gradient */ + vertices[2].x = max( vertices[1].x, rect->right - buttons_size ); + vertices[2].y = rect->top; + + /* area behind buttons; solid filled with right color */ + vertices[3].x = rect->right; + vertices[3].y = rect->bottom; + + NtGdiGradientFill( hdc, vertices, 4, mesh, 3, GRADIENT_FILL_RECT_H ); + } + else + { + DWORD color = active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION; + fill_rect( hdc, rect, get_sys_color_brush( color )); + } +} + +/* Draw the system icon */ +static BOOL draw_nc_sys_button( HWND hwnd, HDC hdc, BOOL down ) +{ + HICON icon = get_nc_icon_for_window( hwnd ); + + if (icon) + { + RECT rect; + POINT pt; + DWORD style = get_window_long( hwnd, GWL_STYLE ); + DWORD ex_style = get_window_long( hwnd, GWL_EXSTYLE ); + + get_inside_rect( hwnd, COORDS_WINDOW, &rect, style, ex_style ); + pt.x = rect.left + 2; + pt.y = rect.top + (get_system_metrics( SM_CYCAPTION ) - get_system_metrics( SM_CYSMICON )) / 2; + NtUserDrawIconEx( hdc, pt.x, pt.y, icon, + get_system_metrics( SM_CXSMICON ), + get_system_metrics( SM_CYSMICON ), 0, 0, DI_NORMAL ); + } + + return icon != 0; +} + +/* Create a square rectangle and return its width */ +static int make_square_rect( RECT *src, RECT *dst ) +{ + int width = src->right - src->left; + int height = src->bottom - src->top; + int small_diam = width > height ? height : width; + + *dst = *src; + + /* Make it a square box */ + if (width < height) + { + dst->top += (height - width) / 2; + dst->bottom = dst->top + small_diam; + } + else if (width > height) + { + dst->left += (width - height) / 2; + dst->right = dst->left + small_diam; + } + + return small_diam; +} + +static void draw_checked_rect( HDC dc, RECT *rect ) +{ + if (get_sys_color( COLOR_BTNHIGHLIGHT ) == RGB( 255, 255, 255 )) + { + HBRUSH prev_brush; + DWORD prev_bg; + + fill_rect( dc, rect, get_sys_color_brush( COLOR_BTNFACE )); + NtGdiGetAndSetDCDword( dc, NtGdiSetBkColor, RGB(255, 255, 255), &prev_bg ); + prev_brush = NtGdiSelectBrush( dc, get_55aa_brush() ); + NtGdiPatBlt( dc, rect->left, rect->top, rect->right-rect->left, + rect->bottom-rect->top, 0x00fa0089 ); + NtGdiSelectBrush( dc, prev_brush ); + NtGdiGetAndSetDCDword( dc, NtGdiSetBkColor, prev_bg, NULL ); + } + else + { + fill_rect( dc, rect, get_sys_color_brush( COLOR_BTNHIGHLIGHT )); + } +} + +static BOOL draw_push_button( HDC dc, RECT *r, UINT flags ) +{ + RECT rect = *r; + UINT edge; + + if (flags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT)) + edge = EDGE_SUNKEN; + else + edge = EDGE_RAISED; + + if (flags & DFCS_CHECKED) + { + if (flags & DFCS_MONO) + draw_rect_edge( dc, &rect, edge, BF_MONO|BF_RECT|BF_ADJUST, 1 ); + else + draw_rect_edge( dc, &rect, edge, (flags & DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST, 1 ); + if (!(flags & DFCS_TRANSPARENT)) draw_checked_rect( dc, &rect ); + } + else + { + if (flags & DFCS_MONO) + { + draw_rect_edge( dc, &rect, edge, BF_MONO|BF_RECT|BF_ADJUST, 1 ); + if (!(flags & DFCS_TRANSPARENT)) + fill_rect( dc, &rect, get_sys_color_brush( COLOR_BTNFACE )); + } + else + { + UINT edge_flags = BF_RECT | BF_SOFT | (flags & DFCS_FLAT); + if (!(flags & DFCS_TRANSPARENT)) edge_flags |= BF_MIDDLE; + draw_rect_edge( dc, r, edge, edge_flags, 1 ); + } + } + + /* Adjust rectangle if asked */ + if (flags & DFCS_ADJUSTRECT) InflateRect( r, -2, -2 ); + return TRUE; +} + +static BOOL draw_frame_caption( HDC dc, RECT *r, UINT flags ) +{ + RECT rect; + int small_diam = make_square_rect( r, &rect ) - 2; + HFONT prev_font, font; + int color_idx = flags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT; + int xc = (rect.left + rect.right) / 2; + int yc = (rect.top + rect.bottom) / 2; + LOGFONTW lf = { 0 }; + WCHAR str[] = {0, 0}; + DWORD prev_align, prev_bk; + COLORREF prev_color; + SIZE size; + + static const WCHAR marlettW[] = {'M','a','r','l','e','t','t',0}; + + draw_push_button( dc, r, flags & 0xff00 ); + + switch (flags & 0xf) + { + case DFCS_CAPTIONCLOSE: str[0] = 0x72; break; + case DFCS_CAPTIONHELP: str[0] = 0x73; break; + case DFCS_CAPTIONMIN: str[0] = 0x30; break; + case DFCS_CAPTIONMAX: str[0] = 0x31; break; + case DFCS_CAPTIONRESTORE: str[0] = 0x32; break; + default: + WARN( "Invalid caption; flags=0x%04x\n", flags ); + return FALSE; + } + + lf.lfHeight = -small_diam; + lf.lfWeight = FW_NORMAL; + lf.lfCharSet = SYMBOL_CHARSET; + lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE; + memcpy( lf.lfFaceName, marlettW, sizeof(marlettW) ); + font = NtGdiHfontCreate( &lf, sizeof(lf), 0, 0, NULL ); + NtGdiGetAndSetDCDword( dc, NtGdiSetTextAlign, TA_TOP | TA_LEFT, &prev_align ); + NtGdiGetAndSetDCDword( dc, NtGdiSetBkMode, TRANSPARENT, &prev_bk ); + NtGdiGetDCDword( dc, NtGdiGetTextColor, &prev_color ); + prev_font = NtGdiSelectFont( dc, font ); + NtGdiGetTextExtentExW( dc, str, 1, 0, NULL, NULL, &size, 0 ); + + if (flags & DFCS_INACTIVE) + { + NtGdiGetAndSetDCDword( dc, NtGdiSetTextColor, get_sys_color(COLOR_BTNHIGHLIGHT), NULL ); + NtGdiExtTextOutW( dc, xc-size.cx/2+1, yc-size.cy/2+1, 0, NULL, str, 1, NULL, 0 ); + } + NtGdiGetAndSetDCDword( dc, NtGdiSetTextColor, get_sys_color( color_idx ), NULL ); + NtGdiExtTextOutW( dc, xc-size.cx/2, yc-size.cy/2, 0, NULL, str, 1, NULL, 0 ); + + NtGdiSelectFont(dc, prev_font); + NtGdiGetAndSetDCDword( dc, NtGdiSetTextColor, prev_color, NULL ); + NtGdiGetAndSetDCDword( dc, NtGdiSetTextAlign, prev_align, NULL ); + NtGdiGetAndSetDCDword( dc, NtGdiSetBkMode, prev_bk, NULL ); + NtGdiDeleteObjectApp( font ); + + return TRUE; +} + +static void draw_close_button( HWND hwnd, HDC hdc, BOOL down, BOOL grayed ) +{ + RECT rect; + DWORD style = get_window_long( hwnd, GWL_STYLE ); + DWORD ex_style = get_window_long( hwnd, GWL_EXSTYLE ); + UINT flags = DFCS_CAPTIONCLOSE; + + get_inside_rect( hwnd, COORDS_WINDOW, &rect, style, ex_style ); + + /* A tool window has a smaller Close button */ + if (ex_style & WS_EX_TOOLWINDOW) + { + /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE + * it uses 11x11 for the close button in tool window */ + const int bmp_height = 11; + const int bmp_width = 11; + int caption_height = get_system_metrics( SM_CYSMCAPTION ); + + rect.top = rect.top + (caption_height - 1 - bmp_height) / 2; + rect.left = rect.right - (caption_height + 1 + bmp_width) / 2; + rect.bottom = rect.top + bmp_height; + rect.right = rect.left + bmp_width; + } + else + { + rect.left = rect.right - get_system_metrics( SM_CXSIZE ); + rect.bottom = rect.top + get_system_metrics( SM_CYSIZE ) - 2; + rect.top += 2; + rect.right -= 2; + } + + if (down) flags |= DFCS_PUSHED; + if (grayed) flags |= DFCS_INACTIVE; + draw_frame_caption( hdc, &rect, flags ); +} + +static void draw_max_button( HWND hwnd, HDC hdc, BOOL down, BOOL grayed ) +{ + RECT rect; + UINT flags; + DWORD style = get_window_long( hwnd, GWL_STYLE ); + DWORD ex_style = get_window_long( hwnd, GWL_EXSTYLE ); + + /* never draw maximize box when window has WS_EX_TOOLWINDOW style */ + if (ex_style & WS_EX_TOOLWINDOW) return; + + flags = (style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX; + + get_inside_rect( hwnd, COORDS_WINDOW, &rect, style, ex_style ); + if (style & WS_SYSMENU) rect.right -= get_system_metrics( SM_CXSIZE ); + rect.left = rect.right - get_system_metrics( SM_CXSIZE ); + rect.bottom = rect.top + get_system_metrics( SM_CYSIZE ) - 2; + rect.top += 2; + rect.right -= 2; + if (down) flags |= DFCS_PUSHED; + if (grayed) flags |= DFCS_INACTIVE; + draw_frame_caption( hdc, &rect, flags ); +} + +static void draw_min_button( HWND hwnd, HDC hdc, BOOL down, BOOL grayed ) +{ + RECT rect; + UINT flags; + DWORD style = get_window_long( hwnd, GWL_STYLE ); + DWORD ex_style = get_window_long( hwnd, GWL_EXSTYLE ); + + /* never draw minimize box when window has WS_EX_TOOLWINDOW style */ + if (ex_style & WS_EX_TOOLWINDOW) return; + + flags = (style & WS_MINIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMIN; + + get_inside_rect( hwnd, COORDS_WINDOW, &rect, style, ex_style ); + if (style & WS_SYSMENU) + rect.right -= get_system_metrics( SM_CXSIZE ); + if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX)) + rect.right -= get_system_metrics( SM_CXSIZE ) - 2; + rect.left = rect.right - get_system_metrics( SM_CXSIZE ); + rect.bottom = rect.top + get_system_metrics( SM_CYSIZE ) - 2; + rect.top += 2; + rect.right -= 2; + if (down) flags |= DFCS_PUSHED; + if (grayed) flags |= DFCS_INACTIVE; + draw_frame_caption( hdc, &rect, flags ); +} + +static void draw_nc_caption( HDC hdc, RECT *rect, HWND hwnd, DWORD style, + DWORD ex_style, BOOL active ) +{ + RECT r = *rect; + WCHAR buffer[256]; + HPEN prev_pen; + HMENU sys_menu; + BOOL gradient = FALSE; + UINT pen_color = COLOR_3DFACE; + int len; + + if ((ex_style & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) + pen_color = COLOR_WINDOWFRAME; + prev_pen = NtGdiSelectPen( hdc, get_sys_color_pen( pen_color )); + NtGdiMoveTo( hdc, r.left, r.bottom - 1, NULL ); + NtGdiLineTo( hdc, r.right, r.bottom - 1 ); + NtGdiSelectPen( hdc, prev_pen ); + r.bottom--; + + NtUserSystemParametersInfo( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 ); + draw_caption_bar( hdc, &r, style, active, gradient ); + + if ((style & WS_SYSMENU) && !(ex_style & WS_EX_TOOLWINDOW)) + { + if (draw_nc_sys_button( hwnd, hdc, FALSE )) + r.left += get_system_metrics( SM_CXSMICON ) + 2; + } + + if (style & WS_SYSMENU) + { + UINT state; + + /* Go get the sysmenu */ + sys_menu = NtUserGetSystemMenu( hwnd, FALSE ); + state = get_menu_state( sys_menu, SC_CLOSE, MF_BYCOMMAND ); + + /* Draw a grayed close button if disabled or if SC_CLOSE is not there */ + draw_close_button( hwnd, hdc, FALSE, + (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF) ); + r.right -= get_system_metrics( SM_CYCAPTION ) - 1; + + if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX)) + { + draw_max_button( hwnd, hdc, FALSE, !(style & WS_MAXIMIZEBOX) ); + r.right -= get_system_metrics( SM_CXSIZE ) + 1; + + draw_min_button( hwnd, hdc, FALSE, !(style & WS_MINIMIZEBOX) ); + r.right -= get_system_metrics( SM_CXSIZE ) + 1; + } + } + + /* FIXME: use packed send message */ + len = send_message( hwnd, WM_GETTEXT, ARRAY_SIZE( buffer ), (LPARAM)buffer ); + if (len) + { + NONCLIENTMETRICSW nclm; + HFONT hFont, hOldFont; + nclm.cbSize = sizeof(nclm); + NtUserSystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &nclm, 0 ); + if (ex_style & WS_EX_TOOLWINDOW) + hFont = NtGdiHfontCreate( &nclm.lfSmCaptionFont, sizeof(nclm.lfSmCaptionFont), 0, 0, NULL ); + else + hFont = NtGdiHfontCreate( &nclm.lfCaptionFont, sizeof(nclm.lfCaptionFont), 0, 0, NULL ); + hOldFont = NtGdiSelectFont( hdc, hFont ); + if (active) + NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, get_sys_color( COLOR_CAPTIONTEXT ), NULL ); + else + NtGdiGetAndSetDCDword( hdc, NtGdiSetTextColor, get_sys_color( COLOR_INACTIVECAPTIONTEXT ), NULL ); + NtGdiGetAndSetDCDword( hdc, NtGdiSetBkMode, TRANSPARENT, NULL ); + r.left += 2; + DrawTextW( hdc, buffer, -1, &r, + DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT ); + NtGdiDeleteObjectApp( NtGdiSelectFont( hdc, hOldFont )); + } +} + +/* Paint the non-client area for windows */ +static void nc_paint( HWND hwnd, HRGN clip ) +{ + HDC hdc; + RECT rfuzz, rect, clip_rect; + BOOL active; + WND *win; + DWORD style, ex_style; + WORD flags; + HRGN hrgn; + RECT rectClient; + + if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS) return; + style = win->dwStyle; + ex_style = win->dwExStyle; + flags = win->flags; + release_win_ptr( win ); + + active = flags & WIN_NCACTIVATED; + + TRACE( "%p %d\n", hwnd, active ); + + get_window_rects( hwnd, COORDS_SCREEN, NULL, &rectClient, get_thread_dpi() ); + hrgn = NtGdiCreateRectRgn( rectClient.left, rectClient.top, + rectClient.right, rectClient.bottom ); + + if (clip > (HRGN)1) + { + NtGdiCombineRgn( hrgn, clip, hrgn, RGN_DIFF ); + hdc = NtUserGetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN ); + } + else + { + hdc = NtUserGetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN ); + } + + if (!hdc) + { + NtGdiDeleteObjectApp( hrgn ); + return; + } + + get_window_rects( hwnd, COORDS_WINDOW, &rect, NULL, get_thread_dpi() ); + NtGdiGetAppClipBox( hdc, &clip_rect ); + + NtGdiSelectPen( hdc, get_sys_color_pen( COLOR_WINDOWFRAME )); + + if (has_static_outer_frame( ex_style )) + draw_rect_edge( hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST, 1 ); + else if (has_big_frame( style, ex_style )) + draw_rect_edge( hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST, 1 ); + + draw_nc_frame( hdc, &rect, active, style, ex_style ); + + if ((style & WS_CAPTION) == WS_CAPTION) + { + RECT r = rect; + if (ex_style & WS_EX_TOOLWINDOW) + { + r.bottom = rect.top + get_system_metrics( SM_CYSMCAPTION ); + rect.top += get_system_metrics( SM_CYSMCAPTION ); + } + else { + r.bottom = rect.top + get_system_metrics( SM_CYCAPTION ); + rect.top += get_system_metrics( SM_CYCAPTION ); + } + + if (intersect_rect( &rfuzz, &r, &clip_rect )) + draw_nc_caption( hdc, &r, hwnd, style, ex_style, active ); + } + + if (has_menu( hwnd, style )) + { + RECT r = rect; + r.bottom = rect.top + get_system_metrics( SM_CYMENU ); + + TRACE( "drawing menu with rect %s\n", wine_dbgstr_rect( &r )); + + if (user_callbacks) + rect.top += user_callbacks->draw_menu( hdc, &r, hwnd ) + 1; + } + + TRACE( "rect after menu %s\n", wine_dbgstr_rect( &rect )); + + if (ex_style & WS_EX_CLIENTEDGE) + draw_rect_edge( hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST, 1 ); + + /* Draw the scroll-bars */ + if (user_callbacks) + user_callbacks->draw_nc_scrollbar( hwnd, hdc, style & WS_HSCROLL, style & WS_VSCROLL ); + + /* Draw the "size-box" */ + if ((style & WS_VSCROLL) && (style & WS_HSCROLL)) + { + RECT r = rect; + if ((ex_style & WS_EX_LEFTSCROLLBAR) != 0) + r.right = r.left + get_system_metrics( SM_CXVSCROLL ) + 1; + else + r.left = r.right - get_system_metrics( SM_CXVSCROLL ) + 1; + r.top = r.bottom - get_system_metrics( SM_CYHSCROLL ) + 1; + fill_rect( hdc, &r, get_sys_color_brush( COLOR_BTNFACE ) ); + } + + NtUserReleaseDC( hwnd, hdc ); +} + +static LRESULT handle_nc_paint( HWND hwnd , HRGN clip ) +{ + HWND parent = NtUserGetAncestor( hwnd, GA_PARENT ); + DWORD style = get_window_long( hwnd, GWL_STYLE ); + + if (style & WS_VISIBLE) + { + nc_paint( hwnd, clip ); + + if (parent == get_desktop_window()) + NtUserPostMessage( parent, WM_PARENTNOTIFY, WM_NCPAINT, (LPARAM)hwnd ); + } + return 0; +} + LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) { LRESULT result = 0; @@ -713,6 +1490,9 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, break; }
+ case WM_NCPAINT: + return handle_nc_paint( hwnd, (HRGN)wparam ); + case WM_WINDOWPOSCHANGING: return handle_window_pos_changing( hwnd, (WINDOWPOS *)lparam );
@@ -804,10 +1584,14 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
case WM_SETTEXT: result = set_window_text( hwnd, (void *)lparam, ansi ); + if (result && (get_window_long( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION) + handle_nc_paint( hwnd , (HRGN)1 ); /* repaint caption */ break;
case WM_SETICON: result = (LRESULT)set_window_icon( hwnd, wparam, (HICON)lparam ); + if ((get_window_long( hwnd, GWL_STYLE ) & WS_CAPTION) == WS_CAPTION) + handle_nc_paint( hwnd , (HRGN)1 ); /* repaint caption */ break;
case WM_GETICON: diff --git a/dlls/win32u/font.c b/dlls/win32u/font.c index 6aa46e0949a..39b195fe25a 100644 --- a/dlls/win32u/font.c +++ b/dlls/win32u/font.c @@ -6573,3 +6573,25 @@ BOOL WINAPI NtGdiGetCharWidthInfo( HDC hdc, struct char_width_info *info ) release_dc_ptr(dc); return ret; } + +/*********************************************************************** + * DrawTextW (win32u.so) + */ +INT WINAPI DrawTextW( HDC hdc, const WCHAR *str, INT count, RECT *rect, UINT flags ) +{ + struct draw_text_params *params; + ULONG ret_len, size; + void *ret_ptr; + int ret; + + if (count == -1) count = wcslen( str ); + size = FIELD_OFFSET( struct draw_text_params, str[count] ); + if (!(params = malloc( size ))) return 0; + params->hdc = hdc; + params->rect = rect; + params->flags = flags; + if (count) memcpy( params->str, str, count * sizeof(WCHAR) ); + ret = KeUserModeCallback( NtUserDrawText, params, size, &ret_ptr, &ret_len ); + free( params ); + return ret; +} diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c index a6aeae045e2..4622105ddf1 100644 --- a/dlls/win32u/menu.c +++ b/dlls/win32u/menu.c @@ -824,7 +824,7 @@ static BOOL set_menu_item_info( MENUITEM *menu, const MENUITEMINFOW *info ) }
/* see GetMenuState */ -static UINT get_menu_state( HMENU handle, UINT item_id, UINT flags ) +UINT get_menu_state( HMENU handle, UINT item_id, UINT flags ) { POPUPMENU *menu; UINT state, pos; diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index e39e3f54169..6fc1c1423bd 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -36,6 +36,8 @@ struct user_callbacks BOOL (WINAPI *pImmProcessKey)(HWND, HKL, UINT, LPARAM, DWORD); BOOL (WINAPI *pImmTranslateMessage)(HWND, UINT, WPARAM, LPARAM); NTSTATUS (WINAPI *pNtWaitForMultipleObjects)(ULONG,const HANDLE*,BOOLEAN,BOOLEAN,const LARGE_INTEGER*); + UINT (CDECL *draw_menu)( HDC hDC, LPRECT lprect, HWND hwnd ); + void (CDECL *draw_nc_scrollbar)( HWND hwnd, HDC hdc, BOOL draw_horizontal, BOOL draw_vertical ); void (CDECL *free_win_ptr)( struct tagWND *win ); HMENU (CDECL *get_sys_menu)( HWND hwnd, HMENU popup ); HWND (CDECL *is_menu_active)(void); diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 902cd7ddb0c..20b24d9fe86 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -4499,7 +4499,7 @@ static int get_system_metrics_for_dpi( int index, unsigned int dpi ) } }
-static COLORREF get_sys_color( int index ) +COLORREF get_sys_color( int index ) { COLORREF ret = 0;
@@ -4508,7 +4508,7 @@ static COLORREF get_sys_color( int index ) return ret; }
-static HBRUSH get_55aa_brush(void) +HBRUSH get_55aa_brush(void) { static const WORD pattern[] = { 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa }; static HBRUSH brush_55aa; @@ -4546,7 +4546,7 @@ HBRUSH get_sys_color_brush( unsigned int index ) return system_colors[index].brush; }
-static HPEN get_sys_color_pen( unsigned int index ) +HPEN get_sys_color_pen( unsigned int index ) { if (index >= ARRAY_SIZE( system_colors )) return 0;
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 957d930d9da..be15dac62e7 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -394,6 +394,7 @@ extern BOOL draw_menu_bar( HWND hwnd ) DECLSPEC_HIDDEN; extern HMENU get_menu( HWND hwnd ) DECLSPEC_HIDDEN; 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 set_window_menu( HWND hwnd, HMENU handle ) DECLSPEC_HIDDEN;
/* message.c */ @@ -411,12 +412,15 @@ extern LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM
/* sysparams.c */ extern BOOL enable_thunk_lock DECLSPEC_HIDDEN; +extern HBRUSH get_55aa_brush(void) DECLSPEC_HIDDEN; extern RECT get_display_rect( const WCHAR *display ) DECLSPEC_HIDDEN; extern UINT get_monitor_dpi( HMONITOR monitor ) DECLSPEC_HIDDEN; extern BOOL get_monitor_info( HMONITOR handle, MONITORINFO *info ) DECLSPEC_HIDDEN; extern UINT get_win_monitor_dpi( HWND hwnd ) DECLSPEC_HIDDEN; extern RECT get_primary_monitor_rect( UINT dpi ) DECLSPEC_HIDDEN; +extern COLORREF get_sys_color( int index ) DECLSPEC_HIDDEN; extern HBRUSH get_sys_color_brush( unsigned int index ) DECLSPEC_HIDDEN; +extern HPEN get_sys_color_pen( unsigned int index ) DECLSPEC_HIDDEN; extern UINT get_system_dpi(void) DECLSPEC_HIDDEN; extern int get_system_metrics( int index ) DECLSPEC_HIDDEN; extern UINT get_thread_dpi(void) DECLSPEC_HIDDEN; diff --git a/include/ntgdi.h b/include/ntgdi.h index 61ee94071a9..8fd4c5b1214 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -115,6 +115,7 @@ enum NtGdiSetDCPenColor, NtGdiSetGraphicsMode, NtGdiSetROP2, + NtGdiSetTextAlign, };
/* NtGdiGetDCDword parameter, not compatible with Windows */ diff --git a/include/ntuser.h b/include/ntuser.h index 8320a83800f..a918be6b7dd 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -33,6 +33,7 @@ enum NtUserCallWinProc, NtUserCallWindowsHook, NtUserCopyImage, + NtUserDrawText, NtUserFreeCachedClipboardData, NtUserLoadDriver, NtUserLoadImage, @@ -158,6 +159,16 @@ struct copy_image_params UINT flags; };
+/* NtUserDrawText params */ +struct draw_text_params +{ + HDC hdc; + int count; + RECT *rect; /* FIXME: Use NtCallbackReturn instead */ + UINT flags; + WCHAR str[1]; +}; + /* NtUserFreeCachedClipboardData params */ struct free_cached_data_params {
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116809
Your paranoid android.
=== debian11 (32 bit WoW report) ===
user32: menu.c:2324: Test failed: test 25
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/controls.h | 1 - dlls/user32/defwnd.c | 3 - dlls/user32/nonclient.c | 305 ---------------------------------------- dlls/win32u/defwnd.c | 27 ++++ 4 files changed, 27 insertions(+), 309 deletions(-)
diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index b12f56dda6e..83d07e4ad76 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -123,7 +123,6 @@ extern void MENU_EndMenu(HWND) DECLSPEC_HIDDEN; extern HMENU MENU_GetSysMenu( HWND hWnd, HMENU hPopupMenu ) DECLSPEC_HIDDEN;
/* nonclient area */ -extern LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; extern void NC_HandleNCCalcSize( HWND hwnd, WPARAM wParam, RECT *winRect ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCHitTest( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN; extern LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam ) DECLSPEC_HIDDEN; diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c index 89bf2c78ce4..9b23d1e6315 100644 --- a/dlls/user32/defwnd.c +++ b/dlls/user32/defwnd.c @@ -253,9 +253,6 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa (short)LOWORD(lParam), (short)HIWORD(lParam), 0, hwnd, NULL ); return 0;
- case WM_NCACTIVATE: - return NC_HandleNCActivate( hwnd, wParam, lParam ); - case WM_PRINT: DEFWND_Print(hwnd, (HDC)wParam, lParam); return 0; diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c index b8703df8fd1..dab6b73ee1c 100644 --- a/dlls/user32/nonclient.c +++ b/dlls/user32/nonclient.c @@ -799,311 +799,6 @@ static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed) DrawFrameControl( hdc, &rect, DFC_CAPTION, flags ); }
-/****************************************************************************** - * - * NC_DrawFrame - * - * Draw a window frame inside the given rectangle, and update the rectangle. - * - * Bugs - * Many. First, just what IS a frame in Win95? Note that the 3D look - * on the outer edge is handled by NC_DoNCPaint. As is the inner - * edge. The inner rectangle just inside the frame is handled by the - * Caption code. - * - * In short, for most people, this function should be a nop (unless - * you LIKE thick borders in Win95/NT4.0 -- I've been working with - * them lately, but just to get this code right). Even so, it doesn't - * appear to be so. It's being worked on... - * - *****************************************************************************/ - -static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle) -{ - INT width, height; - - /* Firstly the "thick" frame */ - if (style & WS_THICKFRAME) - { - width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME); - height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME); - - SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER : - COLOR_INACTIVEBORDER) ); - /* Draw frame */ - PatBlt( hdc, rect->left, rect->top, - rect->right - rect->left, height, PATCOPY ); - PatBlt( hdc, rect->left, rect->top, - width, rect->bottom - rect->top, PATCOPY ); - PatBlt( hdc, rect->left, rect->bottom - 1, - rect->right - rect->left, -height, PATCOPY ); - PatBlt( hdc, rect->right - 1, rect->top, - -width, rect->bottom - rect->top, PATCOPY ); - - InflateRect( rect, -width, -height ); - } - - /* Now the other bit of the frame */ - if ((style & (WS_BORDER|WS_DLGFRAME)) || - (exStyle & WS_EX_DLGMODALFRAME)) - { - width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE); - height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE); - /* This should give a value of 1 that should also work for a border */ - - SelectObject( hdc, GetSysColorBrush( - (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ? - COLOR_3DFACE : - (exStyle & WS_EX_STATICEDGE) ? - COLOR_WINDOWFRAME : - (style & (WS_DLGFRAME|WS_THICKFRAME)) ? - COLOR_3DFACE : - /* else */ - COLOR_WINDOWFRAME)); - - /* Draw frame */ - PatBlt( hdc, rect->left, rect->top, - rect->right - rect->left, height, PATCOPY ); - PatBlt( hdc, rect->left, rect->top, - width, rect->bottom - rect->top, PATCOPY ); - PatBlt( hdc, rect->left, rect->bottom - 1, - rect->right - rect->left, -height, PATCOPY ); - PatBlt( hdc, rect->right - 1, rect->top, - -width, rect->bottom - rect->top, PATCOPY ); - - InflateRect( rect, -width, -height ); - } -} - - -/****************************************************************************** - * - * NC_DrawCaption - * - * Draw the window caption for windows. - * The correct pen for the window frame must be selected in the DC. - * - *****************************************************************************/ - -static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style, - DWORD exStyle, BOOL active ) -{ - RECT r = *rect; - WCHAR buffer[256]; - HPEN hPrevPen; - HMENU hSysMenu; - BOOL gradient = FALSE; - - hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen( - ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE| - WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ? - COLOR_WINDOWFRAME : COLOR_3DFACE) ); - MoveToEx( hdc, r.left, r.bottom - 1, NULL ); - LineTo( hdc, r.right, r.bottom - 1 ); - SelectObject( hdc, hPrevPen ); - r.bottom--; - - SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0); - NC_DrawCaptionBar (hdc, &r, style, active, gradient); - - if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) { - if (NC_DrawSysButton (hwnd, hdc, FALSE)) - r.left += GetSystemMetrics(SM_CXSMICON) + 2; - } - - if (style & WS_SYSMENU) - { - UINT state; - - /* Go get the sysmenu */ - hSysMenu = NtUserGetSystemMenu(hwnd, FALSE); - state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); - - /* Draw a grayed close button if disabled or if SC_CLOSE is not there */ - NC_DrawCloseButton (hwnd, hdc, FALSE, - (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF)); - r.right -= GetSystemMetrics(SM_CYCAPTION) - 1; - - if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX)) - { - /* In win95 the two buttons are always there */ - /* But if the menu item is not in the menu they're disabled*/ - - NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX))); - r.right -= GetSystemMetrics(SM_CXSIZE) + 1; - - NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX))); - r.right -= GetSystemMetrics(SM_CXSIZE) + 1; - } - } - - if (GetWindowTextW( hwnd, buffer, ARRAY_SIZE( buffer ))) - { - NONCLIENTMETRICSW nclm; - HFONT hFont, hOldFont; - nclm.cbSize = sizeof(nclm); - SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0); - if (exStyle & WS_EX_TOOLWINDOW) - hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont); - else - hFont = CreateFontIndirectW (&nclm.lfCaptionFont); - hOldFont = SelectObject (hdc, hFont); - if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) ); - else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ); - SetBkMode( hdc, TRANSPARENT ); - r.left += 2; - DrawTextW( hdc, buffer, -1, &r, - DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT ); - DeleteObject (SelectObject (hdc, hOldFont)); - } -} - - -/****************************************************************************** - * NC_DoNCPaint - * - * Paint the non-client area for windows. - */ -static void NC_DoNCPaint( HWND hwnd, HRGN clip ) -{ - HDC hdc; - RECT rfuzz, rect, rectClip; - BOOL active; - WND *wndPtr; - DWORD dwStyle, dwExStyle; - WORD flags; - HRGN hrgn; - RECT rectClient; - - if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return; - dwStyle = wndPtr->dwStyle; - dwExStyle = wndPtr->dwExStyle; - flags = wndPtr->flags; - WIN_ReleasePtr( wndPtr ); - - active = flags & WIN_NCACTIVATED; - - TRACE("%p %d\n", hwnd, active ); - - /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in - the call to GetDCEx implying that it is allowed not to use it either. - However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN) - will cause clipRgn to be deleted after ReleaseDC(). - Now, how is the "system" supposed to tell what happened? - */ - - WIN_GetRectangles( hwnd, COORDS_SCREEN, NULL, &rectClient ); - hrgn = CreateRectRgnIndirect( &rectClient ); - - if (clip > (HRGN)1) - { - CombineRgn( hrgn, clip, hrgn, RGN_DIFF ); - hdc = NtUserGetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN ); - } - else - { - hdc = NtUserGetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN ); - } - - if (!hdc) - { - DeleteObject( hrgn ); - return; - } - - WIN_GetRectangles( hwnd, COORDS_WINDOW, &rect, NULL ); - GetClipBox( hdc, &rectClip ); - - SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) ); - - if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) { - DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST); - } - else if (HAS_BIGFRAME( dwStyle, dwExStyle)) { - DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST); - } - - NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle ); - - if ((dwStyle & WS_CAPTION) == WS_CAPTION) - { - RECT r = rect; - if (dwExStyle & WS_EX_TOOLWINDOW) { - r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION); - rect.top += GetSystemMetrics(SM_CYSMCAPTION); - } - else { - r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION); - rect.top += GetSystemMetrics(SM_CYCAPTION); - } - if( IntersectRect( &rfuzz, &r, &rectClip ) ) - NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active); - } - - if (HAS_MENU( hwnd, dwStyle )) - { - RECT r = rect; - r.bottom = rect.top + GetSystemMetrics(SM_CYMENU); - - TRACE("Calling DrawMenuBar with rect (%s)\n", wine_dbgstr_rect(&r)); - - rect.top += MENU_DrawMenuBar( hdc, &r, hwnd ) + 1; - } - - TRACE("After MenuBar, rect is (%s).\n", wine_dbgstr_rect(&rect)); - - if (dwExStyle & WS_EX_CLIENTEDGE) - DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); - - /* Draw the scroll-bars */ - SCROLL_DrawNCScrollBar( hwnd, hdc, dwStyle & WS_HSCROLL, dwStyle & WS_VSCROLL ); - - /* Draw the "size-box" */ - if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL)) - { - RECT r = rect; - if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) - r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1; - else - r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1; - r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1; - FillRect( hdc, &r, GetSysColorBrush( COLOR_BTNFACE ) ); - } - - NtUserReleaseDC( hwnd, hdc ); -} - - -/*********************************************************************** - * NC_HandleNCActivate - * - * Handle a WM_NCACTIVATE message. Called from DefWindowProc(). - */ -LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam, LPARAM lParam ) -{ - /* Lotus Notes draws menu descriptions in the caption of its main - * window. When it wants to restore original "system" view, it just - * sends WM_NCACTIVATE message to itself. Any optimizations here in - * attempt to minimize redrawings lead to a not restored caption. - */ - if (wParam) win_set_flags( hwnd, WIN_NCACTIVATED, 0 ); - else win_set_flags( hwnd, 0, WIN_NCACTIVATED ); - - /* This isn't documented but is reproducible in at least XP SP2 and - * Outlook 2007 depends on it - */ - if (lParam != -1) - { - NC_DoNCPaint( hwnd, (HRGN)1 ); - - if (NtUserGetAncestor( hwnd, GA_PARENT ) == GetDesktopWindow()) - PostMessageW( GetDesktopWindow(), WM_PARENTNOTIFY, WM_NCACTIVATE, (LPARAM)hwnd ); - } - - return TRUE; -} - - /*********************************************************************** * NC_HandleSetCursor * diff --git a/dlls/win32u/defwnd.c b/dlls/win32u/defwnd.c index 8d94bbaad90..db8187a3ea1 100644 --- a/dlls/win32u/defwnd.c +++ b/dlls/win32u/defwnd.c @@ -1463,6 +1463,30 @@ static LRESULT handle_nc_paint( HWND hwnd , HRGN clip ) return 0; }
+static LRESULT handle_nc_activate( HWND hwnd, WPARAM wparam, LPARAM lparam ) +{ + /* Lotus Notes draws menu descriptions in the caption of its main + * window. When it wants to restore original "system" view, it just + * sends WM_NCACTIVATE message to itself. Any optimizations here in + * attempt to minimize redrawings lead to a not restored caption. + */ + if (wparam) win_set_flags( hwnd, WIN_NCACTIVATED, 0 ); + else win_set_flags( hwnd, 0, WIN_NCACTIVATED ); + + /* This isn't documented but is reproducible in at least XP SP2 and + * Outlook 2007 depends on it + */ + if (lparam != -1) + { + nc_paint( hwnd, (HRGN)1 ); + + if (NtUserGetAncestor( hwnd, GA_PARENT ) == get_desktop_window()) + NtUserPostMessage( get_desktop_window(), WM_PARENTNOTIFY, WM_NCACTIVATE, (LPARAM)hwnd ); + } + + return TRUE; +} + LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) { LRESULT result = 0; @@ -1493,6 +1517,9 @@ LRESULT default_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, case WM_NCPAINT: return handle_nc_paint( hwnd, (HRGN)wparam );
+ case WM_NCACTIVATE: + return handle_nc_activate( hwnd, wparam, lparam ); + case WM_WINDOWPOSCHANGING: return handle_window_pos_changing( hwnd, (WINDOWPOS *)lparam );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116810
Your paranoid android.
=== debian11 (64 bit WoW report) ===
user32: msg.c:6881: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0138 was expected, but got msg 0x030f instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 8: the msg 0x8000 was expected, but got msg 0x0086 instead msg.c:6881: Test failed: SetFocus(hwnd) on a button: 9: the msg sequence is not complete: expected 0000 - actual 0006
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/user32/dialog.c | 17 +----------- dlls/win32u/sysparams.c | 61 +++++++++++++++++++++++++++++++---------- include/ntuser.h | 6 ++++ 3 files changed, 53 insertions(+), 31 deletions(-)
diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c index 66000995861..b804de90df2 100644 --- a/dlls/user32/dialog.c +++ b/dlls/user32/dialog.c @@ -1519,22 +1519,7 @@ BOOL WINAPI CheckRadioButton( HWND hwndDlg, int firstID, */ DWORD WINAPI GetDialogBaseUnits(void) { - static LONG cx, cy; - - if (!cx) - { - HDC hdc; - - if ((hdc = GetDC(0))) - { - cx = GdiGetCharDimensions( hdc, NULL, &cy ); - NtUserReleaseDC( 0, hdc ); - } - TRACE( "base units = %ld,%ld\n", cx, cy ); - } - - return MAKELONG( MulDiv( cx, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI ), - MulDiv( cy, GetDpiForSystem(), USER_DEFAULT_SCREEN_DPI )); + return NtUserGetDialogBaseUnits(); }
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 20b24d9fe86..7e43cc2f36f 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2724,38 +2724,66 @@ static void get_real_fontname( LOGFONTW *lf, WCHAR fullname[LF_FACESIZE] ) lstrcpyW( fullname, lf->lfFaceName ); }
+static LONG get_char_dimentions( HDC hdc, TEXTMETRICW *metric, LONG *height ) +{ + SIZE sz; + static const WCHAR abcdW[] = + {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q', + 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H', + 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; + + if (metric && !NtGdiGetTextMetricsW( hdc, metric, 0 )) return 0; + + if (!NtGdiGetTextExtentExW( hdc, abcdW, ARRAYSIZE(abcdW), 0, NULL, NULL, &sz, 0 )) + return 0; + + if (height) *height = sz.cy; + return (sz.cx / 26 + 1) / 2; +} + /* get text metrics and/or "average" char width of the specified logfont * for the specified dc */ -static void get_text_metr_size( HDC hdc, LOGFONTW *plf, TEXTMETRICW * ptm, UINT *psz) +static void get_text_metr_size( HDC hdc, LOGFONTW *plf, TEXTMETRICW *metric, UINT *psz) { ENUMLOGFONTEXDVW exdv = { .elfEnumLogfontEx.elfLogFont = *plf }; HFONT hfont, hfontsav; TEXTMETRICW tm; - if (!ptm) ptm = &tm; + UINT ret; + if (!metric) metric = &tm; hfont = NtGdiHfontCreate( &exdv, sizeof(exdv), 0, 0, NULL ); if (!hfont || !(hfontsav = NtGdiSelectFont( hdc, hfont ))) { - ptm->tmHeight = -1; + metric->tmHeight = -1; if (psz) *psz = 10; if (hfont) NtGdiDeleteObjectApp( hfont ); return; } - NtGdiGetTextMetricsW( hdc, ptm, 0 ); - if (psz) - { - SIZE sz; - static const WCHAR abcdW[] = - {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q', - 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H', - 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'}; - if (NtGdiGetTextExtentExW( hdc, abcdW, ARRAYSIZE(abcdW), 0, NULL, NULL, &sz, 0 )) - *psz = (sz.cx / 26 + 1) / 2; - else *psz = 10; - } + ret = get_char_dimentions( hdc, metric, NULL ); + if (psz) *psz = ret ? ret : 10; NtGdiSelectFont( hdc, hfontsav ); NtGdiDeleteObjectApp( hfont ); }
+static DWORD get_dialog_base_units(void) +{ + static LONG cx, cy; + + if (!cx) + { + HDC hdc; + + if ((hdc = NtUserGetDCEx( 0, 0, DCX_CACHE | DCX_WINDOW ))) + { + cx = get_char_dimentions( hdc, NULL, &cy ); + NtUserReleaseDC( 0, hdc ); + } + TRACE( "base units = %d,%d\n", cx, cy ); + } + + return MAKELONG( muldiv( cx, get_system_dpi(), USER_DEFAULT_SCREEN_DPI ), + muldiv( cy, get_system_dpi(), USER_DEFAULT_SCREEN_DPI )); +} + /* adjust some of the raw values found in the registry */ static void normalize_nonclientmetrics( NONCLIENTMETRICSW *pncm) { @@ -4681,6 +4709,9 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code ) case NtUserCallNoParam_GetDesktopWindow: return HandleToUlong( get_desktop_window() );
+ case NtUserCallNoParam_GetDialogBaseUnits: + return get_dialog_base_units(); + case NtUserCallNoParam_GetInputState: return get_input_state();
diff --git a/include/ntuser.h b/include/ntuser.h index a918be6b7dd..f2fdab6c0f9 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -718,6 +718,7 @@ enum { NtUserCallNoParam_DestroyCaret, NtUserCallNoParam_GetDesktopWindow, + NtUserCallNoParam_GetDialogBaseUnits, NtUserCallNoParam_GetInputState, NtUserCallNoParam_ReleaseCapture, /* temporary exports */ @@ -735,6 +736,11 @@ static inline HWND NtUserGetDesktopWindow(void) return UlongToHandle( NtUserCallNoParam( NtUserCallNoParam_GetDesktopWindow )); }
+static inline DWORD NtUserGetDialogBaseUnits(void) +{ + return NtUserCallNoParam( NtUserCallNoParam_GetDialogBaseUnits ); +}; + static inline BOOL NtUserGetInputState(void) { return NtUserCallNoParam( NtUserCallNoParam_GetInputState );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=116811
Your paranoid android.
=== debian11 (32 bit WoW report) ===
user32: menu.c:2324: Test failed: test 25
From: Jacek Caban jacek@codeweavers.com
Signed-off-by: Jacek Caban jacek@codeweavers.com --- dlls/win32u/sysparams.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 7e43cc2f36f..be8a85bfb9f 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2743,14 +2743,13 @@ static LONG get_char_dimentions( HDC hdc, TEXTMETRICW *metric, LONG *height )
/* get text metrics and/or "average" char width of the specified logfont * for the specified dc */ -static void get_text_metr_size( HDC hdc, LOGFONTW *plf, TEXTMETRICW *metric, UINT *psz) +static void get_text_metr_size( HDC hdc, LOGFONTW *lf, TEXTMETRICW *metric, UINT *psz ) { - ENUMLOGFONTEXDVW exdv = { .elfEnumLogfontEx.elfLogFont = *plf }; HFONT hfont, hfontsav; TEXTMETRICW tm; UINT ret; if (!metric) metric = &tm; - hfont = NtGdiHfontCreate( &exdv, sizeof(exdv), 0, 0, NULL ); + hfont = NtGdiHfontCreate( lf, sizeof(*lf), 0, 0, NULL ); if (!hfont || !(hfontsav = NtGdiSelectFont( hdc, hfont ))) { metric->tmHeight = -1;