Index: rostests/apitests/CMakeLists.txt =================================================================== --- rostests/apitests/CMakeLists.txt (revision 75304) +++ rostests/apitests/CMakeLists.txt (working copy) @@ -8,6 +8,7 @@ add_subdirectory(com) add_subdirectory(comctl32) add_subdirectory(crt) +add_subdirectory(uitester) add_subdirectory(dbghelp) add_subdirectory(dciman32) add_subdirectory(dnsapi) Index: rostests/apitests/uitester/CMakeLists.txt =================================================================== --- rostests/apitests/uitester/CMakeLists.txt (nonexistent) +++ rostests/apitests/uitester/CMakeLists.txt (working copy) @@ -0,0 +1,5 @@ +add_executable(uitester_apitest testlist.c scroll.c uitester.rc) +target_link_libraries(uitester_apitest wine) +set_module_type(uitester_apitest win32cui) +add_importlibs(uitester_apitest uxtheme comctl32 user32 gdi32 msvcrt kernel32) +add_rostests_file(TARGET uitester_apitest) Index: rostests/apitests/uitester/scroll.c =================================================================== --- rostests/apitests/uitester/scroll.c (nonexistent) +++ rostests/apitests/uitester/scroll.c (working copy) @@ -0,0 +1,871 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPL - See COPYING in the top level directory + * PURPOSE: Test for scrolling of dialog controls + * PROGRAMMERS: Katayama Hirofumi MZ + */ + +#include "wine/test.h" +#include +#include +#include +#include +#include +#include + +#define FIRST_WAIT 200 +#define INPUT_WAIT 50 +#define LISTBOX_WAIT 500 + +#define MAX_LINES 25 +#define MAX_COLUMNS 60 + +#define DELTA_X 3 +#define DELTA_Y 3 + +#define EF_ARROWLEFT 1 +#define EF_ARROWUP 2 +#define EF_ARROWRIGHT 3 +#define EF_ARROWDOWN 4 +#define EF_SCROLLLEFT 5 +#define EF_SCROLLUP 6 +#define EF_SCROLLRIGHT 7 +#define EF_SCROLLDOWN 8 +#define EF_DRAGTHUMBLEFT 9 +#define EF_DRAGTHUMBUP 10 +#define EF_DRAGTHUMBRIGHT 11 +#define EF_DRAGTHUMBDOWN 12 + +#define MAX_TARGETS 10 + +static INT s_nPos, nTrackPos; +static SCROLLINFO s_si; +static BOOL s_bDragging = FALSE; +static BOOL s_bArrowing = FALSE; +static INT s_nEntryNumber; +static HWND s_ahTargets[MAX_TARGETS] = { NULL }; + +static RECT GetScrollRect(HWND hwnd, INT nBar) +{ + RECT rc; + TCHAR class_name[10]; + SCROLLBARINFO sbi = { sizeof(sbi) }; + if (GetClassName(hwnd, class_name, 10) && + lstrcmpi(class_name, TEXT("SCROLLBAR")) == 0) + { + GetWindowRect(hwnd, &rc); + } + else + { + switch (nBar) + { + case SB_HORZ: + GetScrollBarInfo(hwnd, OBJID_HSCROLL, &sbi); + return sbi.rcScrollBar; + case SB_VERT: + GetScrollBarInfo(hwnd, OBJID_VSCROLL, &sbi); + return sbi.rcScrollBar; + } + } + return rc; +} + +static POINT GetLeftArrowPt(HWND hwnd) +{ + POINT pt; + RECT rc = GetScrollRect(hwnd, SB_HORZ); + pt.x = rc.left + GetSystemMetrics(SM_CXHSCROLL) / 2; + pt.y = rc.bottom - GetSystemMetrics(SM_CYHSCROLL) / 2; + return pt; +} + +static POINT GetRightArrowPt(HWND hwnd) +{ + POINT pt; + RECT rc = GetScrollRect(hwnd, SB_HORZ); + pt.x = rc.right - GetSystemMetrics(SM_CXHSCROLL) / 2; + pt.y = rc.bottom - GetSystemMetrics(SM_CYHSCROLL) / 2; + return pt; +} + +static POINT GetUpArrowPt(HWND hwnd) +{ + POINT pt; + RECT rc = GetScrollRect(hwnd, SB_VERT); + pt.x = rc.left + GetSystemMetrics(SM_CXVSCROLL) / 2; + pt.y = rc.top + GetSystemMetrics(SM_CYVSCROLL) / 2; + return pt; +} + +static POINT GetDownArrowPt(HWND hwnd) +{ + POINT pt; + RECT rc = GetScrollRect(hwnd, SB_VERT); + pt.x = rc.left + GetSystemMetrics(SM_CXVSCROLL) / 2; + pt.y = rc.bottom - GetSystemMetrics(SM_CYVSCROLL) / 2; + return pt; +} + +typedef struct ENTRY +{ + INT EntryNumber; + INT TargetNumber; + INT EF_; + INT Repeat; + INT nBar; +} ENTRY; + +#define TARGET_EDIT 0 +#define TARGET_LISTBOX 1 +#define TARGET_LISTVIEW 2 +#define TARGET_HSCROLLBAR 3 +#define TARGET_VSCROLLBAR 4 +#define TARGET_TREEVIEW 5 + +static const ENTRY s_Entries[] = +{ + /* EDIT */ + { 0, TARGET_EDIT, EF_ARROWRIGHT, 10, SB_HORZ }, + { 1, TARGET_EDIT, EF_ARROWLEFT, 10, SB_HORZ }, + { 2, TARGET_EDIT, EF_ARROWDOWN, 10, SB_VERT }, + { 3, TARGET_EDIT, EF_ARROWUP, 10, SB_VERT }, + { 4, TARGET_EDIT, EF_SCROLLRIGHT, 10, SB_HORZ }, + { 5, TARGET_EDIT, EF_SCROLLLEFT, 10, SB_HORZ }, + { 6, TARGET_EDIT, EF_SCROLLDOWN, 10, SB_VERT }, + { 7, TARGET_EDIT, EF_SCROLLUP, 10, SB_VERT }, + { 8, TARGET_EDIT, EF_DRAGTHUMBRIGHT, 10, SB_HORZ }, + { 9, TARGET_EDIT, EF_DRAGTHUMBLEFT, 10, SB_HORZ }, + { 10, TARGET_EDIT, EF_DRAGTHUMBDOWN, 10, SB_VERT }, + { 11, TARGET_EDIT, EF_DRAGTHUMBUP, 10, SB_VERT }, + /* LISTBOX */ + { 12, TARGET_LISTBOX, EF_ARROWDOWN, 5, SB_VERT }, + { 13, TARGET_LISTBOX, EF_ARROWUP, 5, SB_VERT }, + { 14, TARGET_LISTBOX, EF_SCROLLDOWN, 10, SB_VERT }, + { 15, TARGET_LISTBOX, EF_SCROLLUP, 10, SB_VERT }, + { 16, TARGET_LISTBOX, EF_DRAGTHUMBDOWN, 10, SB_VERT }, + { 17, TARGET_LISTBOX, EF_DRAGTHUMBUP, 10, SB_VERT }, + /* ListView */ + { 18, TARGET_LISTVIEW, EF_ARROWRIGHT, 10, SB_HORZ }, + { 19, TARGET_LISTVIEW, EF_ARROWLEFT, 10, SB_HORZ }, + { 20, TARGET_LISTVIEW, EF_ARROWDOWN, 10, SB_VERT }, + { 21, TARGET_LISTVIEW, EF_ARROWUP, 10, SB_VERT }, + { 22, TARGET_LISTVIEW, EF_SCROLLRIGHT, 10, SB_HORZ }, + { 23, TARGET_LISTVIEW, EF_SCROLLLEFT, 10, SB_HORZ }, + { 24, TARGET_LISTVIEW, EF_SCROLLDOWN, 10, SB_VERT }, + { 25, TARGET_LISTVIEW, EF_SCROLLUP, 10, SB_VERT }, + { 26, TARGET_LISTVIEW, EF_DRAGTHUMBRIGHT, 10, SB_HORZ }, + { 27, TARGET_LISTVIEW, EF_DRAGTHUMBLEFT, 10, SB_HORZ }, + { 28, TARGET_LISTVIEW, EF_DRAGTHUMBDOWN, 10, SB_VERT }, + { 29, TARGET_LISTVIEW, EF_DRAGTHUMBUP, 10, SB_VERT }, + /* HSCROLLBAR */ + { 30, TARGET_HSCROLLBAR, EF_ARROWRIGHT, 10, SB_CTL }, + { 31, TARGET_HSCROLLBAR, EF_ARROWLEFT, 10, SB_CTL }, + { 32, TARGET_HSCROLLBAR, EF_DRAGTHUMBRIGHT, 10, SB_CTL }, + { 33, TARGET_HSCROLLBAR, EF_DRAGTHUMBLEFT, 10, SB_CTL }, + /* VSCROLLBAR */ + { 34, TARGET_VSCROLLBAR, EF_ARROWDOWN, 10, SB_CTL }, + { 35, TARGET_VSCROLLBAR, EF_ARROWUP, 10, SB_CTL }, + { 36, TARGET_VSCROLLBAR, EF_DRAGTHUMBDOWN, 10, SB_CTL }, + { 37, TARGET_VSCROLLBAR, EF_DRAGTHUMBUP, 10, SB_CTL }, + /* TreeView */ + { 38, TARGET_TREEVIEW, EF_ARROWRIGHT, 10, SB_HORZ }, + { 39, TARGET_TREEVIEW, EF_ARROWLEFT, 10, SB_HORZ }, + { 40, TARGET_TREEVIEW, EF_ARROWDOWN, 10, SB_VERT }, + { 41, TARGET_TREEVIEW, EF_ARROWUP, 10, SB_VERT }, + { 42, TARGET_TREEVIEW, EF_SCROLLRIGHT, 10, SB_HORZ }, + { 43, TARGET_TREEVIEW, EF_SCROLLLEFT, 10, SB_HORZ }, + { 44, TARGET_TREEVIEW, EF_SCROLLDOWN, 10, SB_VERT }, + { 45, TARGET_TREEVIEW, EF_SCROLLUP, 10, SB_VERT }, + { 46, TARGET_TREEVIEW, EF_DRAGTHUMBRIGHT, 10, SB_HORZ }, + { 47, TARGET_TREEVIEW, EF_DRAGTHUMBLEFT, 10, SB_HORZ }, + { 48, TARGET_TREEVIEW, EF_DRAGTHUMBDOWN, 10, SB_VERT }, + { 49, TARGET_TREEVIEW, EF_DRAGTHUMBUP, 10, SB_VERT }, +}; + +static void DoMouseEvent(POINT pt, DWORD dwFlags) +{ + INT x = pt.x * 65535 / GetSystemMetrics(SM_CXSCREEN); + INT y = pt.y * 65535 / GetSystemMetrics(SM_CYSCREEN); + mouse_event(dwFlags, x, y, 0, 0); + Sleep(INPUT_WAIT); +} + +static void LeftClick(HWND hCtrl, POINT pt) +{ + DoMouseEvent(pt, MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP); +} + +static void LeftDown(HWND hCtrl, POINT pt) +{ + DoMouseEvent(pt, MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN); +} + +static void LeftMove(HWND hCtrl, POINT pt) +{ + DoMouseEvent(pt, MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE); +} + +static void LeftUp(HWND hCtrl, POINT pt) +{ + DoMouseEvent(pt, MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTUP); +} + +static void DoEvents(void) +{ + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + +static void DoEntry(HWND hwnd, INT EntryNumber, const ENTRY *pEntry) +{ + INT i; + POINT pt; + HWND hCtrl = s_ahTargets[pEntry->TargetNumber]; + s_nEntryNumber = EntryNumber; + + s_si.cbSize = sizeof(s_si); + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + + ok(hCtrl != NULL, "#%d\n", EntryNumber); + switch (pEntry->EF_) + { + case EF_ARROWLEFT: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + pt = GetLeftArrowPt(hCtrl); + s_bArrowing = TRUE; + for (i = 0; i < pEntry->Repeat; ++i) + { + LeftClick(hCtrl, pt); + + DoEvents(); + if (pEntry->TargetNumber == TARGET_LISTBOX) + { + Sleep(LISTBOX_WAIT); + } + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos >= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos >= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + s_bArrowing = FALSE; + break; + case EF_ARROWUP: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + pt = GetUpArrowPt(hCtrl); + s_bArrowing = TRUE; + for (i = 0; i < pEntry->Repeat; ++i) + { + LeftClick(hCtrl, pt); + + DoEvents(); + if (pEntry->TargetNumber == TARGET_LISTBOX) + { + Sleep(LISTBOX_WAIT); + } + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos >= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos >= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + s_bArrowing = FALSE; + break; + case EF_ARROWRIGHT: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + pt = GetRightArrowPt(hCtrl); + s_bArrowing = TRUE; + for (i = 0; i < pEntry->Repeat; ++i) + { + LeftClick(hCtrl, pt); + + DoEvents(); + if (pEntry->TargetNumber == TARGET_LISTBOX) + { + Sleep(LISTBOX_WAIT); + } + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos <= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos <= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + s_bArrowing = FALSE; + break; + case EF_ARROWDOWN: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + pt = GetDownArrowPt(hCtrl); + s_bArrowing = TRUE; + for (i = 0; i < pEntry->Repeat; ++i) + { + LeftClick(hCtrl, pt); + + DoEvents(); + if (pEntry->TargetNumber == TARGET_LISTBOX) + { + Sleep(LISTBOX_WAIT); + } + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos <= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos <= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + s_bArrowing = FALSE; + break; + case EF_SCROLLLEFT: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + for (i = 0; i < pEntry->Repeat; ++i) + { + SendMessage(hCtrl, WM_HSCROLL, MAKEWPARAM(SB_LINELEFT, 0), 0); + Sleep(INPUT_WAIT); + + DoEvents(); + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos >= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos >= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + break; + case EF_SCROLLUP: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + for (i = 0; i < pEntry->Repeat; ++i) + { + SendMessage(hCtrl, WM_VSCROLL, MAKEWPARAM(SB_LINEUP, 0), 0); + Sleep(INPUT_WAIT); + + DoEvents(); + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos >= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos >= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + break; + case EF_SCROLLRIGHT: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + for (i = 0; i < pEntry->Repeat; ++i) + { + SendMessage(hCtrl, WM_HSCROLL, MAKEWPARAM(SB_LINERIGHT, 0), 0); + Sleep(INPUT_WAIT); + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos <= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos <= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + break; + case EF_SCROLLDOWN: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + for (i = 0; i < pEntry->Repeat; ++i) + { + SendMessage(hCtrl, WM_VSCROLL, MAKEWPARAM(SB_LINEDOWN, 0), 0); + Sleep(INPUT_WAIT); + + DoEvents(); + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos <= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos <= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + break; + case EF_DRAGTHUMBLEFT: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_si.nPos = s_si.nMax; + s_si.nTrackPos = s_si.nMax; + SetScrollInfo(hCtrl, pEntry->nBar, &s_si, TRUE); + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + pt = GetRightArrowPt(hCtrl); + pt.x -= GetSystemMetrics(SM_CXHSCROLL); + s_bDragging = TRUE; + LeftDown(hCtrl, pt); + for (i = 0; i < pEntry->Repeat; ++i) + { + pt.x -= DELTA_X; + LeftMove(hCtrl, pt); + + DoEvents(); + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos >= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos >= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + s_bDragging = FALSE; + LeftUp(hCtrl, pt); + break; + case EF_DRAGTHUMBRIGHT: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_si.nPos = s_si.nMin; + s_si.nTrackPos = s_si.nMin; + SetScrollInfo(hCtrl, pEntry->nBar, &s_si, TRUE); + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + pt = GetLeftArrowPt(hCtrl); + pt.x += GetSystemMetrics(SM_CXHSCROLL); + s_bDragging = TRUE; + LeftDown(hCtrl, pt); + for (i = 0; i < pEntry->Repeat; ++i) + { + pt.x += DELTA_X; + LeftMove(hCtrl, pt); + + DoEvents(); + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos <= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos <= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + s_bDragging = FALSE; + LeftUp(hCtrl, pt); + break; + case EF_DRAGTHUMBUP: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_si.nPos = s_si.nMax; + s_si.nTrackPos = s_si.nMax; + SetScrollInfo(hCtrl, pEntry->nBar, &s_si, TRUE); + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + pt = GetDownArrowPt(hCtrl); + pt.y -= GetSystemMetrics(SM_CYVSCROLL); + s_bDragging = TRUE; + LeftDown(hCtrl, pt); + for (i = 0; i < pEntry->Repeat; ++i) + { + pt.y -= DELTA_Y; + LeftMove(hCtrl, pt); + + DoEvents(); + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos >= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos >= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + s_bDragging = FALSE; + LeftUp(hCtrl, pt); + break; + case EF_DRAGTHUMBDOWN: + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_si.nPos = s_si.nMin; + s_si.nTrackPos = s_si.nMin; + SetScrollInfo(hCtrl, pEntry->nBar, &s_si, TRUE); + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + pt = GetUpArrowPt(hCtrl); + pt.y += GetSystemMetrics(SM_CYVSCROLL); + s_bDragging = TRUE; + LeftDown(hCtrl, pt); + for (i = 0; i < pEntry->Repeat; ++i) + { + pt.y += DELTA_Y; + LeftMove(hCtrl, pt); + + DoEvents(); + + s_si.fMask = SIF_ALL | SIF_TRACKPOS; + GetScrollInfo(hCtrl, pEntry->nBar, &s_si); + ok(s_nPos <= s_si.nPos, "#%d: %d, %d\n", EntryNumber, s_nPos, s_si.nPos); + ok(nTrackPos <= s_si.nTrackPos, "#%d: %d, %d\n", EntryNumber, nTrackPos, s_si.nTrackPos); + + s_nPos = s_si.nPos; + nTrackPos = s_si.nTrackPos; + } + s_bDragging = FALSE; + LeftUp(hCtrl, pt); + break; + } +} + +static LRESULT CALLBACK +HookedWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + LRESULT result; + WNDPROC fn = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA); + + ZeroMemory(&s_si, sizeof(s_si)); + s_si.cbSize = sizeof(s_si); + s_si.fMask = SIF_POS | SIF_TRACKPOS; + + switch (uMsg) + { + case WM_HSCROLL: + if (fn) + { + result = CallWindowProc(fn, hwnd, uMsg, wParam, lParam); + GetScrollInfo(hwnd, SB_HORZ, &s_si); + if (s_bArrowing) + { + ; + } + else if (LOWORD(wParam) != SB_ENDSCROLL) + { + ok(s_si.nTrackPos == s_si.nPos, "#%d: %d, %d, %d\n", s_nEntryNumber, s_si.nTrackPos, s_si.nPos, LOWORD(wParam)); + } + return result; + } + break; + case WM_VSCROLL: + if (fn) + { + result = CallWindowProc(fn, hwnd, uMsg, wParam, lParam); + GetScrollInfo(hwnd, SB_VERT, &s_si); + if (s_bArrowing) + { + ; + } + else if (LOWORD(wParam) != SB_ENDSCROLL) + { + ok(s_si.nTrackPos == s_si.nPos, "#%d: %d, %d, %d\n", s_nEntryNumber, s_si.nTrackPos, s_si.nPos, LOWORD(wParam)); + } + return result; + } + break; + } + if (fn) + { + return CallWindowProc(fn, hwnd, uMsg, wParam, lParam); + } + return DefWindowProc(hwnd, uMsg, wParam, lParam); +} + +static BOOL OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) +{ + INT i, n; + TCHAR buf[MAX_LINES * (MAX_COLUMNS + 7) + 1], buf2[32]; + SCROLLINFO s_si; + HWND hCtrl; + + // EDIT + buf[0] = 0; + for (i = 0; i < MAX_LINES; ++i) + { + for (n = 0; n < MAX_COLUMNS; ++n) + { + wsprintf(buf2, TEXT("%d"), ((n + i) % 10)); + lstrcat(buf, buf2); + } + lstrcat(buf, TEXT("---\r\n")); + lstrcat(buf, TEXT("\r\n")); + } + SetDlgItemText(hwnd, edt1, buf); + hCtrl = GetDlgItem(hwnd, edt1); + SetWindowLongPtr(hCtrl, GWLP_USERDATA, (LONG_PTR)SubclassWindow(hCtrl, HookedWndProc)); + + // ListBox + for (i = 0; i < MAX_LINES; ++i) + { + wsprintf(buf, "item #%d: ", i); + for (n = 0; n < MAX_COLUMNS - 7; ++n) + { + wsprintf(buf2, TEXT("%d"), i % 10); + lstrcat(buf, buf2); + } + ListBox_AddString(GetDlgItem(hwnd, lst1), buf); + } + hCtrl = GetDlgItem(hwnd, lst1); + SetWindowLongPtr(hCtrl, GWLP_USERDATA, (LONG_PTR)SubclassWindow(hCtrl, HookedWndProc)); + + // ListView + { + LV_COLUMN column; + ZeroMemory(&column, sizeof(column)); + column.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; + column.pszText = TEXT("Column"); + column.cx = 400; + column.iSubItem = 0; + ListView_InsertColumn(GetDlgItem(hwnd, ctl1), 0, &column); + for (i = 0; i < MAX_LINES; ++i) + { + LV_ITEM item; + ZeroMemory(&item, sizeof(item)); + wsprintf(buf, "item #%d: ", i); + for (n = 0; n < MAX_COLUMNS - 7; ++n) + { + wsprintf(buf2, TEXT("%d"), i % 10); + lstrcat(buf, buf2); + } + item.mask = LVIF_TEXT; + item.iItem = i; + item.pszText = buf; + ListView_InsertItem(GetDlgItem(hwnd, ctl1), &item); + } + } + hCtrl = GetDlgItem(hwnd, ctl1); + SetWindowLongPtr(hCtrl, GWLP_USERDATA, (LONG_PTR)SubclassWindow(hCtrl, HookedWndProc)); + + // HSCROLLBAR + ZeroMemory(&s_si, sizeof(s_si)); + s_si.cbSize = sizeof(s_si); + s_si.fMask = SIF_ALL; + s_si.nMin = 0; + s_si.nMax = 110; + s_si.nPage = 20; + s_si.nPos = 0; + SetScrollInfo(GetDlgItem(hwnd, scr1), SB_CTL, &s_si, TRUE); + + // VSCROLLBAR + ZeroMemory(&s_si, sizeof(s_si)); + s_si.cbSize = sizeof(s_si); + s_si.fMask = SIF_ALL; + s_si.nMin = 0; + s_si.nMax = 110; + s_si.nPage = 20; + s_si.nPos = 0; + SetScrollInfo(GetDlgItem(hwnd, scr2), SB_CTL, &s_si, TRUE); + + // TreeView + { + TV_INSERTSTRUCT is; + for (i = 0; i < MAX_LINES; ++i) + { + ZeroMemory(&is, sizeof(is)); + wsprintf(buf, "item #%d: ", i); + for (n = 0; n < MAX_COLUMNS - 7; ++n) + { + wsprintf(buf2, TEXT("%d"), i % 10); + lstrcat(buf, buf2); + } + is.hParent = NULL; + is.hInsertAfter = TVI_LAST; + is.item.mask = TVIF_TEXT; + is.item.pszText = buf; + TreeView_InsertItem(GetDlgItem(hwnd, 1000), &is); + } + } + hCtrl = GetDlgItem(hwnd, 1000); + SetWindowLongPtr(hCtrl, GWLP_USERDATA, (LONG_PTR)SubclassWindow(hCtrl, HookedWndProc)); + + i = 0; + s_ahTargets[i++] = GetDlgItem(hwnd, edt1); + s_ahTargets[i++] = GetDlgItem(hwnd, lst1); + s_ahTargets[i++] = GetDlgItem(hwnd, ctl1); + s_ahTargets[i++] = GetDlgItem(hwnd, scr1); + s_ahTargets[i++] = GetDlgItem(hwnd, scr2); + s_ahTargets[i++] = GetDlgItem(hwnd, 1000); + +#if 1 + Sleep(500); + SetTimer(hwnd, 999, FIRST_WAIT, NULL); +#endif + return FALSE; +} + +static unsigned __stdcall test_thread_proc(void *arg) +{ + UINT i; + HWND hwnd = (HWND)arg; + + for (i = 0; i < _countof(s_Entries); ++i) + { + DoEntry(hwnd, s_Entries[i].EntryNumber, &s_Entries[i]); + } + + PostMessage(hwnd, WM_COMMAND, IDOK, 0); + return 0; +} + +static void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) +{ + HANDLE hThread; + switch (id) + { + case 666: + hThread = (HANDLE)(ULONG_PTR)_beginthreadex(NULL, 0, test_thread_proc, hwnd, 0, NULL); + ok(hThread != NULL, "failed to create thread\n"); + CloseHandle(hThread); + break; + case IDOK: + EndDialog(hwnd, IDOK); + break; + case IDCANCEL: + EndDialog(hwnd, IDCANCEL); + break; + } +} + +static void OnTimer(HWND hwnd, UINT id) +{ + KillTimer(hwnd, id); + PostMessage(hwnd, WM_COMMAND, 666, 0); +} + +static void OnHScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos) +{ + SCROLLINFO s_si; + if (hwndCtl == NULL) + return; + + ZeroMemory(&s_si, sizeof(s_si)); + s_si.cbSize = sizeof(s_si); + s_si.fMask = SIF_ALL; + GetScrollInfo(hwndCtl, SB_CTL, &s_si); + + switch (code) + { + case SB_LEFT: + s_si.nPos = s_si.nMax; + case SB_RIGHT: + s_si.nPos = s_si.nMax; + break; + case SB_ENDSCROLL: + break; + case SB_LINELEFT: + s_si.nPos -= 2; + if (s_si.nPos < s_si.nMin) + s_si.nPos = s_si.nMin; + break; + case SB_LINERIGHT: + s_si.nPos += 2; + if (s_si.nPos > s_si.nMax) + s_si.nPos = s_si.nMax; + break; + case SB_PAGELEFT: + s_si.nPos -= s_si.nPage; + if (s_si.nPos < s_si.nMin) + s_si.nPos = s_si.nMin; + break; + case SB_PAGERIGHT: + s_si.nPos += s_si.nPage; + if (s_si.nPos > s_si.nMax) + s_si.nPos = s_si.nMax; + break; + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + s_si.nPos = pos; + break; + } + + SetScrollInfo(hwndCtl, SB_CTL, &s_si, TRUE); +} + +static void OnVScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos) +{ + SCROLLINFO s_si; + if (hwndCtl == NULL) + return; + + ZeroMemory(&s_si, sizeof(s_si)); + s_si.cbSize = sizeof(s_si); + s_si.fMask = SIF_ALL; + GetScrollInfo(hwndCtl, SB_CTL, &s_si); + + switch (code) + { + case SB_TOP: + s_si.nPos = s_si.nMax; + case SB_BOTTOM: + s_si.nPos = s_si.nMax; + break; + case SB_ENDSCROLL: + break; + case SB_LINEUP: + s_si.nPos -= 2; + if (s_si.nPos < s_si.nMin) + s_si.nPos = s_si.nMin; + break; + case SB_LINEDOWN: + s_si.nPos += 2; + if (s_si.nPos > s_si.nMax) + s_si.nPos = s_si.nMax; + break; + case SB_PAGEUP: + s_si.nPos -= s_si.nPage; + if (s_si.nPos < s_si.nMin) + s_si.nPos = s_si.nMin; + break; + case SB_PAGEDOWN: + s_si.nPos += s_si.nPage; + if (s_si.nPos > s_si.nMax) + s_si.nPos = s_si.nMax; + break; + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + s_si.nPos = pos; + break; + } + + SetScrollInfo(hwndCtl, SB_CTL, &s_si, TRUE); +} + +static INT_PTR CALLBACK +DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + HANDLE_MSG(hwnd, WM_INITDIALOG, OnInitDialog); + HANDLE_MSG(hwnd, WM_COMMAND, OnCommand); + HANDLE_MSG(hwnd, WM_TIMER, OnTimer); + HANDLE_MSG(hwnd, WM_HSCROLL, OnHScroll); + HANDLE_MSG(hwnd, WM_VSCROLL, OnVScroll); + } + return 0; +} + +START_TEST(scroll) +{ + InitCommonControls(); + + DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(1), NULL, DialogProc); +}