[PATCH 4/4] dwmapi: Implement DWMWA_CAPTION_BUTTON_BOUNDS via system metrics.
Gabriel Ivăncescu
gabrielopcode at gmail.com
Tue Aug 11 10:29:13 CDT 2020
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
Most of the logic has been followed from user32.
dlls/dwmapi/dwmapi_main.c | 75 ++++++++++++++++++++++++++++++++++++++
dlls/dwmapi/tests/dwmapi.c | 58 ++++++++++++++++++++++++++++-
2 files changed, 132 insertions(+), 1 deletion(-)
diff --git a/dlls/dwmapi/dwmapi_main.c b/dlls/dwmapi/dwmapi_main.c
index bb585c5..a433437 100644
--- a/dlls/dwmapi/dwmapi_main.c
+++ b/dlls/dwmapi/dwmapi_main.c
@@ -32,6 +32,74 @@
WINE_DEFAULT_DEBUG_CHANNEL(dwmapi);
+static void get_caption_buttons_rect(HWND hwnd, RECT *rc)
+{
+ DWORD style = GetWindowLongW(hwnd, GWL_STYLE);
+ DWORD ex_style = GetWindowLongW(hwnd, GWL_EXSTYLE);
+ LONG border_w = 0, border_h = 0;
+
+ GetWindowRect(hwnd, rc);
+ OffsetRect(rc, -rc->left, -rc->top);
+
+ if ((style & WS_THICKFRAME) && (style & (WS_DLGFRAME | WS_BORDER)) != WS_DLGFRAME)
+ {
+ border_w += GetSystemMetrics(SM_CXFRAME);
+ border_h += GetSystemMetrics(SM_CYFRAME);
+ }
+ else if ((!(style & WS_THICKFRAME) && (style & WS_DLGFRAME)) || (ex_style & WS_EX_DLGMODALFRAME))
+ {
+ border_w += GetSystemMetrics(SM_CXDLGFRAME);
+ border_h += GetSystemMetrics(SM_CYDLGFRAME);
+ }
+ else if ((style & WS_BORDER) || !(style & (WS_CHILD | WS_POPUP)))
+ {
+ border_w += GetSystemMetrics(SM_CXBORDER);
+ border_h += GetSystemMetrics(SM_CYBORDER);
+ }
+
+ /* There's additional border info if the window is a child (but not MDI) */
+ if ((style & WS_CHILD) && !(ex_style & WS_EX_MDICHILD))
+ {
+ if (ex_style & WS_EX_CLIENTEDGE)
+ {
+ border_w += GetSystemMetrics(SM_CXEDGE);
+ border_h += GetSystemMetrics(SM_CYEDGE);
+ }
+ if (ex_style & WS_EX_STATICEDGE)
+ {
+ border_w += GetSystemMetrics(SM_CXBORDER);
+ border_h += GetSystemMetrics(SM_CYBORDER);
+ }
+ }
+
+ rc->right -= border_w;
+ rc->top += border_h;
+ rc->left = rc->right;
+
+ /* The height is always reported even if there are no buttons */
+ rc->bottom = rc->top + GetSystemMetrics((ex_style & WS_EX_TOOLWINDOW) ? SM_CYSMCAPTION : SM_CYCAPTION);
+
+ if ((style & (WS_SYSMENU | WS_CAPTION)) == (WS_SYSMENU | WS_CAPTION))
+ {
+ if (ex_style & WS_EX_TOOLWINDOW)
+ rc->left -= GetSystemMetrics(SM_CYSMCAPTION);
+ else
+ {
+ UINT num_buttons = 1;
+
+ /* Minimize and Maximize buttons are always visible in pairs */
+ if (style & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX))
+ num_buttons += 2;
+ else if (ex_style & WS_EX_CONTEXTHELP)
+ num_buttons++;
+
+ rc->left -= GetSystemMetrics(SM_CXSIZE) * num_buttons;
+ }
+ rc->left = max(rc->left, border_w);
+ }
+}
+
+
/* At process attach */
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
{
@@ -222,6 +290,13 @@ HRESULT WINAPI DwmGetWindowAttribute(HWND hwnd, DWORD attribute, PVOID pv_attrib
*(BOOL*)(pv_attribute) = FALSE;
break;
+ case DWMWA_CAPTION_BUTTON_BOUNDS:
+ if (size < sizeof(RECT)) return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
+
+ WARN("DWMWA_CAPTION_BUTTON_BOUNDS: returning rect based on system metrics.\n");
+ get_caption_buttons_rect(hwnd, pv_attribute);
+ break;
+
case DWMWA_EXTENDED_FRAME_BOUNDS:
if (size < sizeof(RECT)) return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
diff --git a/dlls/dwmapi/tests/dwmapi.c b/dlls/dwmapi/tests/dwmapi.c
index e593c30..8308477 100644
--- a/dlls/dwmapi/tests/dwmapi.c
+++ b/dlls/dwmapi/tests/dwmapi.c
@@ -29,8 +29,8 @@ static LRESULT WINAPI test_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARA
static void test_DwmGetWindowAttribute(void)
{
BOOL nc_rendering;
+ RECT rc, rc2;
HRESULT hr;
- RECT rc;
hr = DwmGetWindowAttribute(NULL, DWMWA_NCRENDERING_ENABLED, &nc_rendering, sizeof(nc_rendering));
ok(hr == E_HANDLE || broken(hr == E_INVALIDARG) /* Vista */, "DwmGetWindowAttribute(DWMWA_NCRENDERING_ENABLED) returned 0x%08x.\n", hr);
@@ -53,6 +53,62 @@ static void test_DwmGetWindowAttribute(void)
hr = DwmGetWindowAttribute(test_wnd, DWMWA_EXTENDED_FRAME_BOUNDS, &rc, sizeof(rc));
if (hr != E_HANDLE && hr != DWM_E_COMPOSITIONDISABLED /* Vista */) /* composition is on */
ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_EXTENDED_FRAME_BOUNDS) failed 0x%08x.\n", hr);
+
+ hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc, sizeof(rc) - 1);
+ ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) || broken(hr == E_INVALIDARG) /* Vista */,
+ "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) returned 0x%08x.\n", hr);
+ hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc, sizeof(rc));
+ if (hr != E_HANDLE && hr != DWM_E_COMPOSITIONDISABLED /* Vista */) /* composition is on */
+ {
+ DWORD style = GetWindowLongA(test_wnd, GWL_STYLE), ex_style = GetWindowLongA(test_wnd, GWL_EXSTYLE);
+
+ ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr);
+ ok(rc.left > 0 && rc.right > rc.left && rc.top >= 0 && rc.bottom > rc.top,
+ "unexpected caption rect %s.\n", wine_dbgstr_rect(&rc));
+
+ SetWindowLongA(test_wnd, GWL_STYLE, style & ~(WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
+ hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2));
+ ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr);
+ ok(rc2.left > rc.left && rc2.right == rc.right && rc2.top == rc.top && rc2.bottom == rc.bottom,
+ "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc));
+
+ SetWindowLongA(test_wnd, GWL_EXSTYLE, ex_style | WS_EX_CONTEXTHELP);
+ hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2));
+ ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr);
+ ok(rc2.left > rc.left && rc2.right == rc.right && rc2.top == rc.top && rc2.bottom == rc.bottom,
+ "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc));
+
+ SetWindowLongA(test_wnd, GWL_EXSTYLE, ex_style | WS_EX_TOOLWINDOW);
+ hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2));
+ ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr);
+ ok(rc2.left > rc.left && rc2.right <= rc.right && rc2.top >= rc.top && rc2.bottom <= rc.bottom,
+ "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc));
+ SetWindowLongA(test_wnd, GWL_EXSTYLE, ex_style);
+
+ SetWindowLongA(test_wnd, GWL_STYLE, style & ~WS_SYSMENU);
+ hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2));
+ ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr);
+ ok(rc2.left == rc.right && rc2.right == rc.right && rc2.top == rc.top && rc2.bottom == rc.bottom,
+ "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc));
+ SetWindowLongA(test_wnd, GWL_STYLE, style);
+
+ ShowWindow(test_wnd, SW_SHOWMINIMIZED);
+ ok(IsIconic(test_wnd), "window was not minimized.\n");
+ hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2));
+ ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr);
+ ok(rc2.left - rc.left == rc2.right - rc.right && rc2.left <= rc.left && rc2.top == rc.top && rc2.bottom == rc.bottom,
+ "unexpected caption rect %s (original %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc));
+ ShowWindow(test_wnd, SW_RESTORE);
+ ok(!IsIconic(test_wnd), "window was not restored.\n");
+
+ ShowWindow(test_wnd, SW_HIDE);
+ ok(!IsWindowVisible(test_wnd), "window was not hidden.\n");
+ hr = DwmGetWindowAttribute(test_wnd, DWMWA_CAPTION_BUTTON_BOUNDS, &rc2, sizeof(rc2));
+ ok(hr == S_OK, "DwmGetWindowAttribute(DWMWA_CAPTION_BUTTON_BOUNDS) failed 0x%08x.\n", hr);
+ ok(EqualRect(&rc, &rc2), "unexpected caption rect %s (expected %s).\n", wine_dbgstr_rect(&rc2), wine_dbgstr_rect(&rc));
+ ShowWindow(test_wnd, SW_SHOW);
+ ok(IsWindowVisible(test_wnd), "window was not shown.\n");
+ }
}
static void test_DwmIsCompositionEnabled(void)
--
2.21.0
More information about the wine-devel
mailing list