mirror of
https://github.com/reactos/reactos.git
synced 2026-06-08 08:52:59 +08:00
[NTUSER][USER32_APITEST] Support ShowWindow.SW_FORCEMINIMIZE (#8261)
One more step to support ghost windows. JIRA issue: CORE-19671 - Add IntForceMinimizeWindow helper function. - Use IntForceMinimizeWindow in co_WinPosShowWindow function. - Enhance ShowWindow testcase in user32_apitest. - Add mask to the return value of GetWindowLong.
This commit is contained in:
committed by
GitHub
parent
6ebf15d838
commit
d958a24678
@@ -2,10 +2,11 @@
|
||||
* PROJECT: ReactOS API tests
|
||||
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
|
||||
* PURPOSE: Tests for ShowWindow
|
||||
* COPYRIGHT: Copyright 2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
* COPYRIGHT: Copyright 2021-2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include <versionhelpers.h>
|
||||
|
||||
typedef struct TEST_ENTRY
|
||||
{
|
||||
@@ -164,7 +165,7 @@ WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
return 0;
|
||||
}
|
||||
|
||||
START_TEST(ShowWindow)
|
||||
static VOID Test_ShowWindow_Main(VOID)
|
||||
{
|
||||
WNDCLASSA wc;
|
||||
UINT iTest;
|
||||
@@ -181,3 +182,164 @@ START_TEST(ShowWindow)
|
||||
DoTestEntry(&s_entries[iTest]);
|
||||
}
|
||||
}
|
||||
|
||||
#define RED RGB(255, 0, 0)
|
||||
|
||||
static COLORREF CheckColor(VOID)
|
||||
{
|
||||
HDC hDC = GetDC(NULL);
|
||||
COLORREF color = GetPixel(hDC, 100, 100);
|
||||
ReleaseDC(NULL, hDC);
|
||||
return color;
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
ForceMinimizeThreadFunc(LPVOID arg)
|
||||
{
|
||||
BOOL ret;
|
||||
HWND hwnd = (HWND)arg;
|
||||
DWORD style, exstyle;
|
||||
|
||||
Sleep(100);
|
||||
ok_long(CheckColor(), RED);
|
||||
|
||||
SetWindowLongPtrW(hwnd, GWL_EXSTYLE, WS_EX_MAKEVISIBLEWHENUNGHOSTED);
|
||||
ret = ShowWindow(hwnd, SW_FORCEMINIMIZE);
|
||||
Sleep(100);
|
||||
ok(ret != FALSE, "ret was FALSE\n");
|
||||
ok(CheckColor() != RED, "Color was red\n");
|
||||
style = GetWindowLongPtrW(hwnd, GWL_STYLE);
|
||||
if (IsWindowsVistaOrGreater())
|
||||
ok((style & (WS_POPUP | WS_MINIMIZE | WS_VISIBLE)) == (WS_POPUP | WS_MINIMIZE | WS_VISIBLE), "style was 0x%08lX\n", style);
|
||||
else
|
||||
ok((style & (WS_POPUP | WS_MINIMIZE | WS_VISIBLE)) == (WS_POPUP), "style was 0x%08lX\n", style);
|
||||
exstyle = GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
|
||||
ok_long(exstyle, 0);
|
||||
|
||||
ShowWindow(hwnd, SW_MINIMIZE);
|
||||
Sleep(100);
|
||||
ok(CheckColor() != RED, "Color was red\n");
|
||||
|
||||
SetWindowLongPtrW(hwnd, GWL_EXSTYLE, WS_EX_MAKEVISIBLEWHENUNGHOSTED);
|
||||
ret = ShowWindow(hwnd, SW_FORCEMINIMIZE);
|
||||
Sleep(100);
|
||||
ok(ret != FALSE, "ret was FALSE\n");
|
||||
ok(CheckColor() != RED, "Color was red\n");
|
||||
style = GetWindowLongPtrW(hwnd, GWL_STYLE);
|
||||
ok((style & (WS_POPUP | WS_MINIMIZE | WS_VISIBLE)) == (WS_POPUP | WS_MINIMIZE | WS_VISIBLE), "style was 0x%08lX\n", style);
|
||||
exstyle = GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
|
||||
ok_long(exstyle, 0);
|
||||
|
||||
ShowWindow(hwnd, SW_SHOWNORMAL);
|
||||
Sleep(100);
|
||||
ok_long(CheckColor(), RED);
|
||||
|
||||
SetWindowLongPtrW(hwnd, GWL_EXSTYLE, WS_EX_MAKEVISIBLEWHENUNGHOSTED);
|
||||
ret = ShowWindow(hwnd, SW_FORCEMINIMIZE);
|
||||
Sleep(100);
|
||||
ok(ret != FALSE, "ret was FALSE\n");
|
||||
ok(CheckColor() != RED, "Color was red\n");
|
||||
style = GetWindowLongPtrW(hwnd, GWL_STYLE);
|
||||
if (IsWindowsVistaOrGreater())
|
||||
ok((style & (WS_POPUP | WS_MINIMIZE | WS_VISIBLE)) == (WS_POPUP | WS_MINIMIZE | WS_VISIBLE), "style was 0x%08lX\n", style);
|
||||
else
|
||||
ok((style & (WS_POPUP | WS_MINIMIZE | WS_VISIBLE)) == (WS_POPUP), "style was 0x%08lX\n", style);
|
||||
exstyle = GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
|
||||
ok_long(exstyle, 0);
|
||||
|
||||
SetWindowLongPtrW(hwnd, GWL_EXSTYLE, WS_EX_MAKEVISIBLEWHENUNGHOSTED);
|
||||
ret = ShowWindow(hwnd, SW_FORCEMINIMIZE);
|
||||
Sleep(100);
|
||||
if (IsWindowsVistaOrGreater())
|
||||
ok(ret != FALSE, "ret was FALSE\n");
|
||||
else
|
||||
ok_bool_false(ret, "Return was");
|
||||
ok(CheckColor() != RED, "Color was red\n");
|
||||
style = GetWindowLongPtrW(hwnd, GWL_STYLE);
|
||||
if (IsWindowsVistaOrGreater())
|
||||
ok((style & (WS_POPUP | WS_MINIMIZE | WS_VISIBLE)) == (WS_POPUP | WS_MINIMIZE | WS_VISIBLE), "style was 0x%08lX\n", style);
|
||||
else
|
||||
ok((style & (WS_POPUP | WS_MINIMIZE | WS_VISIBLE)) == (WS_POPUP), "style was 0x%08lX\n", style);
|
||||
exstyle = GetWindowLongPtrW(hwnd, GWL_EXSTYLE);
|
||||
ok_long(exstyle, 0);
|
||||
|
||||
PostMessageW(hwnd, WM_CLOSE, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
ForceMinimizeWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
default:
|
||||
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static VOID
|
||||
Test_WS_FORCEMINIMIZE_Sub(HBRUSH hbr)
|
||||
{
|
||||
WNDCLASSW wc;
|
||||
HWND hwnd;
|
||||
DWORD style;
|
||||
HINSTANCE hInstance = GetModuleHandleW(NULL);
|
||||
DWORD dwThreadId;
|
||||
HANDLE hThread;
|
||||
MSG msg;
|
||||
|
||||
ZeroMemory(&wc, sizeof(wc));
|
||||
wc.lpfnWndProc = ForceMinimizeWndProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hIcon = LoadIconW(NULL, (PCWSTR)IDI_APPLICATION);
|
||||
wc.hCursor = LoadCursorW(NULL, (PCWSTR)IDC_ARROW);
|
||||
wc.hbrBackground = hbr;
|
||||
wc.lpszClassName = L"SW_FORCEMINIMIZE";
|
||||
if (!RegisterClassW(&wc))
|
||||
{
|
||||
skip("RegisterClassW failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
style = WS_POPUP | WS_VISIBLE;
|
||||
hwnd = CreateWindowExW(0, L"SW_FORCEMINIMIZE", L"SW_FORCEMINIMIZE", style,
|
||||
50, 50, 100, 100, NULL, NULL, hInstance, NULL);
|
||||
if (!hwnd)
|
||||
{
|
||||
skip("CreateWindowExW failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hThread = CreateThread(NULL, 0, ForceMinimizeThreadFunc, hwnd, 0, &dwThreadId);
|
||||
if (!hThread)
|
||||
{
|
||||
skip("CreateThread failed\n");
|
||||
DestroyWindow(hwnd);
|
||||
return;
|
||||
}
|
||||
CloseHandle(hThread);
|
||||
|
||||
while (GetMessageW(&msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
Test_WS_FORCEMINIMIZE()
|
||||
{
|
||||
HBRUSH hbr = CreateSolidBrush(RED);
|
||||
Test_WS_FORCEMINIMIZE_Sub(hbr);
|
||||
DeleteObject(hbr);
|
||||
}
|
||||
|
||||
START_TEST(ShowWindow)
|
||||
{
|
||||
Test_ShowWindow_Main();
|
||||
Test_WS_FORCEMINIMIZE();
|
||||
}
|
||||
|
||||
@@ -2586,9 +2586,36 @@ co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
|
||||
return SwpFlags;
|
||||
}
|
||||
|
||||
// SW_FORCEMINIMIZE
|
||||
void IntForceMinimizeWindow(PWND pWnd)
|
||||
{
|
||||
HRGN hRgn;
|
||||
PREGION pRgn;
|
||||
|
||||
if ((pWnd->style & (WS_MINIMIZE | WS_VISIBLE)) != WS_VISIBLE)
|
||||
return;
|
||||
|
||||
if (pWnd->state & WNDS_DESTROYED)
|
||||
return;
|
||||
|
||||
pWnd->ExStyle &= ~WS_EX_MAKEVISIBLEWHENUNGHOSTED;
|
||||
|
||||
IntSetStyle(pWnd, 0, WS_VISIBLE);
|
||||
|
||||
// Invalidate and redraw the window region
|
||||
hRgn = GreCreateRectRgnIndirect(&pWnd->rcWindow);
|
||||
pRgn = REGION_LockRgn(hRgn);
|
||||
co_UserRedrawWindow(UserGetDesktopWindow(), NULL, pRgn, RDW_ALLCHILDREN | RDW_ERASE | RDW_INVALIDATE);
|
||||
REGION_UnlockRgn(pRgn);
|
||||
GreDeleteObject(hRgn);
|
||||
|
||||
// Activate the other window if necessary
|
||||
if (pWnd->spwndParent == pWnd->head.rpdesk->pDeskInfo->spwnd)
|
||||
co_WinPosActivateOtherWindow(pWnd);
|
||||
}
|
||||
|
||||
/*
|
||||
ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits!
|
||||
Win: xxxShowWindow
|
||||
*/
|
||||
BOOLEAN FASTCALL
|
||||
co_WinPosShowWindow(PWND Wnd, INT Cmd)
|
||||
@@ -2661,7 +2688,10 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd)
|
||||
break;
|
||||
}
|
||||
|
||||
case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
|
||||
case SW_FORCEMINIMIZE:
|
||||
IntForceMinimizeWindow(Wnd);
|
||||
return WasVisible;
|
||||
|
||||
case SW_SHOWMINNOACTIVE:
|
||||
Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
|
||||
/* Fall through. */
|
||||
|
||||
@@ -1077,6 +1077,14 @@ GetClassWord(
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
#define PUBLIC_EXSTYLE ( \
|
||||
WS_EX_NOACTIVATE | WS_EX_COMPOSITED | WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT | \
|
||||
WS_EX_LAYERED | WS_EX_APPWINDOW | WS_EX_STATICEDGE | WS_EX_CONTROLPARENT | \
|
||||
WS_EX_LEFTSCROLLBAR | WS_EX_RTLREADING | WS_EX_RIGHT | WS_EX_CONTEXTHELP | \
|
||||
WS_EX_CLIENTEDGE | WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_MDICHILD | \
|
||||
WS_EX_TRANSPARENT | WS_EX_ACCEPTFILES | WS_EX_TOPMOST | WS_EX_NOPARENTNOTIFY | \
|
||||
WS_EX_DRAGDETECT | WS_EX_DLGMODALFRAME \
|
||||
)
|
||||
|
||||
LONG_PTR IntGetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
|
||||
{
|
||||
@@ -1116,7 +1124,7 @@ LONG_PTR IntGetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
|
||||
{
|
||||
case GWLP_USERDATA: retvalue = wndPtr->dwUserData; break;
|
||||
case GWL_STYLE: retvalue = wndPtr->style; break;
|
||||
case GWL_EXSTYLE: retvalue = wndPtr->ExStyle; break;
|
||||
case GWL_EXSTYLE: retvalue = (wndPtr->ExStyle & PUBLIC_EXSTYLE); break;
|
||||
case GWLP_ID: retvalue = wndPtr->IDMenu; break;
|
||||
case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hModule; break;
|
||||
#if 0
|
||||
|
||||
Reference in New Issue
Block a user