Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
June 2022
- 68 participants
- 3274 messages
[PATCH 0/4] MR233: win32u: Partially move raw input APIs.
by Zebediah Figura (@zfigura)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/233
June 13, 2022
Re: [PATCH v2 2/5] win32u: Move WM_NCPAINT handling from user32.
by Marvin
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=116815
Your paranoid android.
=== debian11 (64 bit WoW report) ===
user32:
win.c:10976: Test failed: Expected foreground window 0, got 0000000001390054
win.c:10982: Test failed: Expected foreground window 00000000001A0124, got 0000000001390054
June 13, 2022
Re: [PATCH v2 0/5] MR232: win32u: user32 conversion - approved
by Huw Davies (@huw)
This merge request was approved by Huw Davies.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/232
June 13, 2022
Re: [PATCH v2 0/5] MR232: win32u: user32 conversion
by Huw Davies (@huw)
Huw Davies (@huw) commented about dlls/win32u/sysparams.c:
> lstrcpyW( fullname, lf->lfFaceName );
> }
>
> +static LONG get_char_dimentions( HDC hdc, TEXTMETRICW *metric, LONG *height )
I've pushed a fix for this typo.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/232#note_1921
June 13, 2022
[PATCH v2 5/5] win32u: Simplify get_text_metr_size.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)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 7c333953f7e..0b6053a5ab9 100644
--- a/dlls/win32u/sysparams.c
+++ b/dlls/win32u/sysparams.c
@@ -2743,14 +2743,13 @@ static LONG get_char_dimensions( 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;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/232
June 13, 2022
[PATCH v2 4/5] win32u: Move GetDialogBaseUnits implementation from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)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..7c333953f7e 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_dimensions( 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_dimensions( 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_dimensions( 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 );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/232
June 13, 2022
[PATCH v2 3/5] win32u: Move WM_NCACTIVATE implementation from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)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 );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/232
June 13, 2022
[PATCH v2 2/5] win32u: Move WM_NCPAINT handling from user32.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)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
{
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/232
June 13, 2022
[PATCH v2 1/5] win32u: Allow passing simple LOGFONTW to NtGdiHfontCreate.
by Jacek Caban
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)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 );
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/232
June 13, 2022
[PATCH v2 0/5] MR232: win32u: user32 conversion
by Jacek Caban (@jacek)
--
v2: win32u: Simplify get_text_metr_size.
win32u: Move GetDialogBaseUnits implementation from user32.
https://gitlab.winehq.org/wine/wine/-/merge_requests/232
June 13, 2022