mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[USER32_APITEST] Add scrollbar showing/hiding testcase (#7254)
Checks CORE-19669, making sure that CS_HREDRAW and CS_VREDRAW are respected when the client area changes due to the scrollbar disappearing or re-appearing. ROSTESTS-397 Co-authored-by: Stanislav Motylkov <x86corez@gmail.com>
This commit is contained in:
parent
fd327db20f
commit
a9b77d89fb
3 changed files with 730 additions and 0 deletions
|
@ -41,6 +41,7 @@ list(APPEND SOURCE
|
||||||
RedrawWindow.c
|
RedrawWindow.c
|
||||||
RegisterClassEx.c
|
RegisterClassEx.c
|
||||||
RegisterHotKey.c
|
RegisterHotKey.c
|
||||||
|
ScrollBarRedraw.c
|
||||||
ScrollBarWndExtra.c
|
ScrollBarWndExtra.c
|
||||||
ScrollDC.c
|
ScrollDC.c
|
||||||
ScrollWindowEx.c
|
ScrollWindowEx.c
|
||||||
|
|
727
modules/rostests/apitests/user32/ScrollBarRedraw.c
Normal file
727
modules/rostests/apitests/user32/ScrollBarRedraw.c
Normal file
|
@ -0,0 +1,727 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS API tests
|
||||||
|
* LICENSE: MIT (https://spdx.org/licenses/MIT)
|
||||||
|
* PURPOSE: Tests window redrawing when scrollbars appear or disappear
|
||||||
|
* COPYRIGHT: Copyright 2024 Marek Benc <benc.marek.elektro98@proton.me>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
|
||||||
|
#define TEST_CLASS_NAME L"ScrollBarRedraw"
|
||||||
|
#define TEST_WINDOW_TITLE L"ScrollBarRedraw"
|
||||||
|
|
||||||
|
static LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
#define TEST_COLOR_COUNT 16
|
||||||
|
|
||||||
|
/* Standard Windows 16-Color VGA Color palette. */
|
||||||
|
static COLORREF Colors[] =
|
||||||
|
{
|
||||||
|
RGB(0x00, 0x00, 0x00), /* Black */
|
||||||
|
RGB(0x00, 0x00, 0x80), /* Dark Blue */
|
||||||
|
RGB(0x00, 0x80, 0x00), /* Dark Green */
|
||||||
|
RGB(0x00, 0x80, 0x80), /* Dark Cyan */
|
||||||
|
RGB(0x80, 0x00, 0x00), /* Dark Red */
|
||||||
|
RGB(0x80, 0x00, 0x80), /* Dark Magenta */
|
||||||
|
RGB(0x80, 0x80, 0x00), /* Dark Yellow */
|
||||||
|
RGB(0xC0, 0xC0, 0xC0), /* Light Gray */
|
||||||
|
RGB(0x80, 0x80, 0x80), /* Dark Gray */
|
||||||
|
RGB(0x00, 0x00, 0xFF), /* Blue */
|
||||||
|
RGB(0x00, 0xFF, 0x00), /* Green */
|
||||||
|
RGB(0x00, 0xFF, 0xFF), /* Cyan */
|
||||||
|
RGB(0xFF, 0x00, 0x00), /* Red */
|
||||||
|
RGB(0xFF, 0x00, 0xFF), /* Magenta */
|
||||||
|
RGB(0xFF, 0xFF, 0x00), /* Yellow */
|
||||||
|
RGB(0xFF, 0xFF, 0xFF) /* White */
|
||||||
|
};
|
||||||
|
static HBRUSH ColorBrushes[TEST_COLOR_COUNT] = { 0 };
|
||||||
|
|
||||||
|
static BOOL HaveHRedraw = FALSE;
|
||||||
|
static BOOL HaveVRedraw = FALSE;
|
||||||
|
static BOOL WindowCreatedOk = FALSE;
|
||||||
|
|
||||||
|
typedef enum _FSM_STATE
|
||||||
|
{
|
||||||
|
FSM_STATE_START,
|
||||||
|
FSM_STATE_VSCR_SHOWN,
|
||||||
|
FSM_STATE_VSCR_HIDDEN,
|
||||||
|
FSM_STATE_HSCR_SHOWN,
|
||||||
|
FSM_STATE_HSCR_HIDDEN,
|
||||||
|
FSM_STATE_BSCR_SHOWN,
|
||||||
|
FSM_STATE_BSCR_HIDDEN,
|
||||||
|
FSM_STATE_WIDTH_SHRUNK,
|
||||||
|
FSM_STATE_WIDTH_EXPANDED,
|
||||||
|
FSM_STATE_HEIGHT_SHRUNK,
|
||||||
|
FSM_STATE_HEIGHT_EXPANDED,
|
||||||
|
FSM_STATE_BOTH_SHRUNK,
|
||||||
|
FSM_STATE_BOTH_EXPANDED,
|
||||||
|
FSM_STATE_END
|
||||||
|
} FSM_STATE;
|
||||||
|
|
||||||
|
#define FSM_STEP_PERIOD_MS 250
|
||||||
|
|
||||||
|
static UINT_PTR FsmTimer = 0;
|
||||||
|
static UINT CurrentColor = 0;
|
||||||
|
static FSM_STATE FsmState = FSM_STATE_START;
|
||||||
|
|
||||||
|
static int ClientWidth = 0;
|
||||||
|
static int ClientHeight = 0;
|
||||||
|
|
||||||
|
static int OrigWidth = 0;
|
||||||
|
static int OrigHeight = 0;
|
||||||
|
static int SmallWidth = 0;
|
||||||
|
static int SmallHeight = 0;
|
||||||
|
|
||||||
|
static void ColorsCleanup(void)
|
||||||
|
{
|
||||||
|
UINT Iter;
|
||||||
|
|
||||||
|
for (Iter = 0; Iter < _countof(ColorBrushes); Iter++)
|
||||||
|
{
|
||||||
|
if (ColorBrushes[Iter] != NULL)
|
||||||
|
{
|
||||||
|
DeleteObject(ColorBrushes[Iter]);
|
||||||
|
ColorBrushes[Iter] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL ColorsInit(void)
|
||||||
|
{
|
||||||
|
UINT Iter;
|
||||||
|
|
||||||
|
assert(_countof(Colors) == _countof(ColorBrushes));
|
||||||
|
|
||||||
|
for (Iter = 0; Iter < _countof(ColorBrushes); Iter++)
|
||||||
|
{
|
||||||
|
ColorBrushes[Iter] = CreateSolidBrush(Colors[Iter]);
|
||||||
|
if (ColorBrushes[Iter] == NULL)
|
||||||
|
{
|
||||||
|
ColorsCleanup();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RunTestWindow(PCWSTR ClassName, PCWSTR WindowTitle, UINT ClassStyle)
|
||||||
|
{
|
||||||
|
WNDCLASSW Class = { 0 };
|
||||||
|
HWND Window;
|
||||||
|
MSG Message;
|
||||||
|
HINSTANCE hInst;
|
||||||
|
|
||||||
|
CurrentColor = 0;
|
||||||
|
hInst = GetModuleHandleW(NULL);
|
||||||
|
|
||||||
|
Class.style = ClassStyle;
|
||||||
|
Class.lpfnWndProc = WindowProc;
|
||||||
|
Class.cbClsExtra = 0;
|
||||||
|
Class.cbWndExtra = 0;
|
||||||
|
Class.hInstance = hInst;
|
||||||
|
Class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
Class.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
Class.hbrBackground = ColorBrushes[CurrentColor];
|
||||||
|
Class.lpszMenuName = NULL;
|
||||||
|
Class.lpszClassName = ClassName;
|
||||||
|
|
||||||
|
if (!RegisterClassW(&Class))
|
||||||
|
{
|
||||||
|
skip("Failed to register window class '%ls', code: %ld\n",
|
||||||
|
ClassName, GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window = CreateWindowW(ClassName,
|
||||||
|
WindowTitle,
|
||||||
|
WS_OVERLAPPEDWINDOW | WS_VSCROLL | WS_HSCROLL,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
hInst,
|
||||||
|
NULL);
|
||||||
|
if (Window == NULL)
|
||||||
|
{
|
||||||
|
skip("Failed to create window of class '%ls', code: %ld\n",
|
||||||
|
ClassName, GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowWindow(Window, SW_SHOWNORMAL);
|
||||||
|
UpdateWindow(Window);
|
||||||
|
|
||||||
|
while (GetMessageW(&Message, NULL, 0, 0))
|
||||||
|
{
|
||||||
|
TranslateMessage(&Message);
|
||||||
|
DispatchMessageW(&Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(ScrollBarRedraw)
|
||||||
|
{
|
||||||
|
if (!ColorsInit())
|
||||||
|
{
|
||||||
|
skip("Failed to initialize colors and solid color brushes\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("Running test without specifying either CS_HREDRAW or CS_HREDRAW\n");
|
||||||
|
HaveHRedraw = FALSE;
|
||||||
|
HaveVRedraw = FALSE;
|
||||||
|
RunTestWindow(TEST_CLASS_NAME L"NoRedraw",
|
||||||
|
TEST_WINDOW_TITLE L" (No Redraw Flags)",
|
||||||
|
0);
|
||||||
|
|
||||||
|
trace("Running test with CS_HREDRAW\n");
|
||||||
|
HaveHRedraw = TRUE;
|
||||||
|
HaveVRedraw = FALSE;
|
||||||
|
RunTestWindow(TEST_CLASS_NAME L"HRedraw",
|
||||||
|
TEST_WINDOW_TITLE L" (CS_HREDRAW)",
|
||||||
|
CS_HREDRAW);
|
||||||
|
|
||||||
|
trace("Running test with CS_VREDRAW\n");
|
||||||
|
HaveHRedraw = FALSE;
|
||||||
|
HaveVRedraw = TRUE;
|
||||||
|
RunTestWindow(TEST_CLASS_NAME L"VRedraw",
|
||||||
|
TEST_WINDOW_TITLE L" (CS_VREDRAW)",
|
||||||
|
CS_VREDRAW);
|
||||||
|
|
||||||
|
trace("Running test with both CS_HREDRAW and CS_VREDRAW\n");
|
||||||
|
HaveHRedraw = TRUE;
|
||||||
|
HaveVRedraw = TRUE;
|
||||||
|
RunTestWindow(TEST_CLASS_NAME L"HRedrawVRedraw",
|
||||||
|
TEST_WINDOW_TITLE L" (CS_HREDRAW | CS_VREDRAW)",
|
||||||
|
CS_HREDRAW | CS_VREDRAW);
|
||||||
|
|
||||||
|
trace("Test complete\n");
|
||||||
|
ColorsCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HideVertScrollBar(HWND Window)
|
||||||
|
{
|
||||||
|
SCROLLINFO ScrollInfo;
|
||||||
|
|
||||||
|
ScrollInfo.cbSize = sizeof(ScrollInfo);
|
||||||
|
ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
|
||||||
|
ScrollInfo.nPage = ClientHeight;
|
||||||
|
|
||||||
|
ScrollInfo.nMin = 0;
|
||||||
|
ScrollInfo.nMax = ClientHeight - 1;
|
||||||
|
ScrollInfo.nPos = 0;
|
||||||
|
|
||||||
|
SetScrollInfo(Window, SB_VERT, &ScrollInfo, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowVertScrollBar(HWND Window)
|
||||||
|
{
|
||||||
|
SCROLLINFO ScrollInfo;
|
||||||
|
|
||||||
|
ScrollInfo.cbSize = sizeof(ScrollInfo);
|
||||||
|
ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
|
||||||
|
ScrollInfo.nPage = ClientHeight;
|
||||||
|
|
||||||
|
ScrollInfo.nMin = 0;
|
||||||
|
ScrollInfo.nMax = (3 * ClientHeight) - 1;
|
||||||
|
ScrollInfo.nPos = 0;
|
||||||
|
|
||||||
|
SetScrollInfo(Window, SB_VERT, &ScrollInfo, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void HideHorzScrollBar(HWND Window)
|
||||||
|
{
|
||||||
|
SCROLLINFO ScrollInfo;
|
||||||
|
|
||||||
|
ScrollInfo.cbSize = sizeof(ScrollInfo);
|
||||||
|
ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
|
||||||
|
ScrollInfo.nPage = ClientWidth;
|
||||||
|
|
||||||
|
ScrollInfo.nMin = 0;
|
||||||
|
ScrollInfo.nMax = ClientWidth - 1;
|
||||||
|
ScrollInfo.nPos = 0;
|
||||||
|
|
||||||
|
SetScrollInfo(Window, SB_HORZ, &ScrollInfo, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ShowHorzScrollBar(HWND Window)
|
||||||
|
{
|
||||||
|
SCROLLINFO ScrollInfo;
|
||||||
|
|
||||||
|
ScrollInfo.cbSize = sizeof(ScrollInfo);
|
||||||
|
ScrollInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
|
||||||
|
ScrollInfo.nPage = ClientWidth;
|
||||||
|
|
||||||
|
ScrollInfo.nMin = 0;
|
||||||
|
ScrollInfo.nMax = (3 * ClientWidth) - 1;
|
||||||
|
ScrollInfo.nPos = 0;
|
||||||
|
|
||||||
|
SetScrollInfo(Window, SB_HORZ, &ScrollInfo, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int FsmStep(HWND Window)
|
||||||
|
{
|
||||||
|
static COLORREF PrevColor = CLR_INVALID;
|
||||||
|
COLORREF Color = CLR_INVALID;
|
||||||
|
HDC hdc = NULL;
|
||||||
|
|
||||||
|
if (FsmState != FSM_STATE_END)
|
||||||
|
{
|
||||||
|
hdc = GetDC(Window);
|
||||||
|
if (hdc == NULL)
|
||||||
|
{
|
||||||
|
skip("Failed to get device context\n");
|
||||||
|
|
||||||
|
FsmState = FSM_STATE_END;
|
||||||
|
DestroyWindow(Window);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Color = GetPixel(hdc, ClientWidth / 4, ClientHeight / 4);
|
||||||
|
|
||||||
|
ReleaseDC(Window, hdc);
|
||||||
|
hdc = NULL;
|
||||||
|
|
||||||
|
if (Color == CLR_INVALID)
|
||||||
|
{
|
||||||
|
skip("Failed to get window color\n");
|
||||||
|
|
||||||
|
FsmState = FSM_STATE_END;
|
||||||
|
DestroyWindow(Window);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("FsmState: %d, Color: 0x%.8lX\n", FsmState, Color);
|
||||||
|
|
||||||
|
switch (FsmState)
|
||||||
|
{
|
||||||
|
case FSM_STATE_START:
|
||||||
|
ShowVertScrollBar(Window);
|
||||||
|
FsmState = FSM_STATE_VSCR_SHOWN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_VSCR_SHOWN:
|
||||||
|
if (HaveHRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_HREDRAW specified, but appearence of vertical scroll bar"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"CS_HREDRAW not specified, but appearence of vertical scroll bar"
|
||||||
|
" triggered unneccessary redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
HideVertScrollBar(Window);
|
||||||
|
FsmState = FSM_STATE_VSCR_HIDDEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_VSCR_HIDDEN:
|
||||||
|
if (HaveHRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_HREDRAW specified, but disappearence of vertical scroll bar"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"CS_HREDRAW not specified, but disappearence of vertical scroll bar"
|
||||||
|
" triggered unneccessary redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowHorzScrollBar(Window);
|
||||||
|
FsmState = FSM_STATE_HSCR_SHOWN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_HSCR_SHOWN:
|
||||||
|
if (HaveVRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_VREDRAW specified, but appearence of horizontal scroll bar"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"CS_VREDRAW not specified, but appearence of horizontal scroll bar"
|
||||||
|
" triggered unneccessary redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
HideHorzScrollBar(Window);
|
||||||
|
FsmState = FSM_STATE_HSCR_HIDDEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_HSCR_HIDDEN:
|
||||||
|
if (HaveVRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_VREDRAW specified, but disappearence of horizontal scroll bar"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"CS_VREDRAW not specified, but disappearence of horizontal scroll bar"
|
||||||
|
" triggered unneccessary redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowVertScrollBar(Window);
|
||||||
|
ShowHorzScrollBar(Window);
|
||||||
|
|
||||||
|
FsmState = FSM_STATE_BSCR_SHOWN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_BSCR_SHOWN:
|
||||||
|
if (HaveHRedraw || HaveVRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_HREDRAW or CS_VREDRAW specified, but appearence of both scroll bars"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"Neither CS_HREDRAW nor CS_VREDRAW specified, but appearence"
|
||||||
|
" of both scroll bars triggered unneccessary redraw,"
|
||||||
|
" PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
HideVertScrollBar(Window);
|
||||||
|
HideHorzScrollBar(Window);
|
||||||
|
|
||||||
|
FsmState = FSM_STATE_BSCR_HIDDEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_BSCR_HIDDEN:
|
||||||
|
if (HaveHRedraw || HaveVRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_HREDRAW or CS_VREDRAW specified, but disappearence of both scroll bars"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"Neither CS_HREDRAW nor CS_VREDRAW specified, but disappearence"
|
||||||
|
" of both scroll bars triggered unneccessary redraw,"
|
||||||
|
" PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(Window, HWND_TOPMOST, 0, 0, SmallWidth, OrigHeight, SWP_NOMOVE);
|
||||||
|
FsmState = FSM_STATE_WIDTH_SHRUNK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_WIDTH_SHRUNK:
|
||||||
|
if (HaveHRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_HREDRAW specified, but horizontal window shrinkage"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"CS_HREDRAW not specified, but horizontal window shrinkage"
|
||||||
|
" triggered unneccessary redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(Window, HWND_TOPMOST, 0, 0, OrigWidth, OrigHeight, SWP_NOMOVE);
|
||||||
|
FsmState = FSM_STATE_WIDTH_EXPANDED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_WIDTH_EXPANDED:
|
||||||
|
if (HaveHRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_HREDRAW specified, but horizontal window expansion"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"CS_HREDRAW not specified, but horizontal window expansion"
|
||||||
|
" triggered unneccessary redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(Window, HWND_TOPMOST, 0, 0, OrigWidth, SmallHeight, SWP_NOMOVE);
|
||||||
|
FsmState = FSM_STATE_HEIGHT_SHRUNK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_HEIGHT_SHRUNK:
|
||||||
|
if (HaveVRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_VREDRAW specified, but vertical window shrinkage"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"CS_VREDRAW not specified, but vertical window shrinkage"
|
||||||
|
" triggered unneccessary redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(Window, HWND_TOPMOST, 0, 0, OrigWidth, OrigHeight, SWP_NOMOVE);
|
||||||
|
FsmState = FSM_STATE_HEIGHT_EXPANDED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_HEIGHT_EXPANDED:
|
||||||
|
if (HaveVRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_VREDRAW specified, but vertical window expansion"
|
||||||
|
" didn't trigger redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"CS_VREDRAW not specified, but vertical window expansion"
|
||||||
|
" triggered unneccessary redraw, PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(Window, HWND_TOPMOST, 0, 0, SmallWidth, SmallHeight, SWP_NOMOVE);
|
||||||
|
|
||||||
|
FsmState = FSM_STATE_BOTH_SHRUNK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_BOTH_SHRUNK:
|
||||||
|
if (HaveHRedraw || HaveVRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_HREDRAW or CS_VREDRAW specified, but combined"
|
||||||
|
" vertical/horizontal shrinkage didn't trigger redraw,"
|
||||||
|
" PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"Neither CS_HREDRAW nor CS_VREDRAW specified, but combined"
|
||||||
|
" vertical/horizontal shrinkage triggered unneccessary redraw,"
|
||||||
|
" PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(Window, HWND_TOPMOST, 0, 0, OrigWidth, OrigHeight, SWP_NOMOVE);
|
||||||
|
|
||||||
|
FsmState = FSM_STATE_BOTH_EXPANDED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_BOTH_EXPANDED:
|
||||||
|
if (HaveHRedraw || HaveVRedraw)
|
||||||
|
{
|
||||||
|
ok(Color != PrevColor,
|
||||||
|
"CS_HREDRAW or CS_VREDRAW specified, but combined"
|
||||||
|
" vertical/horizontal expansion didn't trigger redraw,"
|
||||||
|
" PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok(Color == PrevColor,
|
||||||
|
"Neither CS_HREDRAW nor CS_VREDRAW specified, but combined"
|
||||||
|
" vertical/horizontal expansion triggered unneccessary redraw,"
|
||||||
|
" PrevColor: 0x%.8lX, Color: 0x%.8lX\n",
|
||||||
|
PrevColor, Color);
|
||||||
|
}
|
||||||
|
|
||||||
|
FsmState = FSM_STATE_END;
|
||||||
|
DestroyWindow(Window);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FSM_STATE_END:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrevColor = Color;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int OnPaint(HWND Window)
|
||||||
|
{
|
||||||
|
HRGN Region;
|
||||||
|
HDC hdc;
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
|
||||||
|
hdc = BeginPaint(Window, &ps);
|
||||||
|
if (hdc == NULL)
|
||||||
|
{
|
||||||
|
skip("Failed to get device context\n");
|
||||||
|
DestroyWindow(Window);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Region = CreateRectRgn(ps.rcPaint.left,
|
||||||
|
ps.rcPaint.top,
|
||||||
|
ps.rcPaint.right,
|
||||||
|
ps.rcPaint.bottom);
|
||||||
|
if (Region == NULL)
|
||||||
|
{
|
||||||
|
skip("Failed to create drawing region\n");
|
||||||
|
EndPaint(Window, &ps);
|
||||||
|
DestroyWindow(Window);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FillRgn(hdc, Region, ColorBrushes[CurrentColor]))
|
||||||
|
{
|
||||||
|
skip("Failed to paint the window\n");
|
||||||
|
DeleteObject(Region);
|
||||||
|
EndPaint(Window, &ps);
|
||||||
|
DestroyWindow(Window);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteObject(Region);
|
||||||
|
EndPaint(Window, &ps);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LRESULT CALLBACK WindowProc(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (Message)
|
||||||
|
{
|
||||||
|
case WM_CREATE:
|
||||||
|
{
|
||||||
|
RECT Rect;
|
||||||
|
WindowCreatedOk = FALSE;
|
||||||
|
|
||||||
|
/* It's important for the test that the entire Window is visible. */
|
||||||
|
if (!SetWindowPos(Window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE))
|
||||||
|
{
|
||||||
|
skip("Failed to set window as top-most, code: %ld\n", GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetClientRect(Window, &Rect))
|
||||||
|
{
|
||||||
|
skip("Failed to retrieve client area dimensions, code: %ld\n", GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ClientWidth = Rect.right;
|
||||||
|
ClientHeight = Rect.bottom;
|
||||||
|
|
||||||
|
if (!GetWindowRect(Window, &Rect))
|
||||||
|
{
|
||||||
|
skip("Failed to retrieve window dimensions, code: %ld\n", GetLastError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
OrigWidth = Rect.right - Rect.left;
|
||||||
|
OrigHeight = Rect.bottom - Rect.top;
|
||||||
|
|
||||||
|
SmallWidth = max((OrigWidth * 3) / 4, 1);
|
||||||
|
SmallHeight = max((OrigHeight * 3) / 4, 1);
|
||||||
|
OrigWidth = max(OrigWidth, SmallWidth + 1);
|
||||||
|
OrigHeight = max(OrigHeight, SmallHeight + 1);
|
||||||
|
|
||||||
|
trace("OrigWidth: %d, OrigHeight: %d, SmallWidth: %d, SmallHeight: %d\n",
|
||||||
|
OrigWidth, OrigHeight, SmallWidth, SmallHeight);
|
||||||
|
|
||||||
|
HideVertScrollBar(Window);
|
||||||
|
HideHorzScrollBar(Window);
|
||||||
|
|
||||||
|
FsmState = FSM_STATE_START;
|
||||||
|
FsmTimer = 0;
|
||||||
|
WindowCreatedOk = TRUE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_PAINT:
|
||||||
|
if (FsmTimer == 0 && WindowCreatedOk)
|
||||||
|
{
|
||||||
|
FsmTimer = SetTimer(Window, 1, FSM_STEP_PERIOD_MS, NULL);
|
||||||
|
if (FsmTimer == 0)
|
||||||
|
{
|
||||||
|
skip("Failed to initialize FSM timer, code: %ld\n", GetLastError());
|
||||||
|
WindowCreatedOk = FALSE;
|
||||||
|
DestroyWindow(Window);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OnPaint(Window);
|
||||||
|
|
||||||
|
case WM_SIZE:
|
||||||
|
{
|
||||||
|
int NewWidth = LOWORD(lParam);
|
||||||
|
int NewHeight = HIWORD(lParam);
|
||||||
|
|
||||||
|
if (NewWidth != 0 && NewHeight != 0 &&
|
||||||
|
(NewWidth != ClientWidth || NewHeight != ClientHeight))
|
||||||
|
{
|
||||||
|
CurrentColor = (CurrentColor + 1) % TEST_COLOR_COUNT;
|
||||||
|
SetClassLongPtrW(Window,
|
||||||
|
GCLP_HBRBACKGROUND,
|
||||||
|
(LONG_PTR)ColorBrushes[CurrentColor]);
|
||||||
|
|
||||||
|
trace("New window size: %d x %d, new color: 0x%.8lX\n",
|
||||||
|
NewWidth, NewHeight, Colors[CurrentColor]);
|
||||||
|
|
||||||
|
ClientWidth = NewWidth;
|
||||||
|
ClientHeight = NewHeight;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WM_ERASEBKGND:
|
||||||
|
/* We use WM_PAINT instead, since WM_ERASEBKGND is issued before WM_SIZE. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case WM_TIMER:
|
||||||
|
if (wParam != 0 && wParam == FsmTimer)
|
||||||
|
{
|
||||||
|
return FsmStep(Window);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_NCDESTROY:
|
||||||
|
if (FsmTimer != 0)
|
||||||
|
{
|
||||||
|
KillTimer(Window, FsmTimer);
|
||||||
|
FsmTimer = 0;
|
||||||
|
|
||||||
|
if (FsmState != FSM_STATE_END)
|
||||||
|
{
|
||||||
|
skip("Window closed before test concluded, FsmState: %d, FSM_STATE_END: %d.\n",
|
||||||
|
FsmState, FSM_STATE_END);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (WindowCreatedOk)
|
||||||
|
{
|
||||||
|
skip("Window closed before test began.\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return DefWindowProcW(Window, Message, wParam, lParam);
|
||||||
|
}
|
|
@ -42,6 +42,7 @@ extern void func_RealGetWindowClass(void);
|
||||||
extern void func_RedrawWindow(void);
|
extern void func_RedrawWindow(void);
|
||||||
extern void func_RegisterHotKey(void);
|
extern void func_RegisterHotKey(void);
|
||||||
extern void func_RegisterClassEx(void);
|
extern void func_RegisterClassEx(void);
|
||||||
|
extern void func_ScrollBarRedraw(void);
|
||||||
extern void func_ScrollBarWndExtra(void);
|
extern void func_ScrollBarWndExtra(void);
|
||||||
extern void func_ScrollDC(void);
|
extern void func_ScrollDC(void);
|
||||||
extern void func_ScrollWindowEx(void);
|
extern void func_ScrollWindowEx(void);
|
||||||
|
@ -104,6 +105,7 @@ const struct test winetest_testlist[] =
|
||||||
{ "RedrawWindow", func_RedrawWindow },
|
{ "RedrawWindow", func_RedrawWindow },
|
||||||
{ "RegisterHotKey", func_RegisterHotKey },
|
{ "RegisterHotKey", func_RegisterHotKey },
|
||||||
{ "RegisterClassEx", func_RegisterClassEx },
|
{ "RegisterClassEx", func_RegisterClassEx },
|
||||||
|
{ "ScrollBarRedraw", func_ScrollBarRedraw },
|
||||||
{ "ScrollBarWndExtra", func_ScrollBarWndExtra },
|
{ "ScrollBarWndExtra", func_ScrollBarWndExtra },
|
||||||
{ "ScrollDC", func_ScrollDC },
|
{ "ScrollDC", func_ScrollDC },
|
||||||
{ "ScrollWindowEx", func_ScrollWindowEx },
|
{ "ScrollWindowEx", func_ScrollWindowEx },
|
||||||
|
|
Loading…
Reference in a new issue