out_of_range_item[] = {'O','u','t',' ','o','f',' ','R','a','n','g','e',' ','I','t','e','m',0};
/* Allocate space for result */
- textBuffer = malloc(MAX_CHARS);
+ textBuffer = HeapAlloc(GetProcessHeap(), 0, MAX_CHARS);
/* Basic comboboxex test */
myHwnd = createComboEx(WS_BORDER | WS_VISIBLE | WS_CHILD | CBS_DROPDOWN);
/* Add items onto the end of the combobox */
res = addItem(myHwnd, -1, first_item);
- ok(res == 0, "Adding simple item failed (%ld)\n", res);
+ ok(res == 0, "Adding simple item failed (%d)\n", res);
res = addItem(myHwnd, -1, second_item);
- ok(res == 1, "Adding simple item failed (%ld)\n", res);
+ ok(res == 1, "Adding simple item failed (%d)\n", res);
res = addItem(myHwnd, 2, third_item);
- ok(res == 2, "Adding simple item failed (%ld)\n", res);
+ ok(res == 2, "Adding simple item failed (%d)\n", res);
res = addItem(myHwnd, 1, middle_item);
- ok(res == 1, "Inserting simple item failed (%ld)\n", res);
+ ok(res == 1, "Inserting simple item failed (%d)\n", res);
/* Add an item completely out of range */
res = addItem(myHwnd, 99, out_of_range_item);
- ok(res == -1, "Adding using out of range index worked unexpectedly (%ld)\n", res);
+ ok(res == -1, "Adding using out of range index worked unexpectedly (%d)\n", res);
res = addItem(myHwnd, 5, out_of_range_item);
- ok(res == -1, "Adding using out of range index worked unexpectedly (%ld)\n", res);
+ ok(res == -1, "Adding using out of range index worked unexpectedly (%d)\n", res);
/* Removed: Causes traps on Windows XP
res = addItem(myHwnd, -2, "Out Of Range Item");
ok(res == -1, "Adding out of range worked unexpectedly (%ld)\n", res);
*/
- /* Get an item completely out of range */
- res = getItem(myHwnd, 99, &cbexItem);
- ok(res == 0, "Getting item using out of range index worked unexpectedly (%ld, %s)\n", res, cbexItem.pszText);
- res = getItem(myHwnd, 4, &cbexItem);
- ok(res == 0, "Getting item using out of range index worked unexpectedly (%ld, %s)\n", res, cbexItem.pszText);
- res = getItem(myHwnd, -2, &cbexItem);
- ok(res == 0, "Getting item using out of range index worked unexpectedly (%ld, %s)\n", res, cbexItem.pszText);
-
- /* Get an item in range */
- res = getItem(myHwnd, 0, &cbexItem);
- ok(res != 0, "Getting item using valid index failed unexpectedly (%ld)\n", res);
+ /* Get an item completely out of range */
+ res = getItem(myHwnd, 99, &cbexItem);
+ ok(res == 0, "Getting item using out of range index worked unexpectedly (%d, %s)\n", res, cbexItem.pszText);
+ res = getItem(myHwnd, 4, &cbexItem);
+ ok(res == 0, "Getting item using out of range index worked unexpectedly (%d, %s)\n", res, cbexItem.pszText);
+ res = getItem(myHwnd, -2, &cbexItem);
+ ok(res == 0, "Getting item using out of range index worked unexpectedly (%d, %s)\n", res, cbexItem.pszText);
+
+ /* Get an item in range */
+ res = getItem(myHwnd, 0, &cbexItem);
+ ok(res != 0, "Getting item using valid index failed unexpectedly (%d)\n", res);
ok(strcmp(first_item, cbexItem.pszText) == 0, "Getting item returned wrong string (%s)\n", cbexItem.pszText);
- res = getItem(myHwnd, 1, &cbexItem);
- ok(res != 0, "Getting item using valid index failed unexpectedly (%ld)\n", res);
+ res = getItem(myHwnd, 1, &cbexItem);
+ ok(res != 0, "Getting item using valid index failed unexpectedly (%d)\n", res);
ok(strcmp(middle_item, cbexItem.pszText) == 0, "Getting item returned wrong string (%s)\n", cbexItem.pszText);
- res = getItem(myHwnd, 2, &cbexItem);
- ok(res != 0, "Getting item using valid index failed unexpectedly (%ld)\n", res);
+ res = getItem(myHwnd, 2, &cbexItem);
+ ok(res != 0, "Getting item using valid index failed unexpectedly (%d)\n", res);
ok(strcmp(second_item, cbexItem.pszText) == 0, "Getting item returned wrong string (%s)\n", cbexItem.pszText);
- res = getItem(myHwnd, 3, &cbexItem);
- ok(res != 0, "Getting item using valid index failed unexpectedly (%ld)\n", res);
+ res = getItem(myHwnd, 3, &cbexItem);
+ ok(res != 0, "Getting item using valid index failed unexpectedly (%d)\n", res);
ok(strcmp(third_item, cbexItem.pszText) == 0, "Getting item returned wrong string (%s)\n", cbexItem.pszText);
- /* Set an item completely out of range */
- res = setItem(myHwnd, 99, replacement_item);
- ok(res == 0, "Setting item using out of range index worked unexpectedly (%ld)\n", res);
- res = setItem(myHwnd, 4, replacement_item);
- ok(res == 0, "Setting item using out of range index worked unexpectedly (%ld)\n", res);
- res = setItem(myHwnd, -2, replacement_item);
- ok(res == 0, "Setting item using out of range index worked unexpectedly (%ld)\n", res);
+ /* Set an item completely out of range */
+ res = setItem(myHwnd, 99, replacement_item);
+ ok(res == 0, "Setting item using out of range index worked unexpectedly (%d)\n", res);
+ res = setItem(myHwnd, 4, replacement_item);
+ ok(res == 0, "Setting item using out of range index worked unexpectedly (%d)\n", res);
+ res = setItem(myHwnd, -2, replacement_item);
+ ok(res == 0, "Setting item using out of range index worked unexpectedly (%d)\n", res);
- /* Set an item in range */
+ /* Set an item in range */
res = setItem(myHwnd, 0, replacement_item);
- ok(res != 0, "Setting first item failed (%ld)\n", res);
+ ok(res != 0, "Setting first item failed (%d)\n", res);
res = setItem(myHwnd, 3, replacement_item);
- ok(res != 0, "Setting last item failed (%ld)\n", res);
+ ok(res != 0, "Setting last item failed (%d)\n", res);
/* Remove items completely out of range (4 items in control at this point) */
res = delItem(myHwnd, -1);
- ok(res == CB_ERR, "Deleting using out of range index worked unexpectedly (%ld)\n", res);
+ ok(res == CB_ERR, "Deleting using out of range index worked unexpectedly (%d)\n", res);
res = delItem(myHwnd, 4);
- ok(res == CB_ERR, "Deleting using out of range index worked unexpectedly (%ld)\n", res);
+ ok(res == CB_ERR, "Deleting using out of range index worked unexpectedly (%d)\n", res);
/* Remove items in range (4 items in control at this point) */
res = delItem(myHwnd, 3);
- ok(res == 3, "Deleting using out of range index failed (%ld)\n", res);
+ ok(res == 3, "Deleting using out of range index failed (%d)\n", res);
res = delItem(myHwnd, 0);
- ok(res == 2, "Deleting using out of range index failed (%ld)\n", res);
+ ok(res == 2, "Deleting using out of range index failed (%d)\n", res);
res = delItem(myHwnd, 0);
- ok(res == 1, "Deleting using out of range index failed (%ld)\n", res);
+ ok(res == 1, "Deleting using out of range index failed (%d)\n", res);
res = delItem(myHwnd, 0);
- ok(res == 0, "Deleting using out of range index failed (%ld)\n", res);
+ ok(res == 0, "Deleting using out of range index failed (%d)\n", res);
/* Remove from an empty box */
res = delItem(myHwnd, 0);
- ok(res == CB_ERR, "Deleting using out of range index worked unexpectedly (%ld)\n", res);
+ ok(res == CB_ERR, "Deleting using out of range index worked unexpectedly (%d)\n", res);
/* Cleanup */
- free(textBuffer);
+ HeapFree(GetProcessHeap(), 0, textBuffer);
}
-LRESULT CALLBACK ComboExTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+static LRESULT CALLBACK ComboExTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
-
+
default:
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
-
+
return 0L;
}
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandleA(NULL);
wc.hIcon = NULL;
- wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW));
+ wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = ComboExTestClass;
wc.lpfnWndProc = ComboExTestWndProc;
RegisterClassA(&wc);
- hComboExParentWnd = CreateWindowExA(0, ComboExTestClass, "ComboEx test", WS_OVERLAPPEDWINDOW,
+ hComboExParentWnd = CreateWindowExA(0, ComboExTestClass, "ComboEx test", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
assert(hComboExParentWnd != NULL);
static void cleanup(void)
{
MSG msg;
-
+
PostMessageA(hComboExParentWnd, WM_CLOSE, 0, 0);
while (GetMessageA(&msg,0,0,0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
-
+
UnregisterClassA(ComboExTestClass, GetModuleHandleA(NULL));
}
-<module name="comctl32_winetest" type="win32cui" installbase="bin" installname="comctl32_winetest.exe" allowwarnings="true">
- <include base="comctl32_winetest">.</include>
- <define name="__USE_W32API" />
- <library>shlwapi</library>
- <library>ole32</library>
- <library>comctl32</library>
- <library>ntdll</library>
- <library>gdi32</library>
- <library>user32</library>
- <library>kernel32</library>
- <library>advapi32</library>
- <file>comboex.c</file>
- <file>dpa.c</file>
- <file>header.c</file>
- <file>imagelist.c</file>
- <file>listview.c</file>
- <file>monthcal.c</file>
- <file>mru.c</file>
- <file>progress.c</file>
- <file>propsheet.c</file>
- <file>subclass.c</file>
- <file>tab.c</file>
- <file>testlist.c</file>
- <file>toolbar.c</file>
- <file>tooltips.c</file>
- <file>treeview.c</file>
- <file>updown.c</file>
- <file>propsheet.rc</file>
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
+<module name="comctl32_winetest" type="win32cui" installbase="bin" installname="comctl32_winetest.exe" allowwarnings="true" entrypoint="0">
+ <include base="comctl32_winetest">.</include>
+ <define name="WINVER">0x600</define>
+ <define name="_WIN32_WINNT">0x600</define>
+ <library>wine</library>
+ <library>comctl32</library>
+ <library>ole32</library>
+ <library>shlwapi</library>
+ <library>user32</library>
+ <library>gdi32</library>
+ <library>advapi32</library>
+ <library>kernel32</library>
+ <library>ntdll</library>
+ <file>comboex.c</file>
+ <file>datetime.c</file>
+ <file>dpa.c</file>
+ <file>header.c</file>
+ <file>imagelist.c</file>
+ <file>listview.c</file>
+ <file>misc.c</file>
+ <file>monthcal.c</file>
+ <file>mru.c</file>
+ <file>msg.c</file>
+ <file>progress.c</file>
+ <file>propsheet.c</file>
+ <file>rebar.c</file>
+ <file>status.c</file>
+ <file>subclass.c</file>
+ <file>tab.c</file>
+ <file>toolbar.c</file>
+ <file>tooltips.c</file>
+ <file>trackbar.c</file>
+ <file>treeview.c</file>
+ <file>updown.c</file>
+ <file>rsrc.rc</file>
+ <file>testlist.c</file>
</module>
--- /dev/null
+Index: dpa.c
+===================================================================
+--- dpa.c (revision 25766)
++++ dpa.c (working copy)
+@@ -25,6 +25,7 @@
+
+ #include "windef.h"
+ #include "winbase.h"
++#include "wingdi.h"
+ #include "winuser.h"
+ #include "commctrl.h"
+ #include "objidl.h"
+Index: monthcal.c
+===================================================================
+--- monthcal.c (revision 25766)
++++ monthcal.c (working copy)
+@@ -23,6 +23,7 @@
+
+ #include "windef.h"
+ #include "winbase.h"
++#include "wingdi.h"
+ #include "winuser.h"
+
+ #include "commctrl.h"
--- /dev/null
+/* Unit test suite for datetime control.
+*
+* Copyright 2007 Kanit Therdsteerasukdi
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#include <windows.h>
+#include <commctrl.h>
+
+#include "wine/test.h"
+#include "msg.h"
+
+#define expect(EXPECTED, GOT) ok((GOT)==(EXPECTED), "Expected %d, got %ld\n", (EXPECTED), (GOT))
+
+#define expect_unsuccess(EXPECTED, GOT) ok((GOT)==(EXPECTED), "Expected %d(unsuccessful), got %ld(successful)\n", (EXPECTED), (GOT))
+
+#define NUM_MSG_SEQUENCES 1
+#define DATETIME_SEQ_INDEX 0
+
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+
+static const struct message test_dtm_set_format_seq[] = {
+ { DTM_SETFORMATA, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { DTM_SETFORMATA, sent|wparam, 0x00000000 },
+ { 0 }
+};
+
+static const struct message test_dtm_set_and_get_mccolor_seq[] = {
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000000, 0x00ffffff },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000000, 0x00dcb464 },
+ { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000004, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000004, 0x00ffffff },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000004, 0x00dcb464 },
+ { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000004, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000001, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000001, 0x00ffffff },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000001, 0x00dcb464 },
+ { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000001, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000002, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000002, 0x00ffffff },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000002, 0x00dcb464 },
+ { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000002, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000003, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000003, 0x00ffffff },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000003, 0x00dcb464 },
+ { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000003, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000005, 0x00000000 },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000005, 0x00ffffff },
+ { DTM_SETMCCOLOR, sent|wparam|lparam, 0x00000005, 0x00dcb464 },
+ { DTM_GETMCCOLOR, sent|wparam|lparam, 0x00000005, 0x00000000 },
+ { 0 }
+};
+
+static const struct message test_dtm_set_and_get_mcfont_seq[] = {
+ { DTM_SETMCFONT, sent|lparam, 0, 0x00000001 },
+ { DTM_GETMCFONT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
+
+static const struct message test_dtm_get_monthcal_seq[] = {
+ { DTM_GETMONTHCAL, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
+
+static const struct message test_dtm_set_and_get_range_seq[] = {
+ { DTM_SETRANGE, sent|wparam, 0x00000001 },
+ { DTM_GETRANGE, sent|wparam, 0x00000000 },
+ { DTM_SETRANGE, sent|wparam, 0x00000002 },
+ { DTM_SETRANGE, sent|wparam, 0x00000002 },
+ { DTM_GETRANGE, sent|wparam, 0x00000000},
+ { DTM_SETRANGE, sent|wparam, 0x00000001 },
+ { DTM_SETRANGE, sent|wparam, 0x00000003 },
+ { DTM_SETRANGE, sent|wparam, 0x00000003 },
+ { DTM_GETRANGE, sent|wparam, 0x00000000 },
+ { DTM_SETRANGE, sent|wparam, 0x00000003 },
+ { DTM_GETRANGE, sent|wparam, 0x00000000 },
+ { DTM_SETRANGE, sent|wparam, 0x00000003 },
+ { DTM_GETRANGE, sent|wparam, 0x00000000 },
+ { 0 }
+};
+
+static const struct message test_dtm_set_range_swap_min_max_seq[] = {
+ { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { DTM_GETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { DTM_SETRANGE, sent|wparam, 0x00000003 },
+ { DTM_GETRANGE, sent|wparam, 0x00000000 },
+ { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { DTM_GETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { DTM_SETRANGE, sent|wparam, 0x00000003 },
+ { DTM_GETRANGE, sent|wparam, 0x00000000 },
+ { DTM_SETRANGE, sent|wparam, 0x00000003 },
+ { DTM_GETRANGE, sent|wparam, 0x00000000 },
+ { DTM_SETRANGE, sent|wparam, 0x00000003 },
+ { DTM_GETRANGE, sent|wparam, 0x00000000 },
+ { 0 }
+};
+
+static const struct message test_dtm_set_and_get_system_time_seq[] = {
+ { DTM_SETSYSTEMTIME, sent|wparam, 0x00000001 },
+ { WM_DESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { WM_NCDESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { DTM_SETSYSTEMTIME, sent|wparam, 0x00000001 },
+ { DTM_GETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { DTM_GETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { DTM_SETSYSTEMTIME, sent|wparam, 0x00000000 },
+ { 0 }
+};
+
+static const struct message destroy_window_seq[] = {
+ { WM_DESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { WM_NCDESTROY, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
+
+struct subclass_info
+{
+ WNDPROC oldproc;
+};
+
+static LRESULT WINAPI datetime_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ trace("datetime: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, DATETIME_SEQ_INDEX, &msg);
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static HWND create_datetime_control(DWORD style, DWORD exstyle)
+{
+ struct subclass_info *info;
+ HWND hWndDateTime = NULL;
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ hWndDateTime = CreateWindowEx(0,
+ DATETIMEPICK_CLASS,
+ NULL,
+ style,
+ 0,50,300,120,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (!hWndDateTime) {
+ HeapFree(GetProcessHeap(), 0, info);
+ return NULL;
+ }
+
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(hWndDateTime, GWLP_WNDPROC,
+ (LONG_PTR)datetime_subclass_proc);
+ SetWindowLongPtrA(hWndDateTime, GWLP_USERDATA, (LONG_PTR)info);
+
+ return hWndDateTime;
+}
+
+static void test_dtm_set_format(HWND hWndDateTime)
+{
+ LRESULT r;
+
+ r = SendMessage(hWndDateTime, DTM_SETFORMAT, 0, (LPARAM)NULL);
+ expect(1, r);
+
+ r = SendMessage(hWndDateTime, DTM_SETFORMAT, 0,
+ (LPARAM)"'Today is: 'hh':'m':'s dddd MMM dd', 'yyyy");
+ expect(1, r);
+
+ ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_format_seq, "test_dtm_set_format", FALSE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+}
+
+static void test_mccolor_types(HWND hWndDateTime, int mccolor_type, const char* mccolor_name)
+{
+ LRESULT r;
+ COLORREF theColor, prevColor;
+
+ theColor=RGB(0,0,0);
+ r = SendMessage(hWndDateTime, DTM_SETMCCOLOR, mccolor_type, theColor);
+ ok(r != -1, "%s: Set RGB(0,0,0): Expected COLORREF of previous value, got %ld\n", mccolor_name, r);
+ prevColor=theColor;
+ theColor=RGB(255,255,255);
+ r = SendMessage(hWndDateTime, DTM_SETMCCOLOR, mccolor_type, theColor);
+ ok(r==prevColor, "%s: Set RGB(255,255,255): Expected COLORREF of previous value, got %ld\n", mccolor_name, r);
+ prevColor=theColor;
+ theColor=RGB(100,180,220);
+ r = SendMessage(hWndDateTime, DTM_SETMCCOLOR, mccolor_type, theColor);
+ ok(r==prevColor, "%s: Set RGB(100,180,220): Expected COLORREF of previous value, got %ld\n", mccolor_name, r);
+ r = SendMessage(hWndDateTime, DTM_GETMCCOLOR, mccolor_type, 0);
+ ok(r==theColor, "%s: GETMCCOLOR: Expected %d, got %ld\n", mccolor_name, theColor, r);
+}
+
+static void test_dtm_set_and_get_mccolor(HWND hWndDateTime)
+{
+ test_mccolor_types(hWndDateTime, MCSC_BACKGROUND, "MCSC_BACKGROUND");
+ test_mccolor_types(hWndDateTime, MCSC_MONTHBK, "MCSC_MONTHBK");
+ test_mccolor_types(hWndDateTime, MCSC_TEXT, "MCSC_TEXT");
+ test_mccolor_types(hWndDateTime, MCSC_TITLEBK, "MCSC_TITLEBK");
+ test_mccolor_types(hWndDateTime, MCSC_TITLETEXT, "MCSC_TITLETEXT");
+ test_mccolor_types(hWndDateTime, MCSC_TRAILINGTEXT, "MCSC_TRAILINGTEXT");
+
+ ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_mccolor_seq, "test_dtm_set_and_get_mccolor", FALSE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+}
+
+static void test_dtm_set_and_get_mcfont(HWND hWndDateTime)
+{
+ HFONT hFontOrig, hFontNew;
+
+ hFontOrig = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+ SendMessage(hWndDateTime, DTM_SETMCFONT, (WPARAM)hFontOrig, TRUE);
+ hFontNew = (HFONT)SendMessage(hWndDateTime, DTM_GETMCFONT, 0, 0);
+ ok(hFontOrig == hFontNew, "Expected hFontOrig==hFontNew, hFontOrig=%p, hFontNew=%p\n", hFontOrig, hFontNew);
+
+ ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_mcfont_seq, "test_dtm_set_and_get_mcfont", FALSE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+}
+
+static void test_dtm_get_monthcal(HWND hWndDateTime)
+{
+ LRESULT r;
+
+ todo_wine {
+ r = SendMessage(hWndDateTime, DTM_GETMONTHCAL, 0, 0);
+ ok(r == (LPARAM)NULL, "Expected NULL(no child month calendar control), got %ld\n", r);
+ }
+
+ ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_get_monthcal_seq, "test_dtm_get_monthcal", FALSE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+}
+
+static void fill_systime_struct(SYSTEMTIME *st, int year, int month, int dayofweek, int day, int hour, int minute, int second, int milliseconds)
+{
+ st->wYear = year;
+ st->wMonth = month;
+ st->wDayOfWeek = dayofweek;
+ st->wDay = day;
+ st->wHour = hour;
+ st->wMinute = minute;
+ st->wSecond = second;
+ st->wMilliseconds = milliseconds;
+}
+
+static LPARAM compare_systime_date(SYSTEMTIME *st1, SYSTEMTIME *st2)
+{
+ return (st1->wYear == st2->wYear)
+ && (st1->wMonth == st2->wMonth)
+ && (st1->wDayOfWeek == st2->wDayOfWeek)
+ && (st1->wDay == st2->wDay);
+}
+
+static LPARAM compare_systime_time(SYSTEMTIME *st1, SYSTEMTIME *st2)
+{
+ return (st1->wHour == st2->wHour)
+ && (st1->wMinute == st2->wMinute)
+ && (st1->wSecond == st2->wSecond)
+ && (st1->wMilliseconds == st2->wMilliseconds);
+}
+
+static LPARAM compare_systime(SYSTEMTIME *st1, SYSTEMTIME *st2)
+{
+ if(!compare_systime_date(st1, st2))
+ return 0;
+
+ return compare_systime_time(st1, st2);
+}
+
+#define expect_systime(ST1, ST2) ok(compare_systime((ST1), (ST2))==1, "ST1 != ST2\n")
+#define expect_systime_date(ST1, ST2) ok(compare_systime_date((ST1), (ST2))==1, "ST1.date != ST2.date\n")
+#define expect_systime_time(ST1, ST2) ok(compare_systime_time((ST1), (ST2))==1, "ST1.time != ST2.time\n")
+
+static void test_dtm_set_and_get_range(HWND hWndDateTime)
+{
+ LRESULT r;
+ SYSTEMTIME st[2];
+ SYSTEMTIME getSt[2];
+
+ /* initialize st[0] to lowest possible value */
+ fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
+ /* intialize st[1] to all invalid numbers */
+ fill_systime_struct(&st[1], 0, 0, 7, 0, 24, 60, 60, 1000);
+
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN, (LPARAM)st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
+ ok(r == GDTR_MIN, "Expected %x, not %x(GDTR_MAX) or %x(GDTR_MIN | GDTR_MAX), got %lx\n", GDTR_MIN, GDTR_MAX, GDTR_MIN | GDTR_MAX, r);
+ expect_systime(&st[0], &getSt[0]);
+
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MAX, (LPARAM)st);
+ expect_unsuccess(0, r);
+
+ /* set st[0] to all invalid numbers */
+ fill_systime_struct(&st[0], 0, 0, 7, 0, 24, 60, 60, 1000);
+ /* set st[1] to highest possible value */
+ fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
+
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MAX, (LPARAM)st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
+ todo_wine {
+ ok(r == GDTR_MAX, "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MIN | GDTR_MAX), got %lx\n", GDTR_MAX, GDTR_MIN, GDTR_MIN | GDTR_MAX, r);
+ }
+ expect_systime(&st[1], &getSt[1]);
+
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN, (LPARAM)st);
+ expect_unsuccess(0, r);
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
+ expect_unsuccess(0, r);
+
+ /* set st[0] to highest possible value */
+ fill_systime_struct(&st[0], 30827, 12, 6, 31, 23, 59, 59, 999);
+
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
+ ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
+ expect_systime(&st[0], &getSt[0]);
+ expect_systime(&st[1], &getSt[1]);
+
+ /* initialize st[0] to lowest possible value */
+ fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
+ /* set st[1] to highest possible value */
+ fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
+
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
+ ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
+ expect_systime(&st[0], &getSt[0]);
+ expect_systime(&st[1], &getSt[1]);
+
+ /* set st[0] to value higher than minimum */
+ fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
+ /* set st[1] to value lower than maximum */
+ fill_systime_struct(&st[1], 2007, 3, 2, 31, 23, 59, 59, 999);
+
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
+ ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
+ expect_systime(&st[0], &getSt[0]);
+ expect_systime(&st[1], &getSt[1]);
+
+ ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_range_seq, "test_dtm_set_and_get_range", FALSE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+}
+
+/* when max<min for DTM_SETRANGE, Windows seems to swap the min and max values,
+although that's undocumented. However, it doesn't seem to be implemented
+correctly, causing some strange side effects */
+static void test_dtm_set_range_swap_min_max(HWND hWndDateTime)
+{
+ LRESULT r;
+ SYSTEMTIME st[2];
+ SYSTEMTIME getSt[2];
+ SYSTEMTIME origSt;
+
+ fill_systime_struct(&st[0], 2007, 2, 4, 15, 2, 2, 2, 2);
+
+ r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&origSt);
+ ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
+ expect_systime(&st[0], &origSt);
+
+ /* set st[0] to value higher than st[1] */
+ fill_systime_struct(&st[0], 2007, 3, 2, 31, 23, 59, 59, 999);
+ fill_systime_struct(&st[1], 1980, 1, 3, 23, 14, 34, 37, 465);
+
+ /* since min>max, min and max values should be swapped by DTM_SETRANGE
+ automatically */
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
+ ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
+ todo_wine {
+ expect_systime(&st[0], &getSt[0]);
+ }
+ todo_wine {
+ expect_systime(&st[1], &getSt[1]);
+ }
+
+ fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
+
+ r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt[0]);
+ ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
+ /* the time part seems to not change after swapping the min and max values
+ and doing DTM_SETSYSTEMTIME */
+ expect_systime_date(&st[0], &getSt[0]);
+ todo_wine {
+ expect_systime_time(&origSt, &getSt[0]);
+ }
+
+ /* set st[0] to value higher than minimum */
+ fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
+ /* set st[1] to value lower than maximum */
+ fill_systime_struct(&st[1], 2007, 3, 2, 31, 23, 59, 59, 999);
+
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
+ expect(1, r);
+ /* for some reason after we swapped the min and max values before,
+ whenever we do a DTM_SETRANGE, the DTM_GETRANGE will return the values
+ swapped*/
+ r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
+ ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
+ todo_wine {
+ expect_systime(&st[0], &getSt[1]);
+ }
+ todo_wine {
+ expect_systime(&st[1], &getSt[0]);
+ }
+
+ /* set st[0] to value higher than st[1] */
+ fill_systime_struct(&st[0], 2007, 3, 2, 31, 23, 59, 59, 999);
+ fill_systime_struct(&st[1], 1980, 1, 3, 23, 14, 34, 37, 465);
+
+ /* set min>max again, so that the return values of DTM_GETRANGE are no
+ longer swapped the next time we do a DTM SETRANGE and DTM_GETRANGE*/
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
+ ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
+ expect_systime(&st[0], &getSt[1]);
+ expect_systime(&st[1], &getSt[0]);
+
+ /* initialize st[0] to lowest possible value */
+ fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
+ /* set st[1] to highest possible value */
+ fill_systime_struct(&st[1], 30827, 12, 6, 31, 23, 59, 59, 999);
+
+ r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
+ ok(r == (GDTR_MIN | GDTR_MAX), "Expected %x, not %x(GDTR_MIN) or %x(GDTR_MAX), got %lx\n", (GDTR_MIN | GDTR_MAX), GDTR_MIN, GDTR_MAX, r);
+ expect_systime(&st[0], &getSt[0]);
+ expect_systime(&st[1], &getSt[1]);
+
+ ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_range_swap_min_max_seq, "test_dtm_set_range_swap_min_max", FALSE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+}
+
+static void test_dtm_set_and_get_system_time(HWND hWndDateTime)
+{
+ LRESULT r;
+ SYSTEMTIME st;
+ SYSTEMTIME getSt;
+ HWND hWndDateTime_test_gdt_none;
+
+ hWndDateTime_test_gdt_none = create_datetime_control(0, 0);
+
+ ok(hWndDateTime_test_gdt_none!=NULL, "Expected non NULL, got %p\n", hWndDateTime_test_gdt_none);
+ if(hWndDateTime_test_gdt_none) {
+ r = SendMessage(hWndDateTime_test_gdt_none, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
+ expect(0, r);
+ }
+ else {
+ skip("hWndDateTime_test_gdt_none is NULL\n");
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ return;
+ }
+
+ DestroyWindow(hWndDateTime_test_gdt_none);
+
+ r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
+ ok(r == GDT_NONE, "Expected %d, not %d(GDT_VALID) or %d(GDT_ERROR), got %ld\n", GDT_NONE, GDT_VALID, GDT_ERROR, r);
+
+ /* set st to lowest possible value */
+ fill_systime_struct(&st, 1601, 1, 0, 1, 0, 0, 0, 0);
+
+ r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
+ expect(1, r);
+
+ /* set st to highest possible value */
+ fill_systime_struct(&st, 30827, 12, 6, 31, 23, 59, 59, 999);
+
+ r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
+ expect(1, r);
+
+ /* set st to value between min and max */
+ fill_systime_struct(&st, 1980, 1, 3, 23, 14, 34, 37, 465);
+
+ r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
+ expect(1, r);
+ r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
+ ok(r == GDT_VALID, "Expected %d, not %d(GDT_NONE) or %d(GDT_ERROR), got %ld\n", GDT_VALID, GDT_NONE, GDT_ERROR, r);
+ expect_systime(&st, &getSt);
+
+ /* set st to invalid value */
+ fill_systime_struct(&st, 0, 0, 7, 0, 24, 60, 60, 1000);
+
+ r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
+ expect_unsuccess(0, r);
+
+ ok_sequence(sequences, DATETIME_SEQ_INDEX, test_dtm_set_and_get_system_time_seq, "test_dtm_set_and_get_system_time", FALSE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+}
+
+static void test_datetime_control(void)
+{
+ HWND hWndDateTime;
+
+ hWndDateTime = create_datetime_control(DTS_SHOWNONE, 0);
+
+ ok(hWndDateTime != NULL, "Expected non NULL, got %p\n", hWndDateTime);
+ if(hWndDateTime!=NULL) {
+ test_dtm_set_format(hWndDateTime);
+ test_dtm_set_and_get_mccolor(hWndDateTime);
+ test_dtm_set_and_get_mcfont(hWndDateTime);
+ test_dtm_get_monthcal(hWndDateTime);
+ test_dtm_set_and_get_range(hWndDateTime);
+ test_dtm_set_range_swap_min_max(hWndDateTime);
+ test_dtm_set_and_get_system_time(hWndDateTime);
+ }
+ else {
+ skip("hWndDateTime is NULL\n");
+ }
+
+ DestroyWindow(hWndDateTime);
+ ok_sequence(sequences, DATETIME_SEQ_INDEX, destroy_window_seq, "test_dtm_set_and_get_system_time", TRUE);
+}
+
+START_TEST(datetime)
+{
+ INITCOMMONCONTROLSEX icex;
+
+ icex.dwSize = sizeof(icex);
+ icex.dwICC = ICC_DATE_CLASSES;
+ InitCommonControlsEx(&icex);
+ init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ test_datetime_control();
+}
#include <stdarg.h>
-#include "windows.h"
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
#include "commctrl.h"
#include "objidl.h"
static PVOID (WINAPI *pDPA_DeletePtr)(const HDPA,INT);
static BOOL (WINAPI *pDPA_Destroy)(const HDPA);
static VOID (WINAPI *pDPA_DestroyCallback)(HDPA,PFNDPAENUMCALLBACK,PVOID);
-static VOID (WINAPI *pDPA_EnumCallback)(HDPA,PFNDPAENUMCALLBACK,PVOID);
+static VOID (WINAPI *pDPA_EnumCallback)(HDPA,PFNDPAENUMCALLBACK,PVOID);
static INT (WINAPI *pDPA_GetPtr)(const HDPA,INT);
static INT (WINAPI *pDPA_GetPtrIndex)(const HDPA,PVOID);
static BOOL (WINAPI *pDPA_Grow)(HDPA,INT);
#define COMCTL32_GET_PROC(func, ord) \
((p ## func = (PVOID)GetProcAddress(hcomctl32,(LPCSTR)ord)) ? 1 \
- : (trace( #func " not exported\n"), 0))
+ : (trace( #func " not exported\n"), 0))
static BOOL InitFunctionPtrs(HMODULE hcomctl32)
{
{
ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
return p1;
-}
+}
static PVOID CALLBACK CB_MergeDeleteOddSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
{
static INT nEnum;
static INT CALLBACK CB_EnumFirstThree(PVOID pItem, PVOID lp)
-{
+{
INT i;
i = pDPA_GetPtrIndex(lp, pItem);
static HRESULT CALLBACK CB_Save(LPITEMDATA pInfo, IStream *pStm, LPARAM lp)
{
HRESULT hRes;
-
+
ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
hRes = IStream_Write(pStm, &pInfo->iPos, sizeof(INT), NULL);
- ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+ ok(hRes == S_OK, "hRes=0x%x\n", hRes);
hRes = IStream_Write(pStm, &pInfo->pvData, sizeof(PVOID), NULL);
- ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+ ok(hRes == S_OK, "hRes=0x%x\n", hRes);
return S_OK;
}
{
HRESULT hRes;
INT iOldPos;
-
+
iOldPos = pInfo->iPos;
ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
hRes = IStream_Read(pStm, &pInfo->iPos, sizeof(INT), NULL);
- ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+ ok(hRes == S_OK, "hRes=0x%x\n", hRes);
ok(pInfo->iPos == iOldPos, "iPos=%d iOldPos=%d\n", pInfo->iPos, iOldPos);
hRes = IStream_Read(pStm, &pInfo->pvData, sizeof(PVOID), NULL);
- ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+ ok(hRes == S_OK, "hRes=0x%x\n", hRes);
return S_OK;
}
if(!ulItem) break;
dwOut = dwOut << 4 | (ulItem & 0xf);
}
-
+
*pdwOut = dwOut;
if(dwOut != dwIn)
{
pDPA_DeleteAllPtrs(dpa);
-
+
do
{
pDPA_InsertPtr(dpa, 0, (PVOID)(dwIn & 0xf));
dwIn >>= 4;
}
while(dwIn);
-
+
return FALSE;
}
-
+
return TRUE;
}
PVOID p;
DWORD dw, dw2, dw3;
HRESULT hRes;
-
+ BOOL rc;
+
GetSystemInfo(&si);
hHeap = HeapCreate(0, 1, 2);
- ok(hHeap != NULL, "error=%ld\n", GetLastError());
+ ok(hHeap != NULL, "error=%d\n", GetLastError());
dpa3 = pDPA_CreateEx(0, hHeap);
ok(dpa3 != NULL, "\n");
ret = pDPA_Grow(dpa3, si.dwPageSize + 1);
- todo_wine ok(!ret && GetLastError() == ERROR_NOT_ENOUGH_MEMORY,
- "ret=%d error=%ld\n", ret, GetLastError());
-
+ todo_wine ok(!ret && GetLastError() == ERROR_NOT_ENOUGH_MEMORY,
+ "ret=%d error=%d\n", ret, GetLastError());
+
dpa = pDPA_Create(0);
ok(dpa != NULL, "\n");
ok(pDPA_SetPtr(dpa, 1, (PVOID)6), "\n");
/* Fill the greated gap */
ok(pDPA_SetPtr(dpa, 0, (PVOID)5), "\n");
- ok(CheckDPA(dpa, 0x56, &dw), "dw=0x%lx\n", dw);
-
+ rc=CheckDPA(dpa, 0x56, &dw);
+ ok(rc, "dw=0x%x\n", dw);
+
/* Prepend item */
ret = pDPA_InsertPtr(dpa, 1, (PVOID)1);
ok(ret == 1, "ret=%d\n", ret);
/* Append item using out of bound index */
ret = pDPA_InsertPtr(dpa, 5, (PVOID)2);
ok(ret == 4, "ret=%d\n", ret);
- /* Append item using DPA_APPEND */
+ /* Append item using DPA_APPEND */
ret = pDPA_InsertPtr(dpa, DPA_APPEND, (PVOID)4);
ok(ret == 5, "ret=%d\n", ret);
- ok(CheckDPA(dpa, 0x516324, &dw), "dw=0x%lx\n", dw);
+ rc=CheckDPA(dpa, 0x516324, &dw);
+ ok(rc, "dw=0x%x\n", dw);
for(i = 1; i <= 6; i++)
{
/* Sort DPA */
ok(pDPA_Sort(dpa, CB_CmpGT, 0xdeadbeef), "\n");
- ok(CheckDPA(dpa, 0x654321, &dw), "dw=0x%lx\n", dw);
-
+ rc=CheckDPA(dpa, 0x654321, &dw);
+ ok(rc, "dw=0x%x\n", dw);
+
/* Clone into a new DPA */
dpa2 = pDPA_Clone(dpa, NULL);
ok(dpa2 != NULL, "\n");
/* The old data should have been preserved */
- ok(CheckDPA(dpa2, 0x654321, &dw2), "dw=0x%lx\n", dw2);
+ rc=CheckDPA(dpa2, 0x654321, &dw2);
+ ok(rc, "dw=0x%x\n", dw2);
ok(pDPA_Sort(dpa, CB_CmpLT, 0xdeadbeef), "\n");
-
+
/* Test if the DPA itself was really copied */
- ok(CheckDPA(dpa, 0x123456, &dw), "dw=0x%lx\n", dw );
- ok(CheckDPA(dpa2, 0x654321, &dw2), "dw2=0x%lx\n", dw2);
+ rc=CheckDPA(dpa, 0x123456, &dw);
+ ok(rc, "dw=0x%x\n", dw );
+ rc=CheckDPA(dpa2, 0x654321, &dw2);
+ ok(rc, "dw2=0x%x\n", dw2);
/* Clone into an old DPA */
p = NULL; SetLastError(ERROR_SUCCESS);
p = pDPA_Clone(dpa, dpa3);
ok(p == dpa3, "p=%p\n", p);
- ok(CheckDPA(dpa3, 0x123456, &dw3), "dw3=0x%lx\n", dw3);
+ rc=CheckDPA(dpa3, 0x123456, &dw3);
+ ok(rc, "dw3=0x%x\n", dw3);
for(i = 1; i <= 6; i++)
{
j = pDPA_Search(dpa, (PVOID)i, i+1, CB_CmpLT, 0xdeadbeef, DPAS_SORTED);
todo_wine ok(j+1 == i, "j=%d i=%d\n", j, i);
}
-
+
/* Try to get the index of a nonexistent item */
i = pDPA_GetPtrIndex(dpa, (PVOID)7);
ok(i == DPA_ERR, "i=%d\n", i);
-
+
/* Try to delete out of bound indexes */
p = pDPA_DeletePtr(dpa, -1);
ok(p == NULL, "p=%p\n", p);
/* Delete the third item */
p = pDPA_DeletePtr(dpa, 2);
ok(p == (PVOID)3, "p=%p\n", p);
- ok(CheckDPA(dpa, 0x12456, &dw), "dw=0x%lx\n", dw);
+ rc=CheckDPA(dpa, 0x12456, &dw);
+ ok(rc, "dw=0x%x\n", dw);
/* Check where to re-insert the deleted item */
- i = pDPA_Search(dpa, (PVOID)3, 0,
+ i = pDPA_Search(dpa, (PVOID)3, 0,
CB_CmpLT, 0xdeadbeef, DPAS_SORTED|DPAS_INSERTAFTER);
ok(i == 2, "i=%d\n", i);
/* DPAS_INSERTBEFORE works just like DPAS_INSERTAFTER */
/* Re-insert the item */
ret = pDPA_InsertPtr(dpa, 2, (PVOID)3);
ok(ret == 2, "ret=%d i=%d\n", ret, 2);
- ok(CheckDPA(dpa, 0x123456, &dw), "dw=0x%lx\n", dw);
-
+ rc=CheckDPA(dpa, 0x123456, &dw);
+ ok(rc, "dw=0x%x\n", dw);
+
/* When doing a binary search while claiming reverse order all indexes
* should be bogus */
for(i = 0; i < 6; i++)
p = pDPA_DeletePtr(dpa, 1);
p = pDPA_DeletePtr(dpa, 2);
p = pDPA_DeletePtr(dpa, 3);
- ok(CheckDPA(dpa, 0x135, &dw), "dw=0x%lx\n", dw);
-
+ rc=CheckDPA(dpa, 0x135, &dw);
+ ok(rc, "dw=0x%x\n", dw);
+
/* Delete all odd entries from dpa2 */
- pDPA_Merge(dpa2, dpa, DPAM_DELETE,
+ pDPA_Merge(dpa2, dpa, DPAM_DELETE,
CB_CmpLT, CB_MergeDeleteOddSrc, 0xdeadbeef);
- todo_wine ok(CheckDPA(dpa2, 0x246, &dw2), "dw=0x%lx\n", dw2);
-
+ todo_wine
+ {
+ rc=CheckDPA(dpa2, 0x246, &dw2);
+ ok(rc, "dw=0x%x\n", dw2);
+ }
+
/* Merge dpa3 into dpa2 and dpa */
- pDPA_Merge(dpa, dpa3, DPAM_INSERT|DPAM_NOSORT,
+ pDPA_Merge(dpa, dpa3, DPAM_INSERT|DPAM_NOSORT,
CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
- pDPA_Merge(dpa2, dpa3, DPAM_INSERT|DPAM_NOSORT,
+ pDPA_Merge(dpa2, dpa3, DPAM_INSERT|DPAM_NOSORT,
CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
-
- ok(CheckDPA(dpa, 0x123456, &dw ), "dw=0x%lx\n", dw);
- ok(CheckDPA(dpa2, 0x123456, &dw2), "dw2=0x%lx\n", dw2);
- ok(CheckDPA(dpa3, 0x123456, &dw3), "dw3=0x%lx\n", dw3);
+
+ rc=CheckDPA(dpa, 0x123456, &dw);
+ ok(rc, "dw=0x%x\n", dw);
+ rc=CheckDPA(dpa2, 0x123456, &dw2);
+ ok(rc, "dw2=0x%x\n", dw2);
+ rc=CheckDPA(dpa3, 0x123456, &dw3);
+ ok(rc, "dw3=0x%x\n", dw3);
}
if(pDPA_EnumCallback)
{
nEnum = 0;
pDPA_EnumCallback(dpa2, CB_EnumFirstThree, (PVOID)dpa2);
- ok(CheckDPA(dpa2, 0x777456, &dw2), "dw=0x%lx\n", dw2);
+ rc=CheckDPA(dpa2, 0x777456, &dw2);
+ ok(rc, "dw=0x%x\n", dw2);
ok(nEnum == 3, "nEnum=%d\n", nEnum);
}
-
+
/* Setting item with huge index should work */
ok(pDPA_SetPtr(dpa2, 0x12345, (PVOID)0xdeadbeef), "\n");
ret = pDPA_GetPtrIndex(dpa2, (PVOID)0xdeadbeef);
ok(ret == 0x12345, "ret=%d\n", ret);
-
+
pDPA_DeleteAllPtrs(dpa2);
- ok(CheckDPA(dpa2, 0, &dw2), "dw2=0x%lx\n", dw2);
+ rc=CheckDPA(dpa2, 0, &dw2);
+ ok(rc, "dw2=0x%x\n", dw2);
pDPA_Destroy(dpa2);
if(pDPA_DestroyCallback)
dwMode = STGM_DIRECT|STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
- ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+ ok(hRes == S_OK, "hRes=0x%x\n", hRes);
hRes = IStorage_CreateStream(pStg, szStg, dwMode, 0, 0, &pStm);
- ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+ ok(hRes == S_OK, "hRes=0x%x\n", hRes);
hRes = pDPA_SaveStream(dpa, CB_Save, pStm, 0xdeadbeef);
- todo_wine ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+ todo_wine ok(hRes == S_OK, "hRes=0x%x\n", hRes);
pDPA_Destroy(dpa);
-
+
hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
- ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
+ ok(hRes == S_OK, "hRes=0x%x\n", hRes);
hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, 0xdeadbeef);
- todo_wine ok(hRes == S_OK, "hRes=0x%lx\n", hRes);
- todo_wine ok(CheckDPA(dpa, 0x123456, &dw), "dw=0x%lx\n", dw);
- pDPA_Destroy(dpa);
+ todo_wine
+ {
+ ok(hRes == S_OK, "hRes=0x%x\n", hRes);
+ rc=CheckDPA(dpa, 0x123456, &dw);
+ ok(rc, "dw=0x%x\n", dw);
+ }
ret = IStream_Release(pStm);
ok(!ret, "ret=%d\n", ret);
-
+
ret = IStorage_Release(pStg);
ok(!ret, "ret=%d\n", ret);
CoUninitialize();
}
- else ok(0, "hResult: %ld\n", hRes);
+ else ok(0, "hResult: %d\n", hRes);
skip_stream_tests:
pDPA_Destroy(dpa);
hcomctl32 = GetModuleHandleA("comctl32.dll");
- if(!hcomctl32)
- {
- ok(0, "error=%ld\n", GetLastError());
- return;
- }
-
if(InitFunctionPtrs(hcomctl32))
test_dpa();
else
/* Unit test suite for header control.
*
* Copyright 2005 Vijay Kiran Kamuju
+ * Copyright 2007 Shanren Zhou
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <assert.h>
#include "wine/test.h"
+#include "msg.h"
typedef struct tagEXPECTEDNOTIFY
{
HDITEMA hdItem;
} EXPECTEDNOTIFY;
-EXPECTEDNOTIFY expectedNotify[10];
-INT nExpectedNotify = 0;
-INT nReceivedNotify = 0;
-INT unexpectedNotify[10];
-INT nUnexpectedNotify = 0;
+typedef LRESULT (*CUSTOMDRAWPROC)(int n, NMCUSTOMDRAW *nm);
+
+static CUSTOMDRAWPROC g_CustomDrawProc;
+static int g_CustomDrawCount;
+static DRAWITEMSTRUCT g_DrawItem;
+static BOOL g_DrawItemReceived;
+
+static EXPECTEDNOTIFY expectedNotify[10];
+static INT nExpectedNotify = 0;
+static INT nReceivedNotify = 0;
+static INT unexpectedNotify[10];
+static INT nUnexpectedNotify = 0;
static HWND hHeaderParentWnd;
static HWND hWndHeader;
#define MAX_CHARS 100
+#define compare(val, exp, fmt) ok((val) == (exp), #val " value: " fmt ", expected: " fmt "\n", (val), (exp))
+
+#define expect(expected, got) ok(expected == got, "expected %d, got %d\n", expected,got)
+
+#define NUM_MSG_SEQUENCES 2
+#define PARENT_SEQ_INDEX 0
+#define HEADER_SEQ_INDEX 1
+
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+
+static const struct message create_parent_wnd_seq[] = {
+ { WM_GETMINMAXINFO, sent },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { 0 }
+};
+
+static const struct message add_header_to_parent_seq_interactive[] = {
+ { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
+ { WM_QUERYUISTATE, sent },
+ { WM_PARENTNOTIFY, sent|wparam, 1 },
+ { WM_SHOWWINDOW, sent|wparam, 1 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_ACTIVATEAPP, sent|wparam, 1 },
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATE, sent|wparam, 1 },
+ { WM_IME_SETCONTEXT, sent|defwinproc|wparam, 1 },
+ { WM_IME_NOTIFY, sent|defwinproc|wparam, 2 },
+ { WM_SETFOCUS, sent|defwinproc|wparam, 0 },
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
+ { WM_SIZE, sent|wparam, 0 },
+ { WM_MOVE, sent|wparam, 0 },
+ { 0 }
+};
+
+static const struct message add_header_to_parent_seq[] = {
+ { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
+ { WM_QUERYUISTATE, sent },
+ { WM_PARENTNOTIFY, sent },
+ { 0 }
+};
+
+static const struct message insertItem_seq[] = {
+ { HDM_INSERTITEM, sent|wparam, 0 },
+ { HDM_INSERTITEM, sent|wparam, 1 },
+ { HDM_INSERTITEM, sent|wparam, 2 },
+ { HDM_INSERTITEM, sent|wparam, 3 },
+ { 0 }
+};
+
+static const struct message getItem_seq[] = {
+ { HDM_GETITEM, sent|wparam, 3 },
+ { HDM_GETITEM, sent|wparam, 0 },
+ { 0 }
+};
+
+
+static const struct message deleteItem_getItemCount_seq[] = {
+ { HDM_DELETEITEM, sent|wparam, 3 },
+ { HDM_GETITEMCOUNT, sent },
+ { HDM_DELETEITEM, sent|wparam, 3 },
+ { HDM_GETITEMCOUNT, sent },
+ { HDM_DELETEITEM, sent|wparam, 2 },
+ { HDM_GETITEMCOUNT, sent },
+ { 0 }
+};
+
+static const struct message orderArray_seq[] = {
+ { HDM_GETITEMCOUNT, sent },
+ { HDM_SETORDERARRAY, sent|wparam, 2 },
+ { HDM_GETORDERARRAY, sent|wparam, 2 },
+ { 0 }
+};
+
+static const struct message setItem_seq[] = {
+ { HDM_SETITEM, sent|wparam, 0 },
+ { HDM_SETITEM, sent|wparam, 1 },
+ { 0 }
+};
+
+static const struct message getItemRect_seq[] = {
+ { HDM_GETITEMRECT, sent|wparam, 1 },
+ { HDM_GETITEMRECT, sent|wparam, 0 },
+ { HDM_GETITEMRECT, sent|wparam, 10 },
+ { 0 }
+};
+
+static const struct message layout_seq[] = {
+ { HDM_LAYOUT, sent },
+ { 0 }
+};
+
+static const struct message orderToIndex_seq[] = {
+ { HDM_ORDERTOINDEX, sent|wparam, 1 },
+ { 0 }
+};
+
+static const struct message hittest_seq[] = {
+ { HDM_HITTEST, sent },
+ { HDM_HITTEST, sent },
+ { HDM_HITTEST, sent },
+ { 0 }
+};
+
+static const struct message setHotDivider_seq_interactive[] = {
+ { HDM_SETHOTDIVIDER, sent|wparam, TRUE },
+ { WM_PAINT, sent|defwinproc},
+ { WM_NCPAINT, sent|defwinproc},
+ { WM_ERASEBKGND, sent|defwinproc},
+ { HDM_SETHOTDIVIDER, sent|wparam|lparam, FALSE, 100 },
+ { WM_PAINT, sent|defwinproc},
+ { HDM_SETHOTDIVIDER, sent|wparam|lparam, FALSE, 1},
+ { WM_PAINT, sent|defwinproc},
+ { 0 }
+};
+
+static const struct message setHotDivider_seq_noninteractive[] = {
+ { HDM_SETHOTDIVIDER, sent|wparam, TRUE },
+ { HDM_SETHOTDIVIDER, sent|wparam|lparam, FALSE, 100 },
+ { HDM_SETHOTDIVIDER, sent|wparam|lparam, FALSE, 1},
+ { 0 }
+};
+
+static const struct message imageMessages_seq[] = {
+ { HDM_SETIMAGELIST, sent },
+ { HDM_GETIMAGELIST, sent },
+ { HDM_CREATEDRAGIMAGE, sent },
+ { 0 }
+};
+
+static const struct message filterMessages_seq_interactive[] = {
+ { HDM_SETFILTERCHANGETIMEOUT, sent|wparam|lparam, 1, 100 },
+ { HDM_CLEARFILTER, sent|wparam|lparam, 0, 1 },
+ { HDM_EDITFILTER, sent|wparam|lparam, 1, 0 },
+ { WM_PARENTNOTIFY, sent|wparam|defwinproc, WM_CREATE },
+ { WM_CTLCOLOREDIT, sent|defwinproc },
+ { WM_COMMAND, sent|defwinproc },
+ { 0 }
+};
+
+static const struct message filterMessages_seq_noninteractive[] = {
+ { HDM_SETFILTERCHANGETIMEOUT, sent|wparam|lparam, 1, 100 },
+ { HDM_CLEARFILTER, sent|wparam|lparam, 0, 1 },
+ { HDM_EDITFILTER, sent|wparam|lparam, 1, 0 },
+ { WM_PARENTNOTIFY, sent|wparam|defwinproc, WM_CREATE },
+ { WM_COMMAND, sent|defwinproc },
+ { 0 }
+};
+
+static const struct message unicodeformatMessages_seq[] = {
+ { HDM_SETUNICODEFORMAT, sent|wparam, TRUE },
+ { HDM_GETUNICODEFORMAT, sent },
+ { 0 }
+};
+
+static const struct message bitmapmarginMessages_seq[] = {
+ { HDM_GETBITMAPMARGIN, sent },
+ { 0 }
+};
+
+
static void expect_notify(INT iCode, BOOL fUnicode, HDITEMA *lpItem)
{
assert(nExpectedNotify < 10);
return fRet;
}
-static LONG addItem(HWND hdex, int idx, LPCSTR text)
+static LONG addItem(HWND hdex, int idx, LPSTR text)
{
HDITEMA hdItem;
hdItem.mask = HDI_TEXT | HDI_WIDTH;
hdItem.cxy = 100;
- hdItem.pszText = (LPSTR)text;
+ hdItem.pszText = text;
hdItem.cchTextMax = 0;
return (LONG)SendMessage(hdex, HDM_INSERTITEMA, (WPARAM)idx, (LPARAM)&hdItem);
}
-static LONG setItem(HWND hdex, int idx, LPCSTR text, BOOL fCheckNotifies)
+static LONG setItem(HWND hdex, int idx, LPSTR text, BOOL fCheckNotifies)
{
LONG ret;
HDITEMA hdexItem;
hdexItem.mask = HDI_TEXT;
- hdexItem.pszText = (LPSTR)text;
+ hdexItem.pszText = text;
hdexItem.cchTextMax = 0;
if (fCheckNotifies)
{
return ret;
}
-static LONG setItemUnicodeNotify(HWND hdex, int idx, LPCSTR text, LPCWSTR wText)
+static LONG setItemUnicodeNotify(HWND hdex, int idx, LPSTR text, LPWSTR wText)
{
LONG ret;
HDITEMA hdexItem;
HDITEMW hdexNotify;
hdexItem.mask = HDI_TEXT;
- hdexItem.pszText = (LPSTR)text;
+ hdexItem.pszText = text;
hdexItem.cchTextMax = 0;
-
+
hdexNotify.mask = HDI_TEXT;
- hdexNotify.pszText = (LPWSTR)wText;
-
+ hdexNotify.pszText = wText;
+
expect_notify(HDN_ITEMCHANGINGW, TRUE, (HDITEMA*)&hdexNotify);
expect_notify(HDN_ITEMCHANGEDW, TRUE, (HDITEMA*)&hdexNotify);
ret = (LONG)SendMessage(hdex, HDM_SETITEMA, (WPARAM)idx, (LPARAM)&hdexItem);
ZeroMemory(phdiRead, sizeof(HDITEMA));
phdiRead->mask = maskRead;
ok(SendMessage(hdex, HDM_GETITEMA, (WPARAM)0, (LPARAM)phdiRead)!=0, "Getting item data failed\n");
- ok(SendMessage(hdex, HDM_DELETEITEM, (WPARAM)0, (LPARAM)0)!=0, "Deleteing item failed\n");
+ ok(SendMessage(hdex, HDM_DELETEITEM, (WPARAM)0, (LPARAM)0)!=0, "Deleting item failed\n");
}
static HWND create_header_control (void)
hlayout.prc = &rectwin;
hlayout.pwpos = &winpos;
SendMessageA(handle,HDM_LAYOUT,0,(LPARAM) &hlayout);
- SetWindowPos(handle, winpos.hwndInsertAfter, winpos.x, winpos.y,
+ SetWindowPos(handle, winpos.hwndInsertAfter, winpos.x, winpos.y,
winpos.cx, winpos.cy, 0);
return handle;
}
}
-static const char *str_items[] =
- {"First Item", "Second Item", "Third Item", "Fourth Item", "Replace Item", "Out Of Range Item"};
+static char pszFirstItem[] = "First Item";
+static char pszSecondItem[] = "Second Item";
+static char pszThirdItem[] = "Third Item";
+static char pszFourthItem[] = "Fourth Item";
+static char pszReplaceItem[] = "Replace Item";
+static char pszOutOfRangeItem[] = "Out Of Range Item";
-static const char pszUniTestA[] = "TST";
-static const WCHAR pszUniTestW[] = {'T','S','T',0};
+static char *str_items[] =
+ {pszFirstItem, pszSecondItem, pszThirdItem, pszFourthItem, pszReplaceItem, pszOutOfRangeItem};
+
+static char pszUniTestA[] = "TST";
+static WCHAR pszUniTestW[] = {'T','S','T',0};
#define TEST_GET_ITEM(i,c)\
{ res = getItem(hWndHeader, i, buffer);\
- ok(res != 0, "Getting item[%d] using valid index failed unexpectedly (%ld)\n", i, res);\
+ ok(res != 0, "Getting item[%d] using valid index failed unexpectedly (%d)\n", i, res);\
ok(strcmp(str_items[c], buffer) == 0, "Getting item[%d] returned \"%s\" expecting \"%s\"\n", i, buffer, str_items[c]);\
}
#define TEST_GET_ITEMCOUNT(i)\
{ res = getItemCount(hWndHeader);\
- ok(res == i, "Got Item Count as %ld\n", res);\
+ ok(res == i, "Got Item Count as %d\n", res);\
+}
+
+struct subclass_info
+{
+ WNDPROC oldproc;
+};
+
+static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, HEADER_SEQ_INDEX, &msg);
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ /* do not log painting messages */
+ if (message != WM_PAINT &&
+ message != WM_ERASEBKGND &&
+ message != WM_NCPAINT &&
+ message != WM_NCHITTEST &&
+ message != WM_GETTEXT &&
+ message != WM_GETICON &&
+ message != WM_DEVICECHANGE)
+
+ {
+ trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, PARENT_SEQ_INDEX, &msg);
+ }
+
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static BOOL register_parent_wnd_class(void)
+{
+ WNDCLASSA cls;
+
+ cls.style = 0;
+ cls.lpfnWndProc = parent_wnd_proc;
+ cls.cbClsExtra = 0;
+ cls.cbWndExtra = 0;
+ cls.hInstance = GetModuleHandleA(NULL);
+ cls.hIcon = 0;
+ cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
+ cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+ cls.lpszMenuName = NULL;
+ cls.lpszClassName = "Header test parent class";
+ return RegisterClassA(&cls);
+}
+
+static HWND create_custom_parent_window(void)
+{
+ if (!register_parent_wnd_class())
+ return NULL;
+
+ return CreateWindowExA(0, "Header test parent class", "Header Message Sequence Testing",
+ WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
+ 672+2*GetSystemMetrics(SM_CXSIZEFRAME),
+ 226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
+ NULL, NULL, GetModuleHandleA(NULL), 0);
+}
+
+static HWND create_custom_header_control(HWND hParent, BOOL preloadHeaderItems)
+{
+ struct subclass_info *info;
+ HWND childHandle;
+ HDLAYOUT hlayout;
+ RECT rectwin;
+ WINDOWPOS winpos;
+ int retVal;
+ int loopcnt;
+ static char firstHeaderItem[] = "Name";
+ static char secondHeaderItem[] = "Size";
+ static char *items[] = {secondHeaderItem, firstHeaderItem};
+ HDITEM hdItem;
+ hdItem.mask = HDI_TEXT | HDI_WIDTH | HDI_FORMAT;
+ hdItem.fmt = HDF_LEFT;
+ hdItem.cxy = 80;
+ hdItem.cchTextMax = 260;
+
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ childHandle = CreateWindowEx(0, WC_HEADER, NULL,
+ WS_CHILD|WS_BORDER|WS_VISIBLE|HDS_BUTTONS|HDS_HORZ,
+ 0, 0, 0, 0,
+ hParent, NULL, NULL, NULL);
+ assert(childHandle);
+ if (preloadHeaderItems)
+ {
+ for ( loopcnt = 0 ; loopcnt < 2 ; loopcnt++ )
+ {
+ hdItem.pszText = items[loopcnt];
+ retVal = SendMessage(childHandle, HDM_INSERTITEM, loopcnt, (LPARAM) &hdItem);
+ ok(retVal == loopcnt, "Adding item %d failed with return value %d\n", ( loopcnt + 1 ), retVal);
+ }
+ }
+
+ if (winetest_interactive)
+ ShowWindow (hParent, SW_SHOW);
+
+ GetClientRect(hParent,&rectwin);
+ hlayout.prc = &rectwin;
+ hlayout.pwpos = &winpos;
+ SendMessageA(childHandle,HDM_LAYOUT,0,(LPARAM) &hlayout);
+ SetWindowPos(childHandle, winpos.hwndInsertAfter, winpos.x, winpos.y,
+ winpos.cx, winpos.cy, 0);
+
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(childHandle, GWLP_WNDPROC,
+ (LONG_PTR)header_subclass_proc);
+ SetWindowLongPtrA(childHandle, GWLP_USERDATA, (LONG_PTR)info);
+ return childHandle;
}
static void check_auto_format(void)
HDITEMA hdiCreate;
HDITEMA hdiRead;
static CHAR text[] = "Test";
- LRESULT res;
+ LONG res;
/* Windows stores the format, width, lparam even if they are not in the item's mask */
ZeroMemory(&hdiCreate, sizeof(HDITEMA));
{
TEST_GET_ITEMCOUNT(3-i);
res = addItem(hWndHeader, 0, str_items[i]);
- ok(res == 0, "Adding simple item failed (%ld)\n", res);
+ ok(res == 0, "Adding simple item failed (%d)\n", res);
}
TEST_GET_ITEMCOUNT(4);
res = addItem(hWndHeader, 99, str_items[i+1]);
- ok(res != -1, "Adding Out of Range item should fail with -1 got (%ld)\n", res);
+ ok(res != -1, "Adding Out of Range item should fail with -1 got (%d)\n", res);
TEST_GET_ITEMCOUNT(5);
res = addItem(hWndHeader, 5, str_items[i+1]);
- ok(res != -1, "Adding Out of Range item should fail with -1 got (%ld)\n", res);
+ ok(res != -1, "Adding Out of Range item should fail with -1 got (%d)\n", res);
TEST_GET_ITEMCOUNT(6);
for (i = 0; i < 4; i++) { TEST_GET_ITEM(i,i); TEST_GET_ITEMCOUNT(6); }
res=getItem(hWndHeader, 99, buffer);
- ok(res == 0, "Getting Out of Range item should fail with 0 (%ld), got %s\n", res,buffer);
+ ok(res == 0, "Getting Out of Range item should fail with 0 (%d), got %s\n", res,buffer);
res=getItem(hWndHeader, 5, buffer);
- ok(res == 1, "Getting Out of Range item should fail with 1 (%ld), got %s\n", res,buffer);
+ ok(res == 1, "Getting Out of Range item should fail with 1 (%d), got %s\n", res,buffer);
res=getItem(hWndHeader, -2, buffer);
- ok(res == 0, "Getting Out of Range item should fail with 0 (%ld), got %s\n", res,buffer);
+ ok(res == 0, "Getting Out of Range item should fail with 0 (%d), got %s\n", res,buffer);
if (winetest_interactive)
{
TEST_GET_ITEMCOUNT(6);
res=setItem(hWndHeader, 99, str_items[5], FALSE);
- ok(res == 0, "Setting Out of Range item should fail with 0 (%ld)\n", res);
+ ok(res == 0, "Setting Out of Range item should fail with 0 (%d)\n", res);
res=setItem(hWndHeader, 5, str_items[5], TRUE);
- ok(res == 1, "Setting Out of Range item should fail with 1 (%ld)\n", res);
+ ok(res == 1, "Setting Out of Range item should fail with 1 (%d)\n", res);
res=setItem(hWndHeader, -2, str_items[5], FALSE);
- ok(res == 0, "Setting Out of Range item should fail with 0 (%ld)\n", res);
+ ok(res == 0, "Setting Out of Range item should fail with 0 (%d)\n", res);
TEST_GET_ITEMCOUNT(6);
for (i = 0; i < 4; i++)
{
res = setItem(hWndHeader, i, str_items[4], TRUE);
- ok(res != 0, "Setting %d item failed (%ld)\n", i+1, res);
+ ok(res != 0, "Setting %d item failed (%d)\n", i+1, res);
TEST_GET_ITEM(i, 4);
TEST_GET_ITEMCOUNT(6);
}
-
+
SendMessageA(hWndHeader, HDM_SETUNICODEFORMAT, (WPARAM)TRUE, 0);
setItemUnicodeNotify(hWndHeader, 3, pszUniTestA, pszUniTestW);
SendMessageA(hWndHeader, WM_NOTIFYFORMAT, (WPARAM)hHeaderParentWnd, (LPARAM)NF_REQUERY);
setItem(hWndHeader, 3, str_items[4], TRUE);
-
+
dont_expect_notify(HDN_GETDISPINFOA);
dont_expect_notify(HDN_GETDISPINFOW);
addItem(hWndHeader, 0, LPSTR_TEXTCALLBACKA);
TEST_GET_ITEMCOUNT(6);
res = delItem(hWndHeader, 5);
- ok(res == 1, "Deleting Out of Range item should fail with 1 (%ld)\n", res);
+ ok(res == 1, "Deleting Out of Range item should fail with 1 (%d)\n", res);
res = delItem(hWndHeader, -2);
- ok(res == 0, "Deleting Out of Range item should fail with 0 (%ld)\n", res);
+ ok(res == 0, "Deleting Out of Range item should fail with 0 (%d)\n", res);
TEST_GET_ITEMCOUNT(5);
res = delItem(hWndHeader, 3);
- ok(res != 0, "Deleting using out of range index failed (%ld)\n", res);
+ ok(res != 0, "Deleting using out of range index failed (%d)\n", res);
TEST_GET_ITEMCOUNT(4);
res = delItem(hWndHeader, 0);
- ok(res != 0, "Deleting using out of range index failed (%ld)\n", res);
+ ok(res != 0, "Deleting using out of range index failed (%d)\n", res);
TEST_GET_ITEMCOUNT(3);
res = delItem(hWndHeader, 0);
- ok(res != 0, "Deleting using out of range index failed (%ld)\n", res);
+ ok(res != 0, "Deleting using out of range index failed (%d)\n", res);
TEST_GET_ITEMCOUNT(2);
res = delItem(hWndHeader, 0);
- ok(res != 0, "Deleting using out of range index failed (%ld)\n", res);
+ ok(res != 0, "Deleting using out of range index failed (%d)\n", res);
TEST_GET_ITEMCOUNT(1);
DestroyWindow(hWndHeader);
}
+static void test_hdm_getitemrect(HWND hParent)
+{
+
+ HWND hChild;
+ RECT rect;
+ int retVal;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+
+ retVal = SendMessage(hChild, HDM_GETITEMRECT, 1, (LPARAM) &rect);
+ ok(retVal == TRUE, "Getting item rect should TRUE, got %d\n", retVal);
+ /* check bounding rectangle information of 2nd header item */
+ expect(80, rect.left);
+ expect(0, rect.top);
+ expect(160, rect.right);
+ todo_wine
+ {
+ expect(18, rect.bottom);
+ }
+ retVal = SendMessage(hChild, HDM_GETITEMRECT, 0, (LPARAM) &rect);
+
+ ok(retVal == TRUE, "Getting item rect should TRUE, got %d\n", retVal);
+ /* check bounding rectangle information of 1st header item */
+ expect(0, rect.left);
+ expect(0, rect.top);
+
+ expect(80, rect.right);
+ todo_wine
+ {
+ expect(18, rect.bottom);
+ }
+ retVal = SendMessage(hChild, HDM_GETITEMRECT, 10, (LPARAM) &rect);
+ ok(retVal == 0, "Getting rect of nonexistent item should return 0, got %d\n", retVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, getItemRect_seq, "getItemRect sequence testing", FALSE);
+ DestroyWindow(hChild);
+}
+
+static void test_hdm_layout(HWND hParent)
+{
+ HWND hChild;
+ int retVal;
+ RECT rect;
+ HDLAYOUT hdLayout;
+ WINDOWPOS windowPos;
+ hdLayout.prc = ▭
+ hdLayout.pwpos = &windowPos;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ retVal = SendMessage(hChild, HDM_LAYOUT, 0, (LPARAM) &hdLayout);
+ expect(TRUE, retVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, layout_seq, "layout sequence testing", FALSE);
+
+ DestroyWindow(hChild);
+}
-LRESULT CALLBACK HeaderTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+static void test_hdm_ordertoindex(HWND hParent)
{
+ HWND hChild;
+ int retVal;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ retVal = SendMessage(hChild, HDM_ORDERTOINDEX, 1, 0);
+ expect(1, retVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, orderToIndex_seq, "orderToIndex sequence testing", FALSE);
+ DestroyWindow(hChild);
+}
+
+static void test_hdm_hittest(HWND hParent)
+{
+ HWND hChild;
+ int retVal;
+ POINT pt;
+ HDHITTESTINFO hdHitTestInfo;
+ const int firstItemRightBoundary = 80;
+ const int secondItemRightBoundary = 160;
+ const int bottomBoundary = 18;
+
+ pt.x = firstItemRightBoundary - 1;
+ pt.y = bottomBoundary - 1;
+ hdHitTestInfo.pt = pt;
+
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ retVal = SendMessage(hChild, HDM_HITTEST, 0, (LPARAM) &hdHitTestInfo);
+ todo_wine
+ {
+ expect(0, retVal);
+ expect(0, hdHitTestInfo.iItem);
+ }
+
+ pt.x = secondItemRightBoundary - 1;
+ pt.y = bottomBoundary - 1;
+ hdHitTestInfo.pt = pt;
+ retVal = SendMessage(hChild, HDM_HITTEST, 1, (LPARAM) &hdHitTestInfo);
+ todo_wine
+ {
+ expect(1, retVal);
+ }
+ expect(1, hdHitTestInfo.iItem);
+
+ pt.x = secondItemRightBoundary;
+ pt.y = bottomBoundary + 1;
+ hdHitTestInfo.pt = pt;
+ todo_wine
+ {
+ retVal = SendMessage(hChild, HDM_HITTEST, 0, (LPARAM) &hdHitTestInfo);
+ expect(-1, retVal);
+ }
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, hittest_seq, "hittest sequence testing", FALSE);
+
+ DestroyWindow(hChild);
+}
+
+static void test_hdm_sethotdivider(HWND hParent)
+{
+ HWND hChild;
+ int retVal;
+ /* low word: x coordinate = 5
+ * high word: y coordinate = 5
+ */
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ todo_wine
+ {
+ retVal = SendMessage(hChild, HDM_SETHOTDIVIDER, TRUE, (LPARAM) 0X00050005);
+ expect(0, retVal);
+ }
+ retVal = SendMessage(hChild, HDM_SETHOTDIVIDER, FALSE, 100);
+ expect(100, retVal);
+ retVal = SendMessage(hChild, HDM_SETHOTDIVIDER, FALSE, 1);
+ expect(1, retVal);
+ if (winetest_interactive)
+ ok_sequence(sequences, HEADER_SEQ_INDEX, setHotDivider_seq_interactive,
+ "setHotDivider sequence testing", TRUE);
+ else
+ ok_sequence(sequences, HEADER_SEQ_INDEX, setHotDivider_seq_noninteractive,
+ "setHotDivider sequence testing", FALSE);
+
+ DestroyWindow(hChild);
+}
+
+static void test_hdm_imageMessages(HWND hParent)
+{
+ HIMAGELIST hImageList = ImageList_Create (4, 4, 0, 1, 0);
+ HIMAGELIST hImageListRetVal;
+ HWND hChild;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ hImageListRetVal = (HIMAGELIST) SendMessage(hChild, HDM_SETIMAGELIST, 0, (LPARAM) hImageList);
+ ok(hImageListRetVal == NULL, "Expected NULL, got %d\n", (int) hImageListRetVal);
+
+ hImageListRetVal = (HIMAGELIST) SendMessage(hChild, HDM_GETIMAGELIST, 0, 0);
+ ok(hImageListRetVal != NULL, "Expected non-NULL handle, got %d\n", (int) hImageListRetVal);
+
+ hImageListRetVal = (HIMAGELIST) SendMessage(hChild, HDM_CREATEDRAGIMAGE, 0, 0);
+ ok(hImageListRetVal != NULL, "Expected non-NULL handle, got %d\n", (int) hImageListRetVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, imageMessages_seq, "imageMessages sequence testing", FALSE);
+
+ DestroyWindow(hChild);
+}
+
+static void test_hdm_filterMessages(HWND hParent)
+{
+ HWND hChild;
+ int retVal;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, TRUE);
+ assert(hChild);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ todo_wine
+ {
+ /* msdn incorrecly states that return value
+ * is the index of the filter control being
+ * modified. The sendMessage here should
+ * return previous filter timeout value
+ */
+ retVal = SendMessage(hChild, HDM_SETFILTERCHANGETIMEOUT, 1, 100);
+ expect(1000, retVal);
+ retVal = SendMessage(hChild, HDM_CLEARFILTER, 0, 1);
+ expect(1, retVal);
+ retVal = SendMessage(hChild, HDM_EDITFILTER, 1, 0);
+ expect(1, retVal);
+ }
+ if (winetest_interactive)
+ ok_sequence(sequences, HEADER_SEQ_INDEX, filterMessages_seq_interactive,
+ "filterMessages sequence testing", TRUE);
+ else
+ ok_sequence(sequences, HEADER_SEQ_INDEX, filterMessages_seq_noninteractive,
+ "filterMessages sequence testing", TRUE);
+ DestroyWindow(hChild);
+
+}
+
+static void test_hdm_unicodeformatMessages(HWND hParent)
+{
+ HWND hChild;
+ int retVal;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ retVal = SendMessage(hChild, HDM_SETUNICODEFORMAT, TRUE, 0);
+ expect(0, retVal);
+ retVal = SendMessage(hChild, HDM_GETUNICODEFORMAT, 0, 0);
+ expect(1, retVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, unicodeformatMessages_seq,
+ "unicodeformatMessages sequence testing", FALSE);
+ DestroyWindow(hChild);
+}
+
+static void test_hdm_bitmapmarginMessages(HWND hParent)
+{
+ HWND hChild;
+ int retVal;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ retVal = SendMessage(hChild, HDM_GETBITMAPMARGIN, 0, 0);
+ expect(6, retVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, bitmapmarginMessages_seq,
+ "bitmapmarginMessages sequence testing", FALSE);
+ DestroyWindow(hChild);
+}
+
+static void test_hdm_index_messages(HWND hParent)
+{
+
+ HWND hChild;
+ int retVal;
+ int loopcnt;
+ int strcmpResult;
+ int iSize;
+ static const int lpiarray[2] = {1, 0};
+ static int lpiarrayReceived[2];
+ static char firstHeaderItem[] = "Name";
+ static char secondHeaderItem[] = "Size";
+ static char thirdHeaderItem[] = "Type";
+ static char fourthHeaderItem[] = "Date Modified";
+ static char *items[] = {firstHeaderItem, secondHeaderItem, thirdHeaderItem, fourthHeaderItem};
+ HDITEM hdItem;
+ hdItem.mask = HDI_TEXT | HDI_WIDTH | HDI_FORMAT;
+ hdItem.fmt = HDF_LEFT;
+ hdItem.cxy = 80;
+ hdItem.cchTextMax = 260;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hChild = create_custom_header_control(hParent, FALSE);
+ if (winetest_interactive)
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq_interactive,
+ "adder header control to parent", TRUE);
+ else
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_header_to_parent_seq,
+ "adder header control to parent", TRUE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ for ( loopcnt = 0 ; loopcnt < 4 ; loopcnt++ )
+ {
+ hdItem.pszText = items[loopcnt];
+ retVal = SendMessage(hChild, HDM_INSERTITEM, loopcnt, (LPARAM) &hdItem);
+ ok(retVal == loopcnt, "Adding item %d failed with return value %d\n", ( loopcnt + 1 ), retVal);
+ }
+ ok_sequence(sequences, HEADER_SEQ_INDEX, insertItem_seq, "insertItem sequence testing", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ retVal = SendMessage(hChild, HDM_DELETEITEM, 3, (LPARAM) &hdItem);
+ ok(retVal == TRUE, "Deleting item 3 should return TRUE, got %d\n", retVal);
+ retVal = SendMessage(hChild, HDM_GETITEMCOUNT, 0, (LPARAM) &hdItem);
+ ok(retVal == 3, "Getting item count should return 3, got %d\n", retVal);
+
+ retVal = SendMessage(hChild, HDM_DELETEITEM, 3, (LPARAM) &hdItem);
+ ok(retVal == FALSE, "Deleting already-deleted item should return FALSE, got %d\n", retVal);
+ retVal = SendMessage(hChild, HDM_GETITEMCOUNT, 0, (LPARAM) &hdItem);
+ ok(retVal == 3, "Getting item count should return 3, got %d\n", retVal);
+
+ retVal = SendMessage(hChild, HDM_DELETEITEM, 2, (LPARAM) &hdItem);
+ ok(retVal == TRUE, "Deleting item 2 should return TRUE, got %d\n", retVal);
+ retVal = SendMessage(hChild, HDM_GETITEMCOUNT, 0, (LPARAM) &hdItem);
+ ok(retVal == 2, "Getting item count should return 2, got %d\n", retVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, deleteItem_getItemCount_seq,
+ "deleteItem_getItemCount sequence testing", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ retVal = SendMessage(hChild, HDM_GETITEM, 3, (LPARAM) &hdItem);
+ ok(retVal == FALSE, "Getting already-deleted item should return FALSE, got %d\n", retVal);
+
+ retVal = SendMessage(hChild, HDM_GETITEM, 0, (LPARAM) &hdItem);
+ ok(retVal == TRUE, "Getting the 1st header item should return TRUE, got %d\n", retVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, getItem_seq, "getItem sequence testing", FALSE);
+
+ /* check if the item is the right one */
+ strcmpResult = strcmp(hdItem.pszText, firstHeaderItem);
+ expect(0, strcmpResult);
+ expect(80, hdItem.cxy);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ iSize = SendMessage(hChild, HDM_GETITEMCOUNT, 0, (LPARAM) &hdItem);
+ retVal = SendMessage(hChild, HDM_SETORDERARRAY, (WPARAM) iSize , (LPARAM) (LPINT) lpiarray );
+ ok(retVal == TRUE, "Setting header items order should return TRUE, got %d\n", retVal);
+
+ retVal = SendMessage(hChild, HDM_GETORDERARRAY, (WPARAM) iSize, (LPARAM) (LPINT) lpiarrayReceived );
+ ok(retVal == TRUE, "Getting header items order should return TRUE, got %d\n", retVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, orderArray_seq, "set_get_orderArray sequence testing", FALSE);
+
+ /* check if the array order is set correctly and the size of the array is corret. */
+ expect(2, iSize);
+ expect(lpiarray[0], lpiarrayReceived[0]);
+ expect(lpiarray[1], lpiarrayReceived[1]);
+
+ hdItem.mask = HDI_FORMAT;
+ hdItem.fmt = HDF_CENTER | HDF_STRING;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ retVal = SendMessage(hChild, HDM_SETITEM, 0, (LPARAM) &hdItem);
+ ok(retVal == TRUE, "Aligning 1st header item to center should return TRUE, got %d\n", retVal);
+ hdItem.fmt = HDF_RIGHT | HDF_STRING;
+ retVal = SendMessage(hChild, HDM_SETITEM, 1, (LPARAM) &hdItem);
+ ok(retVal == TRUE, "Aligning 2nd header item to right should return TRUE, got %d\n", retVal);
+
+ ok_sequence(sequences, HEADER_SEQ_INDEX, setItem_seq, "setItem sequence testing", FALSE);
+ DestroyWindow(hChild);
+}
+
+#define TEST_NMCUSTOMDRAW(draw_stage, item_spec, lparam, _left, _top, _right, _bottom) \
+ ok(nm->dwDrawStage == draw_stage, "Invalid dwDrawStage %d vs %d\n", draw_stage, nm->dwDrawStage); \
+ if (item_spec != -1) \
+ ok(nm->dwItemSpec == item_spec, "Invalid dwItemSpec %d vs %ld\n", item_spec, nm->dwItemSpec); \
+ ok(nm->lItemlParam == lparam, "Invalid lItemlParam %d vs %ld\n", lparam, nm->lItemlParam); \
+ ok(nm->rc.top == _top && nm->rc.bottom == _bottom && nm->rc.left == _left && nm->rc.right == _right, \
+ "Invalid rect (%d,%d) (%d,%d) vs (%d,%d) (%d,%d)\n", _left, _top, _right, _bottom, \
+ nm->rc.left, nm->rc.top, nm->rc.right, nm->rc.bottom);
+
+static LRESULT customdraw_1(int n, NMCUSTOMDRAW *nm)
+{
+ if (nm == NULL) { /* test ended */
+ ok(n==1, "NM_CUSTOMDRAW messages: %d, expected: 1\n", n);
+ return 0;
+ }
+
+ switch (n)
+ {
+ case 0:
+ /* don't test dwItemSpec - it's 0 no comctl5 but 1308756 on comctl6 */
+ TEST_NMCUSTOMDRAW(CDDS_PREPAINT, -1, 0, 0, 0, 670, 18);
+ return 0;
+ }
+
+ ok(FALSE, "To many custom draw messages (n=%d, nm->dwDrawStage=%d)\n", n, nm->dwDrawStage);
+ return -1;
+}
+
+static LRESULT customdraw_2(int n, NMCUSTOMDRAW *nm)
+{
+ if (nm == NULL) { /* test ended */
+ ok(n==4, "NM_CUSTOMDRAW messages: %d, expected: 4\n", n);
+ return 0;
+ }
+
+ switch (n)
+ {
+ case 0:
+ TEST_NMCUSTOMDRAW(CDDS_PREPAINT, -1, 0, 0, 0, 670, 18);
+ return CDRF_NOTIFYITEMDRAW;
+ case 1:
+ TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT, 0, 0, 0, 0, 50, 18);
+ return 0;
+ case 2:
+ TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT, 1, 5, 50, 0, 150, 18);
+ return 0;
+ case 3:
+ TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT, 2, 10, 150, 0, 300, 18);
+ return 0;
+ }
+
+ ok(FALSE, "To many custom draw messages (n=%d, nm->dwDrawStage=%d)\n", n, nm->dwDrawStage);
+ return 0;
+}
+
+static LRESULT customdraw_3(int n, NMCUSTOMDRAW *nm)
+{
+ if (nm == NULL) { /* test ended */
+ ok(n==5, "NM_CUSTOMDRAW messages: %d, expected: 5\n", n);
+ return 0;
+ }
+
+ switch (n)
+ {
+ case 0:
+ TEST_NMCUSTOMDRAW(CDDS_PREPAINT, -1, 0, 0, 0, 670, 18);
+ return CDRF_NOTIFYITEMDRAW|CDRF_NOTIFYPOSTERASE|CDRF_NOTIFYPOSTPAINT|CDRF_SKIPDEFAULT;
+ case 1:
+ TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT, 0, 0, 0, 0, 50, 18);
+ return 0;
+ case 2:
+ TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT, 1, 5, 50, 0, 150, 18);
+ return 0;
+ case 3:
+ TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT, 2, 10, 150, 0, 300, 18);
+ return 0;
+ case 4:
+ TEST_NMCUSTOMDRAW(CDDS_POSTPAINT, -1, 0, 0, 0, 670, 18);
+ return 0;
+ }
+
+ ok(FALSE, "To many custom draw messages (n=%d, nm->dwDrawStage=%d)\n", n, nm->dwDrawStage);
+ return 0;
+}
+
+
+static LRESULT customdraw_4(int n, NMCUSTOMDRAW *nm)
+{
+ if (nm == NULL) { /* test ended */
+ ok(n==4, "NM_CUSTOMDRAW messages: %d, expected: 4\n", n);
+ return 0;
+ }
+
+ switch (n)
+ {
+ case 0:
+ TEST_NMCUSTOMDRAW(CDDS_PREPAINT, -1, 0, 0, 0, 670, 18);
+ return CDRF_NOTIFYITEMDRAW|CDRF_NOTIFYPOSTPAINT;
+ case 1:
+ TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT, 0, 0, 0, 0, 50, 18);
+ return 0;
+ case 2:
+ TEST_NMCUSTOMDRAW(CDDS_ITEMPREPAINT, 2, 10, 150, 0, 300, 18);
+ return 0;
+ case 3:
+ TEST_NMCUSTOMDRAW(CDDS_POSTPAINT, -1, 0, 0, 0, 670, 18);
+ return 0;
+ }
+
+ ok(FALSE, "To many custom draw messages (n=%d, nm->dwDrawStage=%d)\n", n, nm->dwDrawStage);
+ return 0;
+}
+
+static void run_customdraw_scenario(CUSTOMDRAWPROC proc)
+{
+ g_CustomDrawProc = proc;
+ g_CustomDrawCount = 0;
+ InvalidateRect(hWndHeader, NULL, TRUE);
+ UpdateWindow(hWndHeader);
+ proc(g_CustomDrawCount, NULL);
+ g_CustomDrawProc = NULL;
+}
+
+static void test_customdraw(void)
+{
+ int i;
+ HDITEM item;
+ RECT rect;
+ CHAR name[] = "Test";
+ hWndHeader = create_header_control();
+ GetClientRect(hWndHeader, &rect);
+ ok(rect.right - rect.left == 670 && rect.bottom - rect.top == 18,
+ "Tests will fail as header size is %dx%d instead of 670x18\n",
+ rect.right - rect.left, rect.bottom - rect.top);
+
+ for (i = 0; i < 3; i++)
+ {
+ ZeroMemory(&item, sizeof(item));
+ item.mask = HDI_TEXT|HDI_WIDTH;
+ item.cxy = 50*(i+1);
+ item.pszText = name;
+ item.lParam = i*5;
+ SendMessage(hWndHeader, HDM_INSERTITEM, i, (LPARAM)&item);
+ }
+
+ run_customdraw_scenario(customdraw_1);
+ run_customdraw_scenario(customdraw_2);
+ run_customdraw_scenario(customdraw_3);
+
+ ZeroMemory(&item, sizeof(item));
+ item.mask = HDI_FORMAT;
+ item.fmt = HDF_OWNERDRAW;
+ SendMessage(hWndHeader, HDM_SETITEM, 1, (LPARAM)&item);
+ g_DrawItem.CtlID = 0;
+ g_DrawItem.CtlType = ODT_HEADER;
+ g_DrawItem.hwndItem = hWndHeader;
+ g_DrawItem.itemID = 1;
+ g_DrawItem.itemState = 0;
+ SendMessage(hWndHeader, HDM_GETITEMRECT, 1, (LPARAM)&g_DrawItem.rcItem);
+ run_customdraw_scenario(customdraw_4);
+ ok(g_DrawItemReceived, "WM_DRAWITEM not received\n");
+ DestroyWindow(hWndHeader);
+ hWndHeader = NULL;
+ g_DrawItem.CtlType = 0;
+ g_DrawItemReceived = FALSE;
+}
+
+static void check_order(const int expected_id[], const int expected_order[],
+ int count, const char *type)
+{
+ int i;
+ HDITEMA hdi;
+
+ ok(getItemCount(hWndHeader) == count, "Invalid item count in order tests\n");
+ for (i = 0; i < count; i++)
+ {
+ hdi.mask = HDI_LPARAM|HDI_ORDER;
+ SendMessage(hWndHeader, HDM_GETITEMA, i, (LPARAM)&hdi);
+ ok(hdi.lParam == expected_id[i],
+ "Invalid item ids after '%s'- item %d has lParam %d\n", type, i, (int)hdi.lParam);
+ ok(hdi.iOrder == expected_order[i],
+ "Invalid item order after '%s'- item %d has iOrder %d\n", type, i, hdi.iOrder);
+ }
+}
+
+static void test_header_order (void)
+{
+ const int rand1[] = {0, 1, 1, 0, 4};
+ const int rand2[] = {4, 5, 6, 7, 4};
+ const int rand3[] = {5, 5, 1, 6, 1};
+ const int rand4[] = {1, 5, 2, 7, 6, 1, 4, 2, 3, 2};
+ const int rand5[] = {7, 8, 5, 6, 7, 2, 1, 9, 10, 10};
+ const int rand6[] = {2, 8, 3, 4, 0};
+
+ const int ids1[] = {3, 0, 2, 1, 4};
+ const int ord1[] = {0, 1, 2, 3, 4};
+ const int ids2[] = {3, 9, 7, 0, 2, 1, 4, 8, 6, 5};
+ const int ord2[] = {0, 4, 7, 1, 2, 3, 9, 8, 6, 5};
+ const int ord3[] = {0, 3, 9, 2, 1, 8, 7, 6, 5, 4};
+ const int ids4[] = {9, 0, 1, 8, 6};
+ const int ord4[] = {1, 0, 4, 3, 2};
+
+ char buffer[20];
+ HDITEMA hdi;
+ int i;
+
+ hWndHeader = create_header_control();
+
+ ZeroMemory(&hdi, sizeof(HDITEMA));
+ hdi.mask = HDI_TEXT | HDI_LPARAM;
+ hdi.pszText = buffer;
+ strcpy(buffer, "test");
+
+ for (i = 0; i < 5; i++)
+ {
+ hdi.lParam = i;
+ SendMessage(hWndHeader, HDM_INSERTITEMA, rand1[i], (LPARAM)&hdi);
+ rand();
+ }
+ check_order(ids1, ord1, 5, "insert without iOrder");
+
+ hdi.mask |= HDI_ORDER;
+ for (i = 0; i < 5; i++)
+ {
+ hdi.lParam = i + 5;
+ hdi.iOrder = rand2[i];
+ SendMessage(hWndHeader, HDM_INSERTITEMA, rand3[i], (LPARAM)&hdi);
+ rand(); rand();
+ }
+ check_order(ids2, ord2, 10, "insert with order");
+
+ hdi.mask = HDI_ORDER;
+ for (i=0; i<10; i++)
+ {
+ hdi.iOrder = rand5[i];
+ SendMessage(hWndHeader, HDM_SETITEMA, rand4[i], (LPARAM)&hdi);
+ rand(); rand();
+ }
+ check_order(ids2, ord3, 10, "setitems changing order");
+
+ for (i=0; i<5; i++)
+ SendMessage(hWndHeader, HDM_DELETEITEM, rand6[i], 0);
+ check_order(ids4, ord4, 5, "deleteitem");
+
+ DestroyWindow(hWndHeader);
+}
+
+static LRESULT CALLBACK HeaderTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ DRAWITEMSTRUCT *di;
switch(msg) {
case WM_NOTIFY:
EXPECTEDNOTIFY *expected;
int i;
+ if (hdr->hdr.code == NM_CUSTOMDRAW)
+ if (g_CustomDrawProc)
+ return g_CustomDrawProc(g_CustomDrawCount++, (NMCUSTOMDRAW*)hdr);
+
for (i=0; i<nUnexpectedNotify; i++)
ok(hdr->hdr.code != unexpectedNotify[i], "Received invalid notify %d\n", hdr->hdr.code);
-
+
if (nReceivedNotify >= nExpectedNotify || hdr->hdr.hwndFrom != hWndHeader )
break;
expected = &expectedNotify[nReceivedNotify];
if (hdr->hdr.code != expected->iCode)
break;
-
+
nReceivedNotify++;
compare_items(hdr->hdr.code, &expected->hdItem, hdr->pitem, expected->fUnicode);
break;
}
+ case WM_DRAWITEM:
+ di = (DRAWITEMSTRUCT *)lParam;
+ ok(g_DrawItem.CtlType != 0, "Unexpected WM_DRAWITEM\n");
+ if (g_DrawItem.CtlType == 0) return 0;
+ g_DrawItemReceived = TRUE;
+ compare(di->CtlType, g_DrawItem.CtlType, "%d");
+ compare(di->CtlID, g_DrawItem.CtlID, "%d");
+ compare(di->hwndItem, g_DrawItem.hwndItem, "%p");
+ compare(di->itemID, g_DrawItem.itemID, "%d");
+ compare(di->itemState, g_DrawItem.itemState, "%d");
+ compare(di->rcItem.left, g_DrawItem.rcItem.left, "%d");
+ compare(di->rcItem.top, g_DrawItem.rcItem.top, "%d");
+ compare(di->rcItem.right, g_DrawItem.rcItem.right, "%d");
+ compare(di->rcItem.bottom, g_DrawItem.rcItem.bottom, "%d");
+ break;
+
case WM_DESTROY:
PostQuitMessage(0);
break;
-
+
default:
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
-
+
return 0L;
}
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandleA(NULL);
wc.hIcon = NULL;
- wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW));
+ wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = "HeaderTestClass";
wc.lpfnWndProc = HeaderTestWndProc;
RegisterClassA(&wc);
- hHeaderParentWnd = CreateWindowExA(0, "HeaderTestClass", "Header test", WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
+ hHeaderParentWnd = CreateWindowExA(0, "HeaderTestClass", "Header test", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 672+2*GetSystemMetrics(SM_CXSIZEFRAME),
+ 226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
+ NULL, NULL, GetModuleHandleA(NULL), 0);
assert(hHeaderParentWnd != NULL);
+ ShowWindow(hHeaderParentWnd, SW_SHOW);
}
START_TEST(header)
{
+ HWND parent_hwnd;
+
init();
test_header_control();
+ test_header_order();
+ test_customdraw();
DestroyWindow(hHeaderParentWnd);
+
+ init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
+ parent_hwnd = create_custom_parent_window();
+ ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create parent windows", FALSE);
+
+ test_hdm_index_messages(parent_hwnd);
+ test_hdm_getitemrect(parent_hwnd);
+ test_hdm_hittest(parent_hwnd);
+ test_hdm_layout(parent_hwnd);
+ test_hdm_ordertoindex(parent_hwnd);
+ test_hdm_sethotdivider(parent_hwnd);
+ test_hdm_imageMessages(parent_hwnd);
+ test_hdm_filterMessages(parent_hwnd);
+ test_hdm_unicodeformatMessages(parent_hwnd);
+ test_hdm_bitmapmarginMessages(parent_hwnd);
+
+ DestroyWindow(parent_hwnd);
+
}
-/* Unit test suite for imagelist control.
+/*
+ * Unit test suite for imagelist control.
*
* Copyright 2004 Michael Stefaniuc
* Copyright 2002 Mike McCormack for CodeWeavers
+ * Copyright 2007 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <assert.h>
-#include <windows.h>
-#include <commctrl.h>
+#define COBJMACROS
+#define CONST_VTABLE
+
+#include <stdarg.h>
#include <stdio.h>
+#include <assert.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "objbase.h"
+#include "commctrl.h" /* must be included after objbase.h to get ImageList_Write */
#include "wine/test.h"
#define REDRAW(hwnd)
#endif
+#define IMAGELIST_MAGIC (('L' << 8) | 'I')
+
+#include "pshpack2.h"
+/* Header used by ImageList_Read() and ImageList_Write() */
+typedef struct _ILHEAD
+{
+ USHORT usMagic;
+ USHORT usVersion;
+ WORD cCurImage;
+ WORD cMaxImage;
+ WORD cGrow;
+ WORD cx;
+ WORD cy;
+ COLORREF bkcolor;
+ WORD flags;
+ SHORT ovls[4];
+} ILHEAD;
+#include "poppack.h"
static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*) = NULL;
/* check new hotspot, it should be the same like the old one */
himlNew = ImageList_GetDragImage(NULL, &ppt);
ok(ppt.x == dx1 && ppt.y == dy1,
- "Expected drag hotspot [%d,%d] got [%ld,%ld]\n",
+ "Expected drag hotspot [%d,%d] got [%d,%d]\n",
dx1, dy1, ppt.x, ppt.y);
/* check size of new dragged image */
ImageList_GetIconSize(himlNew, &newx, &newy);
#undef SIZEX2
#undef SIZEY2
#undef HOTSPOTS_MAX
+ ImageList_Destroy(himl2);
+ ImageList_Destroy(himl1);
DestroyWindow(hwnd);
}
/* remove one extra */
ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
+ /* check SetImageCount/GetImageCount */
+ ok(ImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
+ ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
+ ok(ImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
+ ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
+ ok(ImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
+ ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
+
/* destroy it */
ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
- /* icons should be deleted by the imagelist */
- ok(!DeleteObject(hicon1),"icon 1 wasn't deleted\n");
- ok(!DeleteObject(hicon2),"icon 2 wasn't deleted\n");
- ok(!DeleteObject(hicon3),"icon 3 wasn't deleted\n");
+ ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
+ ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
+ ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
return TRUE;
}
/* destroy it */
ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
- /* icons should be deleted by the imagelist */
- ok(!DeleteObject(hicon1),"icon 1 wasn't deleted\n");
- ok(!DeleteObject(hicon2),"icon 2 wasn't deleted\n");
- ok(!DeleteObject(hicon3),"icon 3 wasn't deleted\n");
+ ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
+ ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
+ ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
return TRUE;
}
ImageList_Destroy(himl1);
ImageList_Destroy(himl2);
- DeleteObject(hicon1);
+ DestroyIcon(hicon1);
DestroyWindow(hwnd);
}
+/*********************** imagelist storage test ***************************/
+
+#define BMP_CX 48
+
+struct my_IStream
+{
+ IStream is;
+ char *iml_data; /* written imagelist data */
+ ULONG iml_data_size;
+};
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(
+ IStream* This,
+ REFIID riid,
+ void** ppvObject)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(
+ IStream* This)
+{
+ assert(0);
+ return 2;
+}
+
+static ULONG STDMETHODCALLTYPE Test_Stream_Release(
+ IStream* This)
+{
+ assert(0);
+ return 1;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_Read(
+ IStream* This,
+ void* pv,
+ ULONG cb,
+ ULONG* pcbRead)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
+{
+ my_is->iml_data_size += add;
+
+ if (!my_is->iml_data)
+ my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
+ else
+ my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
+
+ return my_is->iml_data ? TRUE : FALSE;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_Write(
+ IStream* This,
+ const void* pv,
+ ULONG cb,
+ ULONG* pcbWritten)
+{
+ struct my_IStream *my_is = (struct my_IStream *)This;
+ ULONG current_iml_data_size = my_is->iml_data_size;
+
+ if (!allocate_storage(my_is, cb)) return E_FAIL;
+
+ memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
+ if (pcbWritten) *pcbWritten = cb;
+
+ return S_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(
+ IStream* This,
+ LARGE_INTEGER dlibMove,
+ DWORD dwOrigin,
+ ULARGE_INTEGER* plibNewPosition)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(
+ IStream* This,
+ ULARGE_INTEGER libNewSize)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(
+ IStream* This,
+ IStream* pstm,
+ ULARGE_INTEGER cb,
+ ULARGE_INTEGER* pcbRead,
+ ULARGE_INTEGER* pcbWritten)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(
+ IStream* This,
+ DWORD grfCommitFlags)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(
+ IStream* This)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(
+ IStream* This,
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(
+ IStream* This,
+ ULARGE_INTEGER libOffset,
+ ULARGE_INTEGER cb,
+ DWORD dwLockType)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(
+ IStream* This,
+ STATSTG* pstatstg,
+ DWORD grfStatFlag)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(
+ IStream* This,
+ IStream** ppstm)
+{
+ assert(0);
+ return E_NOTIMPL;
+}
+
+static const IStreamVtbl Test_Stream_Vtbl =
+{
+ Test_Stream_QueryInterface,
+ Test_Stream_AddRef,
+ Test_Stream_Release,
+ Test_Stream_Read,
+ Test_Stream_Write,
+ Test_Stream_Seek,
+ Test_Stream_SetSize,
+ Test_Stream_CopyTo,
+ Test_Stream_Commit,
+ Test_Stream_Revert,
+ Test_Stream_LockRegion,
+ Test_Stream_UnlockRegion,
+ Test_Stream_Stat,
+ Test_Stream_Clone
+};
+
+static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
+
+static INT DIB_GetWidthBytes( int width, int bpp )
+{
+ int words;
+
+ switch (bpp)
+ {
+ case 1: words = (width + 31) / 32; break;
+ case 4: words = (width + 7) / 8; break;
+ case 8: words = (width + 3) / 4; break;
+ case 15:
+ case 16: words = (width + 1) / 2; break;
+ case 24: words = (width * 3 + 3)/4; break;
+ case 32: words = width; break;
+
+ default:
+ words=0;
+ trace("Unknown depth %d, please report.\n", bpp );
+ assert(0);
+ break;
+ }
+ return 4 * words;
+}
+
+static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
+ INT width, INT height, INT bpp,
+ const char *comment)
+{
+ const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
+ const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
+ ULONG hdr_size, image_size;
+
+ hdr_size = sizeof(*bmfh) + sizeof(*bmih);
+ if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
+
+ ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
+ ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
+ ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
+ ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
+ ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
+
+ ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
+ ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
+ ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
+ ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
+ ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
+
+ image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
+ ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
+#if 0
+{
+ char fname[256];
+ FILE *f;
+ sprintf(fname, "bmp_%s.bmp", comment);
+ f = fopen(fname, "wb");
+ fwrite(bm_data, 1, bm_data_size, f);
+ fclose(f);
+}
+#endif
+}
+
+static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max)
+{
+ ILHEAD *ilh = (ILHEAD *)ilh_data;
+
+ ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
+ ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
+ ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
+ ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
+ ok(ilh->cGrow == 4, "wrong cGrow %d (expected 4)\n", ilh->cGrow);
+ ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
+ ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
+ ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
+ ok(ilh->flags == ILC_COLOR24, "wrong flags %04x\n", ilh->flags);
+ ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
+ ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
+ ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
+ ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
+}
+
+static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
+{
+ HDC hdc;
+ char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
+ BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
+ HBITMAP hbmp, hbmp_old;
+ HBRUSH hbrush;
+ RECT rc = { 0, 0, cx, cy };
+
+ hdc = CreateCompatibleDC(0);
+
+ memset(bmi, 0, sizeof(*bmi));
+ bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
+ bmi->bmiHeader.biHeight = cx;
+ bmi->bmiHeader.biWidth = cy;
+ bmi->bmiHeader.biBitCount = 24;
+ bmi->bmiHeader.biPlanes = 1;
+ bmi->bmiHeader.biCompression = BI_RGB;
+ hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
+
+ hbmp_old = SelectObject(hdc, hbmp);
+
+ hbrush = CreateSolidBrush(color);
+ FillRect(hdc, &rc, hbrush);
+ DeleteObject(hbrush);
+
+ DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
+
+ SelectObject(hdc, hbmp_old);
+ DeleteDC(hdc);
+
+ return hbmp;
+}
+
+static void image_list_init(HIMAGELIST himl)
+{
+ HBITMAP hbm;
+ char comment[16];
+ INT n = 1;
+
+#define add_bitmap(grey) \
+ sprintf(comment, "%d", n++); \
+ hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
+ ImageList_Add(himl, hbm, NULL);
+
+ add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
+ add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
+ add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
+ add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
+ add_bitmap(255); add_bitmap(170); add_bitmap(85); add_bitmap(0);
+ add_bitmap(0); add_bitmap(85); add_bitmap(170); add_bitmap(255);
+#undef add_bitmap
+}
+
+#define iml_clear_stream_data() \
+ HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
+ Test_Stream.iml_data = NULL; \
+ Test_Stream.iml_data_size = 0;
+
+static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max,
+ INT width, INT height, INT bpp, const char *comment)
+{
+ INT ret, cxx, cyy;
+
+ ret = ImageList_GetImageCount(himl);
+ ok(ret == cur, "expected cur %d got %d\n", cur, ret);
+
+ ret = ImageList_GetIconSize(himl, &cxx, &cyy);
+ ok(ret, "ImageList_GetIconSize failed\n");
+ ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
+ ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
+
+ iml_clear_stream_data();
+ ret = ImageList_Write(himl, &Test_Stream.is);
+ ok(ret, "ImageList_Write failed\n");
+
+ ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
+ ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
+
+ check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max);
+ check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
+ Test_Stream.iml_data_size - sizeof(ILHEAD),
+ width, height, bpp, comment);
+}
+
+static void test_imagelist_storage(void)
+{
+ HIMAGELIST himl;
+ BOOL ret;
+
+ himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
+ ok(himl != 0, "ImageList_Create failed\n");
+
+ check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, BMP_CX * 4, BMP_CX * 1, 24, "empty");
+
+ image_list_init(himl);
+ check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, BMP_CX * 4, BMP_CX * 7, 24, "orig");
+
+ ret = ImageList_Remove(himl, 4);
+ ok(ret, "ImageList_Remove failed\n");
+ check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, BMP_CX * 4, BMP_CX * 7, 24, "1");
+
+ ret = ImageList_Remove(himl, 5);
+ ok(ret, "ImageList_Remove failed\n");
+ check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, BMP_CX * 4, BMP_CX * 7, 24, "2");
+
+ ret = ImageList_Remove(himl, 6);
+ ok(ret, "ImageList_Remove failed\n");
+ check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, BMP_CX * 4, BMP_CX * 7, 24, "3");
+
+ ret = ImageList_Remove(himl, 7);
+ ok(ret, "ImageList_Remove failed\n");
+ check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "4");
+
+ ret = ImageList_Remove(himl, -2);
+ ok(!ret, "ImageList_Remove(-2) should fail\n");
+ check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "5");
+
+ ret = ImageList_Remove(himl, 20);
+ ok(!ret, "ImageList_Remove(20) should fail\n");
+ check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, BMP_CX * 4, BMP_CX * 7, 24, "6");
+
+ ret = ImageList_Remove(himl, -1);
+ ok(ret, "ImageList_Remove(-1) failed\n");
+ check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, BMP_CX * 4, BMP_CX * 1, 24, "7");
+
+ ret = ImageList_Destroy(himl);
+ ok(ret, "ImageList_Destroy failed\n");
+
+ iml_clear_stream_data();
+}
+
START_TEST(imagelist)
{
desktopDC=GetDC(NULL);
DoTest2();
DoTest3();
testMerge();
+ test_imagelist_storage();
}
* ListView tests
*
* Copyright 2006 Mike McCormack for CodeWeavers
+ * Copyright 2007 George Gov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <commctrl.h>
#include "wine/test.h"
+#include "msg.h"
+
+#define PARENT_SEQ_INDEX 0
+#define LISTVIEW_SEQ_INDEX 1
+#define NUM_MSG_SEQUENCES 2
+
+#define LISTVIEW_ID 0
+#define HEADER_ID 1
+
+#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
+#define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
+ "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
+
+HWND hwndparent;
+
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+
+static const struct message create_parent_wnd_seq[] = {
+ { WM_GETMINMAXINFO, sent },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { WM_SHOWWINDOW, sent|wparam, 1 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_ACTIVATEAPP, sent|wparam, 1 },
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATE, sent|wparam, 1 },
+ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+ { WM_IME_NOTIFY, sent|defwinproc|optional },
+ { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+ /* Win9x adds SWP_NOZORDER below */
+ { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
+ { WM_NCCALCSIZE, sent|wparam|optional, 1 },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
+ { 0 }
+};
+
+static const struct message redraw_listview_seq[] = {
+ { WM_PAINT, sent|id, 0, 0, LISTVIEW_ID },
+ { WM_PAINT, sent|id, 0, 0, HEADER_ID },
+ { WM_NCPAINT, sent|id|defwinproc, 0, 0, HEADER_ID },
+ { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, HEADER_ID },
+ { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
+ { WM_NCPAINT, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
+ { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
+ { 0 }
+};
+
+static const struct message listview_icon_spacing_seq[] = {
+ { LVM_SETICONSPACING, sent|lparam, 0, (LPARAM) MAKELONG(20, 30) },
+ { LVM_SETICONSPACING, sent|lparam, 0, (LPARAM) MAKELONG(25, 35) },
+ { LVM_SETICONSPACING, sent|lparam, 0, (LPARAM) MAKELONG(-1, -1) },
+ { 0 }
+};
+
+static const struct message listview_color_seq[] = {
+ { LVM_SETBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
+ { LVM_GETBKCOLOR, sent },
+ { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(0,0,0) },
+ { LVM_GETTEXTCOLOR, sent },
+ { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
+ { LVM_GETTEXTBKCOLOR, sent },
+
+ { LVM_SETBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
+ { LVM_GETBKCOLOR, sent },
+ { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(100,50,200) },
+ { LVM_GETTEXTCOLOR, sent },
+ { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
+ { LVM_GETTEXTBKCOLOR, sent },
+
+ { LVM_SETBKCOLOR, sent|lparam, 0, CLR_NONE },
+ { LVM_GETBKCOLOR, sent },
+ { LVM_SETTEXTCOLOR, sent|lparam, 0, CLR_NONE },
+ { LVM_GETTEXTCOLOR, sent },
+ { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
+ { LVM_GETTEXTBKCOLOR, sent },
+
+ { LVM_SETBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
+ { LVM_GETBKCOLOR, sent },
+ { LVM_SETTEXTCOLOR, sent|lparam, 0, RGB(255,255,255) },
+ { LVM_GETTEXTCOLOR, sent },
+ { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
+ { LVM_GETTEXTBKCOLOR, sent },
+ { 0 }
+};
+
+static const struct message listview_item_count_seq[] = {
+ { LVM_GETITEMCOUNT, sent },
+ { LVM_INSERTITEM, sent },
+ { LVM_INSERTITEM, sent },
+ { LVM_INSERTITEM, sent },
+ { LVM_GETITEMCOUNT, sent },
+ { LVM_DELETEITEM, sent|wparam, 2 },
+ { LVM_GETITEMCOUNT, sent },
+ { LVM_DELETEALLITEMS, sent },
+ { LVM_GETITEMCOUNT, sent },
+ { LVM_INSERTITEM, sent },
+ { LVM_INSERTITEM, sent },
+ { LVM_GETITEMCOUNT, sent },
+ { LVM_INSERTITEM, sent },
+ { LVM_GETITEMCOUNT, sent },
+ { 0 }
+};
+
+static const struct message listview_itempos_seq[] = {
+ { LVM_INSERTITEM, sent },
+ { LVM_INSERTITEM, sent },
+ { LVM_INSERTITEM, sent },
+ { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
+ { LVM_GETITEMPOSITION, sent|wparam, 1 },
+ { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
+ { LVM_GETITEMPOSITION, sent|wparam, 2 },
+ { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
+ { LVM_GETITEMPOSITION, sent|wparam, 0 },
+ { 0 }
+};
+
+struct subclass_info
+{
+ WNDPROC oldproc;
+};
+
+static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ /* do not log painting messages */
+ if (message != WM_PAINT &&
+ message != WM_ERASEBKGND &&
+ message != WM_NCPAINT &&
+ message != WM_NCHITTEST &&
+ message != WM_GETTEXT &&
+ message != WM_GETICON &&
+ message != WM_DEVICECHANGE)
+ {
+ trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, PARENT_SEQ_INDEX, &msg);
+ }
+
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static BOOL register_parent_wnd_class(void)
+{
+ WNDCLASSA cls;
+
+ cls.style = 0;
+ cls.lpfnWndProc = parent_wnd_proc;
+ cls.cbClsExtra = 0;
+ cls.cbWndExtra = 0;
+ cls.hInstance = GetModuleHandleA(NULL);
+ cls.hIcon = 0;
+ cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
+ cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+ cls.lpszMenuName = NULL;
+ cls.lpszClassName = "Listview test parent class";
+ return RegisterClassA(&cls);
+}
+
+static HWND create_parent_window(void)
+{
+ if (!register_parent_wnd_class())
+ return NULL;
+
+ return CreateWindowEx(0, "Listview test parent class",
+ "Listview test parent window",
+ WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
+ WS_MAXIMIZEBOX | WS_VISIBLE,
+ 0, 0, 100, 100,
+ GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
+}
+
+static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ msg.id = LISTVIEW_ID;
+ add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+ return ret;
+}
+
+static HWND create_listview_control(void)
+{
+ struct subclass_info *info;
+ HWND hwnd;
+ RECT rect;
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ GetClientRect(hwndparent, &rect);
+ hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
+ WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT,
+ 0, 0, rect.right, rect.bottom,
+ hwndparent, NULL, GetModuleHandleA(NULL), NULL);
+ ok(hwnd != NULL, "gle=%d\n", GetLastError());
+
+ if (!hwnd)
+ {
+ HeapFree(GetProcessHeap(), 0, info);
+ return NULL;
+ }
+
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
+ (LONG_PTR)listview_subclass_proc);
+ SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
+
+ return hwnd;
+}
+
+static HWND create_custom_listview_control(DWORD style)
+{
+ struct subclass_info *info;
+ HWND hwnd;
+ RECT rect;
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ GetClientRect(hwndparent, &rect);
+ hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
+ WS_CHILD | WS_BORDER | WS_VISIBLE | style,
+ 0, 0, rect.right, rect.bottom,
+ hwndparent, NULL, GetModuleHandleA(NULL), NULL);
+ ok(hwnd != NULL, "gle=%d\n", GetLastError());
+
+ if (!hwnd)
+ {
+ HeapFree(GetProcessHeap(), 0, info);
+ return NULL;
+ }
+
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
+ (LONG_PTR)listview_subclass_proc);
+ SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
+
+ return hwnd;
+}
+
+static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ msg.id = HEADER_ID;
+ add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+ return ret;
+}
+
+static HWND subclass_header(HWND hwndListview)
+{
+ struct subclass_info *info;
+ HWND hwnd;
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ hwnd = ListView_GetHeader(hwndListview);
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
+ (LONG_PTR)header_subclass_proc);
+ SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
+
+ return hwnd;
+}
static void test_images(void)
{
- HWND hwnd, hwndparent = 0;
+ HWND hwnd;
DWORD r;
LVITEM item;
HIMAGELIST himl;
r = ImageList_Add(himl, hbmp, 0);
ok(r == 0, "should be zero\n");
- hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED,
+ hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED,
10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
ok(hwnd != NULL, "failed to create listview window\n");
item.iItem = 0;
item.iSubItem = 1;
item.iImage = 0;
+ item.pszText = 0;
r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
ok(r == -1, "should fail\n");
static void test_checkboxes(void)
{
- HWND hwnd, hwndparent = 0;
+ HWND hwnd;
LVITEMA item;
DWORD r;
static CHAR text[] = "Text",
text2[] = "Text2",
text3[] = "Text3";
- hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
+ hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
ok(hwnd != NULL, "failed to create listview window\n");
item.iSubItem = 0;
item.pszText = text;
r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
- ok(r == 0, "ret %ld\n", r);
+ ok(r == 0, "ret %d\n", r);
item.iItem = 0;
item.mask = LVIF_STATE;
item.iSubItem = 0;
item.pszText = text;
r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
- ok(r == 1, "ret %ld\n", r);
+ ok(r == 1, "ret %d\n", r);
item.iItem = 1;
item.mask = LVIF_STATE;
r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
ok(item.state == 0x1ccc, "state %x\n", item.state);
- /* Now add an item without specifying a state and check that it's state goes to 0x1000 */
+ /* Now add an item without specifying a state and check that its state goes to 0x1000 */
item.iItem = 2;
item.mask = LVIF_TEXT;
item.state = 0;
item.pszText = text2;
r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
- ok(r == 2, "ret %ld\n", r);
+ ok(r == 2, "ret %d\n", r);
item.iItem = 2;
item.mask = LVIF_STATE;
r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
ok(item.state == 0x1000, "state %x\n", item.state);
- /* Add a further item this time specifying a state and still it's state goes to 0x1000 */
+ /* Add a further item this time specifying a state and still its state goes to 0x1000 */
item.iItem = 3;
item.mask = LVIF_TEXT | LVIF_STATE;
item.stateMask = 0xffff;
item.state = 0x2aaa;
item.pszText = text3;
r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
- ok(r == 3, "ret %ld\n", r);
+ ok(r == 3, "ret %d\n", r);
item.iItem = 3;
item.mask = LVIF_STATE;
r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
ok(item.state == 0x2aaa, "state %x\n", item.state);
+ /* Check that only the bits we asked for are returned,
+ * and that all the others are set to zero
+ */
+ item.iItem = 3;
+ item.mask = LVIF_STATE;
+ item.stateMask = 0xf000;
+ item.state = 0xffff;
+ r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
+ ok(item.state == 0x2000, "state %x\n", item.state);
+
/* Set the style again and check that doesn't change an item's state */
r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
- ok(r == LVS_EX_CHECKBOXES, "ret %lx\n", r);
+ ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
item.iItem = 3;
item.mask = LVIF_STATE;
/* Unsetting the checkbox extended style doesn't change an item's state */
r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
- ok(r == LVS_EX_CHECKBOXES, "ret %lx\n", r);
+ ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
item.iItem = 3;
item.mask = LVIF_STATE;
/* Now setting the style again will change an item's state */
r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
- ok(r == 0, "ret %lx\n", r);
+ ok(r == 0, "ret %x\n", r);
item.iItem = 3;
item.mask = LVIF_STATE;
DestroyWindow(hwnd);
}
+static void insert_column(HWND hwnd, int idx)
+{
+ LVCOLUMN column;
+ DWORD rc;
+
+ memset(&column, 0xaa, sizeof(column));
+ column.mask = LVCF_SUBITEM;
+ column.iSubItem = idx;
+
+ rc = ListView_InsertColumn(hwnd, idx, &column);
+ expect(idx, rc);
+}
+
+static void insert_item(HWND hwnd, int idx)
+{
+ static CHAR text[] = "foo";
+
+ LVITEMA item;
+ DWORD rc;
+
+ memset(&item, 0xaa, sizeof (item));
+ item.mask = LVIF_TEXT;
+ item.iItem = idx;
+ item.iSubItem = 0;
+ item.pszText = text;
+
+ rc = ListView_InsertItem(hwnd, &item);
+ expect(idx, rc);
+}
+
+static void test_items(void)
+{
+ const LPARAM lparamTest = 0x42;
+ HWND hwnd;
+ LVITEMA item;
+ DWORD r;
+ static CHAR text[] = "Text";
+
+ hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
+ 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
+ ok(hwnd != NULL, "failed to create listview window\n");
+
+ /*
+ * Test setting/getting item params
+ */
+
+ /* Set up two columns */
+ insert_column(hwnd, 0);
+ insert_column(hwnd, 1);
+
+ /* Insert an item with just a param */
+ memset (&item, 0xaa, sizeof (item));
+ item.mask = LVIF_PARAM;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ item.lParam = lparamTest;
+ r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
+ ok(r == 0, "ret %d\n", r);
+
+ /* Test getting of the param */
+ memset (&item, 0xaa, sizeof (item));
+ item.mask = LVIF_PARAM;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
+ ok(r != 0, "ret %d\n", r);
+ ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
+
+ /* Set up a subitem */
+ memset (&item, 0xaa, sizeof (item));
+ item.mask = LVIF_TEXT;
+ item.iItem = 0;
+ item.iSubItem = 1;
+ item.pszText = text;
+ r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
+ ok(r != 0, "ret %d\n", r);
+
+ /* Query param from subitem: returns main item param */
+ memset (&item, 0xaa, sizeof (item));
+ item.mask = LVIF_PARAM;
+ item.iItem = 0;
+ item.iSubItem = 1;
+ r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
+ ok(r != 0, "ret %d\n", r);
+ ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
+
+ /* Set up param on first subitem: no effect */
+ memset (&item, 0xaa, sizeof (item));
+ item.mask = LVIF_PARAM;
+ item.iItem = 0;
+ item.iSubItem = 1;
+ item.lParam = lparamTest+1;
+ r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
+ ok(r == 0, "ret %d\n", r);
+
+ /* Query param from subitem again: should still return main item param */
+ memset (&item, 0xaa, sizeof (item));
+ item.mask = LVIF_PARAM;
+ item.iItem = 0;
+ item.iSubItem = 1;
+ r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
+ ok(r != 0, "ret %d\n", r);
+ ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
+
+ /**** Some tests of state highlighting ****/
+ memset (&item, 0xaa, sizeof (item));
+ item.mask = LVIF_STATE;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ item.state = LVIS_SELECTED;
+ item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
+ r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
+ ok(r != 0, "ret %d\n", r);
+ item.iSubItem = 1;
+ item.state = LVIS_DROPHILITED;
+ r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
+ ok(r != 0, "ret %d\n", r);
+
+ memset (&item, 0xaa, sizeof (item));
+ item.mask = LVIF_STATE;
+ item.iItem = 0;
+ item.iSubItem = 0;
+ item.stateMask = -1;
+ r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
+ ok(r != 0, "ret %d\n", r);
+ ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
+ item.iSubItem = 1;
+ r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
+ ok(r != 0, "ret %d\n", r);
+ todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_columns(void)
+{
+ HWND hwnd;
+ LVCOLUMN column;
+ DWORD rc;
+
+ hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
+ 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
+ ok(hwnd != NULL, "failed to create listview window\n");
+
+ /* Add a column with no mask */
+ memset(&column, 0xaa, sizeof(column));
+ column.mask = 0;
+ rc = ListView_InsertColumn(hwnd, 0, &column);
+ ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
+
+ /* Check its width */
+ rc = ListView_GetColumnWidth(hwnd, 0);
+ ok(rc==10, "Inserting column with no mask failed to set width to 10 with %d\n", rc);
+
+ DestroyWindow(hwnd);
+}
+/* test setting imagelist between WM_NCCREATE and WM_CREATE */
+static WNDPROC listviewWndProc;
+static HIMAGELIST test_create_imagelist;
+
+static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ if (uMsg == WM_CREATE)
+ {
+ LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
+ lpcs->style |= LVS_REPORT;
+ SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
+ }
+ return CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
+}
+
+static void test_create(void)
+{
+ HWND hList;
+ HWND hHeader;
+ WNDCLASSEX cls;
+ cls.cbSize = sizeof(WNDCLASSEX);
+ ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
+ listviewWndProc = cls.lpfnWndProc;
+ cls.lpfnWndProc = create_test_wndproc;
+ cls.lpszClassName = "MyListView32";
+ ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
+
+ test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
+ hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
+ ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
+ hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
+ ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
+ DestroyWindow(hList);
+}
+
+static void test_redraw(void)
+{
+ HWND hwnd, hwndheader;
+
+ hwnd = create_listview_control();
+ hwndheader = subclass_header(hwnd);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ trace("invalidate & update\n");
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+ ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ DestroyWindow(hwnd);
+}
+
+static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+ COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
+
+ if(msg == WM_NOTIFY) {
+ NMHDR *nmhdr = (PVOID)lp;
+ if(nmhdr->code == NM_CUSTOMDRAW) {
+ NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
+ trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
+ switch(nmlvcd->nmcd.dwDrawStage) {
+ case CDDS_PREPAINT:
+ SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
+ return CDRF_NOTIFYITEMDRAW;
+ case CDDS_ITEMPREPAINT:
+ nmlvcd->clrTextBk = CLR_DEFAULT;
+ return CDRF_NOTIFYSUBITEMDRAW;
+ case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
+ clr = GetBkColor(nmlvcd->nmcd.hdc);
+ todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
+ return CDRF_NOTIFYPOSTPAINT;
+ case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
+ clr = GetBkColor(nmlvcd->nmcd.hdc);
+ todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
+ return CDRF_DODEFAULT;
+ }
+ return CDRF_DODEFAULT;
+ }
+ }
+
+ return DefWindowProcA(hwnd, msg, wp, lp);
+}
+
+static void test_customdraw(void)
+{
+ HWND hwnd;
+ WNDPROC oldwndproc;
+
+ hwnd = create_listview_control();
+
+ insert_column(hwnd, 0);
+ insert_column(hwnd, 1);
+ insert_item(hwnd, 0);
+
+ oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
+ (LONG_PTR)cd_wndproc);
+
+ InvalidateRect(hwnd, NULL, TRUE);
+ UpdateWindow(hwnd);
+
+ SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
+
+ DestroyWindow(hwnd);
+}
+
+static void test_icon_spacing(void)
+{
+ /* LVM_SETICONSPACING */
+ /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
+ /* note: the first test will fail if the default icon spacing is not (43,43) */
+
+ HWND hwnd;
+ DWORD r;
+
+ hwnd = create_custom_listview_control(LVS_ICON);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ trace("test icon spacing\n");
+ todo_wine {
+ r = SendMessage(hwnd, LVM_SETICONSPACING, 0, (LPARAM) MAKELONG(20, 30));
+ expect(MAKELONG(43,43), r);
+ }
+ r = SendMessage(hwnd, LVM_SETICONSPACING, 0, (LPARAM) MAKELONG(25, 35));
+ expect(MAKELONG(20,30), r);
+ r = SendMessage(hwnd, LVM_SETICONSPACING, 0, (LPARAM) MAKELONG(-1,-1));
+ expect(MAKELONG(25,35), r);
+
+ ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ DestroyWindow(hwnd);
+}
+
+static void test_color(void)
+{
+ /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
+
+ HWND hwnd;
+ DWORD r;
+ int i;
+
+ COLORREF color;
+ COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
+
+ hwnd = create_listview_control();
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ trace("test color seq\n");
+ for (i = 0; i < 4; i++)
+ {
+ color = colors[i];
+
+ r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
+ expect(TRUE, r);
+ r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
+ expect(color, r);
+
+ r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
+ expect (TRUE, r);
+ r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
+ expect(color, r);
+
+ r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
+ expect(TRUE, r);
+ r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
+ expect(color, r);
+ }
+
+ ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ DestroyWindow(hwnd);
+}
+
+static void test_item_count(void)
+{
+ /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
+
+ HWND hwnd;
+ DWORD r;
+
+ LVITEM item0;
+ LVITEM item1;
+ LVITEM item2;
+ static CHAR item0text[] = "item0";
+ static CHAR item1text[] = "item1";
+ static CHAR item2text[] = "item2";
+
+ hwnd = create_listview_control();
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ trace("test item count\n");
+
+ r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
+ expect(0, r);
+
+ /* [item0] */
+ item0.mask = LVIF_TEXT;
+ item0.iItem = 0;
+ item0.iSubItem = 0;
+ item0.pszText = item0text;
+ r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
+ expect(0, r);
+
+ /* [item0, item1] */
+ item1.mask = LVIF_TEXT;
+ item1.iItem = 1;
+ item1.iSubItem = 0;
+ item1.pszText = item1text;
+ r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
+ expect(1, r);
+
+ /* [item0, item1, item2] */
+ item2.mask = LVIF_TEXT;
+ item2.iItem = 2;
+ item2.iSubItem = 0;
+ item2.pszText = item2text;
+ r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
+ expect(2, r);
+
+ r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
+ expect(3, r);
+
+ /* [item0, item1] */
+ r = SendMessage(hwnd, LVM_DELETEITEM, (WPARAM) 2, 0);
+ expect(TRUE, r);
+
+ r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
+ expect(2, r);
+
+ /* [] */
+ r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
+ expect(TRUE, r);
+
+ r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
+ expect(0, r);
+
+ /* [item0] */
+ r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
+ expect(0, r);
+
+ /* [item0, item1] */
+ r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
+ expect(1, r);
+
+ r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
+ expect(2, r);
+
+ /* [item0, item1, item2] */
+ r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
+ expect(2, r);
+
+ r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
+ expect(3, r);
+
+ ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ DestroyWindow(hwnd);
+}
+
+static void test_item_position(void)
+{
+ /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
+
+ HWND hwnd;
+ DWORD r;
+ POINT position;
+
+ LVITEM item0;
+ LVITEM item1;
+ LVITEM item2;
+ static CHAR item0text[] = "item0";
+ static CHAR item1text[] = "item1";
+ static CHAR item2text[] = "item2";
+
+ hwnd = create_custom_listview_control(LVS_ICON);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ trace("test item position\n");
+
+ /* [item0] */
+ item0.mask = LVIF_TEXT;
+ item0.iItem = 0;
+ item0.iSubItem = 0;
+ item0.pszText = item0text;
+ r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
+ expect(0, r);
+
+ /* [item0, item1] */
+ item1.mask = LVIF_TEXT;
+ item1.iItem = 1;
+ item1.iSubItem = 0;
+ item1.pszText = item1text;
+ r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
+ expect(1, r);
+
+ /* [item0, item1, item2] */
+ item2.mask = LVIF_TEXT;
+ item2.iItem = 2;
+ item2.iSubItem = 0;
+ item2.pszText = item2text;
+ r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
+ expect(2, r);
+
+ r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
+ expect(TRUE, r);
+ r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
+ expect(TRUE, r);
+ expect2(10, 5, position.x, position.y);
+
+ r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
+ expect(TRUE, r);
+ r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
+ expect(TRUE, r);
+ expect2(0, 0, position.x, position.y);
+
+ r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
+ expect(TRUE, r);
+ r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
+ expect(TRUE, r);
+ expect2(20, 20, position.x, position.y);
+
+ ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ DestroyWindow(hwnd);
+}
+
START_TEST(listview)
{
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof icc;
InitCommonControlsEx(&icc);
+ init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hwndparent = create_parent_window();
+ ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create parent window", TRUE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
test_images();
test_checkboxes();
+ test_items();
+ test_create();
+ test_redraw();
+ test_customdraw();
+ test_icon_spacing();
+ test_color();
+ test_item_count();
+ test_item_position();
+ test_columns();
}
--- /dev/null
+/*
+ * Misc tests
+ *
+ * Copyright 2006 Paul Vriens
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdio.h>
+#include <windows.h>
+
+#include "wine/test.h"
+
+static PVOID (WINAPI * pAlloc)(LONG);
+static PVOID (WINAPI * pReAlloc)(PVOID, LONG);
+static BOOL (WINAPI * pFree)(PVOID);
+static LONG (WINAPI * pGetSize)(PVOID);
+
+static INT (WINAPI * pStr_GetPtrA)(LPCSTR, LPSTR, INT);
+static BOOL (WINAPI * pStr_SetPtrA)(LPSTR, LPCSTR);
+static INT (WINAPI * pStr_GetPtrW)(LPCWSTR, LPWSTR, INT);
+static BOOL (WINAPI * pStr_SetPtrW)(LPWSTR, LPCWSTR);
+
+static HMODULE hComctl32 = 0;
+
+#define COMCTL32_GET_PROC(ordinal, func) \
+ p ## func = (void*)GetProcAddress(hComctl32, (LPSTR)ordinal); \
+ if(!p ## func) { \
+ trace("GetProcAddress(%d)(%s) failed\n", ordinal, #func); \
+ FreeLibrary(hComctl32); \
+ }
+
+#define expect(expected, got) ok(expected == got, "expected %d, got %d\n", expected,got)
+
+static BOOL InitFunctionPtrs(void)
+{
+ hComctl32 = LoadLibraryA("comctl32.dll");
+
+ if(!hComctl32)
+ {
+ trace("Could not load comctl32.dll\n");
+ return FALSE;
+ }
+
+ COMCTL32_GET_PROC(71, Alloc);
+ COMCTL32_GET_PROC(72, ReAlloc);
+ COMCTL32_GET_PROC(73, Free);
+ COMCTL32_GET_PROC(74, GetSize);
+
+ COMCTL32_GET_PROC(233, Str_GetPtrA)
+ COMCTL32_GET_PROC(234, Str_SetPtrA)
+ COMCTL32_GET_PROC(235, Str_GetPtrW)
+ COMCTL32_GET_PROC(236, Str_SetPtrW)
+
+ return TRUE;
+}
+
+static void test_GetPtrAW(void)
+{
+ if (pStr_GetPtrA)
+ {
+ static const char source[] = "Just a source string";
+ static const char desttest[] = "Just a destination string";
+ static char dest[MAX_PATH];
+ int sourcelen;
+ int destsize = MAX_PATH;
+ int count = -1;
+
+ sourcelen = strlen(source) + 1;
+
+ count = pStr_GetPtrA(NULL, NULL, 0);
+ ok (count == 0, "Expected count to be 0, it was %d\n", count);
+
+ if (0)
+ {
+ /* Crashes on W98, NT4, W2K, XP, W2K3
+ * Our implementation also crashes and we should probably leave
+ * it like that.
+ */
+ count = -1;
+ count = pStr_GetPtrA(NULL, NULL, destsize);
+ trace("count : %d\n", count);
+ }
+
+ count = 0;
+ count = pStr_GetPtrA(source, NULL, 0);
+ ok (count == sourcelen, "Expected count to be %d, it was %d\n", sourcelen , count);
+
+ count = 0;
+ strcpy(dest, desttest);
+ count = pStr_GetPtrA(source, dest, 0);
+ ok (count == sourcelen, "Expected count to be %d, it was %d\n", sourcelen , count);
+ ok (!lstrcmp(dest, desttest), "Expected destination to not have changed\n");
+
+ count = 0;
+ count = pStr_GetPtrA(source, NULL, destsize);
+ ok (count == sourcelen, "Expected count to be %d, it was %d\n", sourcelen , count);
+
+ count = 0;
+ count = pStr_GetPtrA(source, dest, destsize);
+ ok (count == sourcelen, "Expected count to be %d, it was %d\n", sourcelen , count);
+ ok (!lstrcmp(source, dest), "Expected source and destination to be the same\n");
+
+ count = -1;
+ strcpy(dest, desttest);
+ count = pStr_GetPtrA(NULL, dest, destsize);
+ ok (count == 0, "Expected count to be 0, it was %d\n", count);
+ ok (dest[0] == '\0', "Expected destination to be cut-off and 0 terminated\n");
+
+ count = 0;
+ destsize = 15;
+ count = pStr_GetPtrA(source, dest, destsize);
+ ok (count == 15, "Expected count to be 15, it was %d\n", count);
+ ok (!memcmp(source, dest, 14), "Expected first part of source and destination to be the same\n");
+ ok (dest[14] == '\0', "Expected destination to be cut-off and 0 terminated\n");
+ }
+}
+
+static void test_Alloc(void)
+{
+ PCHAR p = pAlloc(0);
+ ok(p != NULL, "p=%p\n", p);
+ ok(pFree(p), "\n");
+ p = pAlloc(1);
+ ok(p != NULL, "\n");
+ *p = '\0';
+ expect(1, pGetSize(p));
+ p = pReAlloc(p, 2);
+ ok(p != NULL, "\n");
+ expect(2, pGetSize(p));
+ ok(pFree(p), "\n");
+ ok(pFree(NULL), "\n");
+ p = pReAlloc(NULL, 2);
+ ok(p != NULL, "\n");
+ ok(pFree(p), "\n");
+}
+
+START_TEST(misc)
+{
+ if(!InitFunctionPtrs())
+ return;
+
+ test_GetPtrAW();
+ test_Alloc();
+
+ FreeLibrary(hComctl32);
+}
* comctl32 month calendar unit tests
*
* Copyright (C) 2006 Vitaliy Margolen
+ * Copyright (C) 2007 Farshad Agah
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <stdarg.h>
-#include "windows.h"
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
#include "commctrl.h"
#include "wine/test.h"
+#include <assert.h>
+#include <windows.h>
+#include "msg.h"
-void test_monthcal(void)
+#define expect(expected, got) ok(expected == got, "Expected %d, got %d\n", expected, got);
+
+#define NUM_MSG_SEQUENCES 2
+#define PARENT_SEQ_INDEX 0
+#define MONTHCAL_SEQ_INDEX 1
+
+struct subclass_info
+{
+ WNDPROC oldproc;
+};
+
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+
+static const struct message create_parent_window_seq[] = {
+ { WM_GETMINMAXINFO, sent },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { WM_SHOWWINDOW, sent|wparam, 1 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_ACTIVATEAPP, sent|wparam, 1 },
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATE, sent|wparam, 1 },
+ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+ { WM_IME_NOTIFY, sent|defwinproc|optional },
+ { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+ /* Win9x adds SWP_NOZORDER below */
+ { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
+ { WM_NCCALCSIZE, sent|wparam|optional, 1 },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
+ { 0 }
+};
+
+static const struct message create_monthcal_control_seq[] = {
+ { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
+ { WM_QUERYUISTATE, sent },
+ { WM_GETFONT, sent },
+ { WM_PARENTNOTIFY, sent|wparam, WM_CREATE},
+ { 0 }
+};
+
+static const struct message create_monthcal_multi_sel_style_seq[] = {
+ { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
+ { WM_QUERYUISTATE, sent },
+ { WM_GETFONT, sent },
+ { 0 }
+};
+
+static const struct message monthcal_color_seq[] = {
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(0,0,0)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(255,255,255)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0},
+
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(0,0,0)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(255,255,255)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0},
+
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TEXT, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(0,0,0)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TEXT, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(255,255,255)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TEXT, 0},
+
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(0,0,0)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(255,255,255)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0},
+
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(0,0,0)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(255,255,255)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0},
+
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(0,0,0)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0},
+ { MCM_SETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(255,255,255)},
+ { MCM_GETCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0},
+ { 0 }
+};
+
+static const struct message monthcal_curr_date_seq[] = {
+ { MCM_SETCURSEL, sent|wparam, 0},
+ { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
+ { WM_ERASEBKGND, sent|lparam|defwinproc, 0},
+ { MCM_SETCURSEL, sent|wparam, 0},
+ { MCM_SETCURSEL, sent|wparam, 0},
+ { MCM_GETCURSEL, sent|wparam, 0},
+ { MCM_GETCURSEL, sent|wparam|lparam, 0, 0},
+ { 0 }
+};
+
+static const struct message monthcal_first_day_seq[] = {
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -5},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -4},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -3},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -2},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, -1},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 1},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 2},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 3},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 4},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 5},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 6},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 7},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 8},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 9},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 10},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+
+ { MCM_SETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 11},
+ { MCM_GETFIRSTDAYOFWEEK, sent|wparam|lparam, 0, 0},
+ { 0 }
+};
+
+static const struct message monthcal_unicode_seq[] = {
+ { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
+ { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0},
+ { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
+ { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
+ { MCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0},
+ { MCM_SETUNICODEFORMAT, sent|wparam|lparam, 1, 0},
+ { 0 }
+};
+
+static const struct message monthcal_hit_test_seq[] = {
+ { MCM_SETCURSEL, sent|wparam, 0},
+ { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_HITTEST, sent|wparam, 0},
+ { 0 }
+};
+
+static const struct message monthcal_todaylink_seq[] = {
+ { MCM_HITTEST, sent|wparam, 0},
+ { MCM_SETTODAY, sent|wparam, 0},
+ { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
+ { MCM_GETTODAY, sent|wparam, 0},
+ { WM_LBUTTONDOWN, sent|wparam|lparam, MK_LBUTTON, MAKELONG(70, 370)},
+ { WM_CAPTURECHANGED, sent|wparam|lparam|defwinproc, 0, 0},
+ { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
+ { MCM_GETCURSEL, sent|wparam, 0},
+ { 0 }
+};
+
+static const struct message monthcal_today_seq[] = {
+ { MCM_SETTODAY, sent|wparam, 0},
+ { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
+ { MCM_GETTODAY, sent|wparam, 0},
+ { MCM_SETTODAY, sent|wparam, 0},
+ { WM_PAINT, sent|wparam|lparam|defwinproc, 0, 0},
+ { MCM_GETTODAY, sent|wparam, 0},
+ { 0 }
+};
+
+static const struct message monthcal_scroll_seq[] = {
+ { MCM_SETMONTHDELTA, sent|wparam|lparam, 2, 0},
+ { MCM_SETMONTHDELTA, sent|wparam|lparam, 3, 0},
+ { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
+ { MCM_SETMONTHDELTA, sent|wparam|lparam, 12, 0},
+ { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
+ { MCM_SETMONTHDELTA, sent|wparam|lparam, 15, 0},
+ { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
+ { MCM_SETMONTHDELTA, sent|wparam|lparam, -5, 0},
+ { MCM_GETMONTHDELTA, sent|wparam|lparam, 0, 0},
+ { 0 }
+};
+
+static const struct message monthcal_monthrange_seq[] = {
+ { MCM_GETMONTHRANGE, sent|wparam, GMR_VISIBLE},
+ { MCM_GETMONTHRANGE, sent|wparam, GMR_DAYSTATE},
+ { 0 }
+};
+
+static const struct message monthcal_max_sel_day_seq[] = {
+ { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 5, 0},
+ { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
+ { MCM_SETMAXSELCOUNT, sent|wparam|lparam, 15, 0},
+ { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
+ { MCM_SETMAXSELCOUNT, sent|wparam|lparam, -1, 0},
+ { MCM_GETMAXSELCOUNT, sent|wparam|lparam, 0, 0},
+ { 0 }
+};
+
+/* expected message sequence for parent*/
+static const struct message destroy_monthcal_parent_msgs_seq[] = {
+ { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY},
+ { 0 }
+};
+
+/* expected message sequence for child*/
+static const struct message destroy_monthcal_child_msgs_seq[] = {
+ { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0},
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0},
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0},
+ { WM_DESTROY, sent|wparam|lparam, 0, 0},
+ { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
+ { 0 }
+};
+
+static const struct message destroy_monthcal_multi_sel_style_seq[] = {
+ { WM_DESTROY, sent|wparam|lparam, 0, 0},
+ { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
+ { 0 }
+};
+
+/* expected message sequence for parent window*/
+static const struct message destroy_parent_seq[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0},
+ { WM_WINDOWPOSCHANGED, sent|wparam, 0},
+ { WM_NCACTIVATE, sent|wparam|lparam, 0, 0},
+ { WM_ACTIVATE, sent|wparam|lparam, 0, 0},
+ { WM_ACTIVATEAPP, sent|wparam, 0},
+ { WM_KILLFOCUS, sent|wparam|lparam, 0, 0},
+ { WM_IME_SETCONTEXT, sent|wparam|optional, 0},
+ { WM_IME_NOTIFY, sent|wparam|lparam|defwinproc|optional, 1, 0},
+ { WM_DESTROY, sent|wparam|lparam, 0, 0},
+ { WM_NCDESTROY, sent|wparam|lparam, 0, 0},
+ { 0 }
+};
+
+static void test_monthcal(void)
{
HWND hwnd;
SYSTEMTIME st[2], st1[2];
st[1].wYear += 4;
ok(SendMessage(hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM)st), "Failed to set max limit\n");
ok(SendMessage(hwnd, MCM_GETRANGE, 0, (LPARAM)st1) == GDTR_MAX, "Only MAX limit should be set\n");
+
+ DestroyWindow(hwnd);
+}
+
+static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ /* do not log painting messages */
+ if (message != WM_PAINT &&
+ message != WM_ERASEBKGND &&
+ message != WM_NCPAINT &&
+ message != WM_NCHITTEST &&
+ message != WM_GETTEXT &&
+ message != WM_GETICON &&
+ message != WM_DEVICECHANGE)
+ {
+ trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, PARENT_SEQ_INDEX, &msg);
+ }
+
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static BOOL register_parent_wnd_class(void)
+{
+ WNDCLASSA cls;
+
+ cls.style = 0;
+ cls.lpfnWndProc = parent_wnd_proc;
+ cls.cbClsExtra = 0;
+ cls.cbWndExtra = 0;
+ cls.hInstance = GetModuleHandleA(NULL);
+ cls.hIcon = 0;
+ cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
+ cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+ cls.lpszMenuName = NULL;
+ cls.lpszClassName = "Month-Cal test parent class";
+ return RegisterClassA(&cls);
+}
+
+static HWND create_parent_window(void)
+{
+ HWND hwnd;
+
+ InitCommonControls();
+
+ /* flush message sequences, so we can check the new sequence by the end of function */
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ if (!register_parent_wnd_class())
+ return NULL;
+
+ hwnd = CreateWindowEx(0, "Month-Cal test parent class",
+ "Month-Cal test parent window",
+ WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
+ WS_MAXIMIZEBOX | WS_VISIBLE,
+ 0, 0, 500, 500,
+ GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
+
+ assert(hwnd);
+
+ /* check for message sequences */
+ ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_window_seq, "create parent window", TRUE);
+
+ return hwnd;
+}
+
+static LRESULT WINAPI monthcal_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ trace("monthcal: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, MONTHCAL_SEQ_INDEX, &msg);
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static HWND create_monthcal_control(DWORD style, HWND parent_window)
+{
+ struct subclass_info *info;
+ HWND hwnd;
+ static const INITCOMMONCONTROLSEX ic = {sizeof(INITCOMMONCONTROLSEX), ICC_DATE_CLASSES};
+
+ InitCommonControlsEx(&ic);
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ hwnd = CreateWindowEx(0,
+ MONTHCAL_CLASS,
+ "",
+ style,
+ 0, 0, 300, 400,
+ parent_window, NULL, GetModuleHandleA(NULL), NULL);
+
+ if (!hwnd)
+ {
+ HeapFree(GetProcessHeap(), 0, info);
+ return NULL;
+ }
+
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
+ (LONG_PTR)monthcal_subclass_proc);
+ SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
+
+ return hwnd;
+}
+
+
+/* Setter and Getters Tests */
+
+static void test_monthcal_color(HWND hwnd)
+{
+ int res, temp;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Setter and Getters for color*/
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(0,0,0));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
+ expect(RGB(0,0,0), temp);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_BACKGROUND, RGB(255,255,255));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_BACKGROUND, 0);
+ expect(RGB(255,255,255), temp);
+
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(0,0,0));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
+ expect(RGB(0,0,0), temp);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_MONTHBK, RGB(255,255,255));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_MONTHBK, 0);
+ expect(RGB(255,255,255), temp);
+
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(0,0,0));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
+ expect(RGB(0,0,0), temp);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TEXT, RGB(255,255,255));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TEXT, 0);
+ expect(RGB(255,255,255), temp);
+
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(0,0,0));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
+ expect(RGB(0,0,0), temp);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLEBK, RGB(255,255,255));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLEBK, 0);
+ expect(RGB(255,255,255), temp);
+
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(0,0,0));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
+ expect(RGB(0,0,0), temp);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TITLETEXT, RGB(255,255,255));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TITLETEXT, 0);
+ expect(RGB(255,255,255), temp);
+
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(0,0,0));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
+ expect(RGB(0,0,0), temp);
+ res = SendMessage(hwnd, MCM_SETCOLOR, MCSC_TRAILINGTEXT, RGB(255,255,255));
+ expect(temp, res);
+ temp = SendMessage(hwnd, MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0);
+ expect(RGB(255,255,255), temp);
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_color_seq, "monthcal color", FALSE);
+}
+
+static void test_monthcal_currDate(HWND hwnd)
+{
+ SYSTEMTIME st_original, st_new, st_test;
+ int res;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Setter and Getters for current date selected */
+ st_original.wYear = 2000;
+ st_original.wMonth = 11;
+ st_original.wDay = 28;
+ st_original.wHour = 11;
+ st_original.wMinute = 59;
+ st_original.wSecond = 30;
+ st_original.wMilliseconds = 0;
+ st_original.wDayOfWeek = 0;
+
+ st_new = st_test = st_original;
+
+ /* Should not validate the time */
+ res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
+ expect(1,res);
+
+ /* Overflow matters, check for wDay */
+ st_test.wDay += 4;
+ res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
+ expect(0,res);
+
+ /* correct wDay before checking for wMonth */
+ st_test.wDay -= 4;
+ expect(st_original.wDay, st_test.wDay);
+
+ /* Overflow matters, check for wMonth */
+ st_test.wMonth += 4;
+ res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st_test);
+ expect(0,res);
+
+ /* checking if gets the information right, modify st_new */
+ st_new.wYear += 4;
+ st_new.wMonth += 4;
+ st_new.wDay += 4;
+ st_new.wHour += 4;
+ st_new.wMinute += 4;
+ st_new.wSecond += 4;
+
+ res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new);
+ expect(1, res);
+
+ /* st_new change to st_origin, above settings with overflow */
+ /* should not change the current settings */
+ expect(st_original.wYear, st_new.wYear);
+ expect(st_original.wMonth, st_new.wMonth);
+ expect(st_original.wDay, st_new.wDay);
+ expect(st_original.wHour, st_new.wHour);
+ expect(st_original.wMinute, st_new.wMinute);
+ expect(st_original.wSecond, st_new.wSecond);
+
+ /* lparam cannot be NULL */
+ res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM) NULL);
+ expect(0, res);
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_curr_date_seq, "monthcal currDate", TRUE);
}
+static void test_monthcal_firstDay(HWND hwnd)
+{
+ int res, fday, i, prev;
+ TCHAR b[128];
+ LCID lcid = LOCALE_USER_DEFAULT;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Setter and Getters for first day of week */
+ /* check for locale first day */
+ if(GetLocaleInfo(lcid, LOCALE_IFIRSTDAYOFWEEK, b, 128)){
+ fday = atoi(b);
+ res = SendMessage(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0);
+ expect(fday, res);
+ prev = fday;
+
+ /* checking for the values that actually will be stored as */
+ /* current first day when we set a new value */
+ for (i = -5; i < 12; i++){
+ res = SendMessage(hwnd, MCM_SETFIRSTDAYOFWEEK, 0, (LPARAM) i);
+ expect(prev, res);
+ res = SendMessage(hwnd, MCM_GETFIRSTDAYOFWEEK, 0, 0);
+ prev = res;
+
+ if (i == -1){
+ expect(MAKELONG(fday, FALSE), res);
+ }else if (i >= 7){
+ expect(MAKELONG(fday, TRUE), res);
+ }else{
+ expect(MAKELONG(i, TRUE), res);
+ }
+ }
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_first_day_seq, "monthcal firstDay", FALSE);
+
+ }else{
+ skip("Cannot retrieve first day of the week\n");
+ }
+
+}
+
+static void test_monthcal_unicode(HWND hwnd)
+{
+ int res, temp;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Setter and Getters for Unicode format */
+
+ /* getting the current settings */
+ temp = SendMessage(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
+
+ /* setting to 1, should return previous settings */
+ res = SendMessage(hwnd, MCM_SETUNICODEFORMAT, 1, 0);
+ expect(temp, res);
+
+ /* current setting is 1, so, should return 1 */
+ res = SendMessage(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
+ todo_wine {expect(1, res);}
+
+ /* setting to 0, should return previous settings */
+ res = SendMessage(hwnd, MCM_SETUNICODEFORMAT, 0, 0);
+ todo_wine {expect(1, res);}
+
+ /* current setting is 0, so, it should return 0 */
+ res = SendMessage(hwnd, MCM_GETUNICODEFORMAT, 0, 0);
+ expect(0, res);
+
+ /* should return previous settings */
+ res = SendMessage(hwnd, MCM_SETUNICODEFORMAT, 1, 0);
+ expect(0, res);
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_unicode_seq, "monthcal unicode", FALSE);
+}
+
+static void test_monthcal_HitTest(HWND hwnd)
+{
+ MCHITTESTINFO mchit;
+ int res;
+ SYSTEMTIME st;
+
+ memset(&mchit, 0, sizeof(MCHITTESTINFO));
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ st.wYear = 2007;
+ st.wMonth = 4;
+ st.wDay = 11;
+ st.wHour = 1;
+ st.wMinute = 0;
+ st.wSecond = 0;
+ st.wMilliseconds = 0;
+ st.wDayOfWeek = 0;
+
+ res = SendMessage(hwnd, MCM_SETCURSEL, 0, (LPARAM)&st);
+ expect(1,res);
+
+ /* (0, 0) is the top left of the control and should not be active */
+ mchit.cbSize = sizeof(MCHITTESTINFO);
+ mchit.pt.x = 0;
+ mchit.pt.y = 0;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(0, mchit.pt.x);
+ expect(0, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_NOWHERE, res);}
+
+ /* (300, 400) is the bottom right of the control and should not be active */
+ mchit.pt.x = 300;
+ mchit.pt.y = 400;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(300, mchit.pt.x);
+ expect(400, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_NOWHERE, res);}
+
+ /* (500, 500) is completely out of the control and should not be active */
+ mchit.pt.x = 500;
+ mchit.pt.y = 500;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(500, mchit.pt.x);
+ expect(500, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_NOWHERE, res);}
+
+ /* (120, 180) is in active area - calendar background */
+ mchit.pt.x = 120;
+ mchit.pt.y = 180;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(120, mchit.pt.x);
+ expect(180, mchit.pt.y);
+ expect(mchit.uHit, res);
+ expect(MCHT_CALENDARBK, res);
+
+ /* (50, 40) is in active area - previous month button */
+ mchit.pt.x = 50;
+ mchit.pt.y = 40;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(50, mchit.pt.x);
+ expect(40, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TITLEBTNPREV, res);}
+
+ /* (90, 40) is in active area - background section of the title */
+ mchit.pt.x = 90;
+ mchit.pt.y = 40;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(90, mchit.pt.x);
+ expect(40, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TITLE, res);}
+
+ /* (140, 40) is in active area - month section of the title */
+ mchit.pt.x = 140;
+ mchit.pt.y = 40;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(140, mchit.pt.x);
+ expect(40, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TITLEMONTH, res);}
+
+ /* (250, 40) is in active area - next month button */
+ mchit.pt.x = 250;
+ mchit.pt.y = 40;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(250, mchit.pt.x);
+ expect(40, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TITLEBTNNEXT, res);}
+
+ /* (70, 70) is in active area - day of the week */
+ mchit.pt.x = 70;
+ mchit.pt.y = 70;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(70, mchit.pt.x);
+ expect(70, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_CALENDARDAY, res);}
+
+ /* (70, 90) is in active area - date from prev month */
+ mchit.pt.x = 70;
+ mchit.pt.y = 90;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(70, mchit.pt.x);
+ expect(90, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_CALENDARDATEPREV, res);}
+
+#if 0
+ /* (125, 115) is in active area - date from this month */
+ mchit.pt.x = 125;
+ mchit.pt.y = 115;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(125, mchit.pt.x);
+ expect(115, mchit.pt.y);
+ expect(mchit.uHit, res);
+ expect(MCHT_CALENDARDATE, res);
+#endif
+
+ /* (80, 220) is in active area - background section of the title */
+ mchit.pt.x = 80;
+ mchit.pt.y = 220;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(80, mchit.pt.x);
+ expect(220, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TITLEBK, res);}
+
+ /* (140, 215) is in active area - month section of the title */
+ mchit.pt.x = 140;
+ mchit.pt.y = 215;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(140, mchit.pt.x);
+ expect(215, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TITLEMONTH, res);}
+
+ /* (170, 215) is in active area - year section of the title */
+ mchit.pt.x = 170;
+ mchit.pt.y = 215;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(170, mchit.pt.x);
+ expect(215, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TITLEYEAR, res);}
+
+ /* (150, 260) is in active area - date from this month */
+ mchit.pt.x = 150;
+ mchit.pt.y = 260;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(150, mchit.pt.x);
+ expect(260, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_CALENDARDATE, res);}
+
+ /* (150, 350) is in active area - date from next month */
+ mchit.pt.x = 150;
+ mchit.pt.y = 350;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(150, mchit.pt.x);
+ expect(350, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_CALENDARDATENEXT, res);}
+
+ /* (150, 370) is in active area - today link */
+ mchit.pt.x = 150;
+ mchit.pt.y = 370;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(150, mchit.pt.x);
+ expect(370, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TODAYLINK, res);}
+
+ /* (70, 370) is in active area - today link */
+ mchit.pt.x = 70;
+ mchit.pt.y = 370;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(70, mchit.pt.x);
+ expect(370, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TODAYLINK, res);}
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_hit_test_seq, "monthcal hit test", TRUE);
+}
+
+static void test_monthcal_todaylink(HWND hwnd)
+{
+ MCHITTESTINFO mchit;
+ SYSTEMTIME st_test, st_new;
+ BOOL error = FALSE;
+ int res;
+
+ memset(&mchit, 0, sizeof(MCHITTESTINFO));
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* (70, 370) is in active area - today link */
+ mchit.cbSize = sizeof(MCHITTESTINFO);
+ mchit.pt.x = 70;
+ mchit.pt.y = 370;
+ res = SendMessage(hwnd, MCM_HITTEST, 0, (LPARAM) & mchit);
+ expect(70, mchit.pt.x);
+ expect(370, mchit.pt.y);
+ expect(mchit.uHit, res);
+ todo_wine {expect(MCHT_TODAYLINK, res);}
+ if (70 != mchit.pt.x || 370 != mchit.pt.y || mchit.uHit != res
+ || MCHT_TODAYLINK != res)
+ error = TRUE;
+
+ st_test.wDay = 1;
+ st_test.wMonth = 1;
+ st_test.wYear = 2005;
+ memset(&st_new, 0, sizeof(SYSTEMTIME));
+
+ SendMessage(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
+
+ res = SendMessage(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
+ expect(1, res);
+ expect(1, st_new.wDay);
+ expect(1, st_new.wMonth);
+ expect(2005, st_new.wYear);
+ if (1 != res || 1 != st_new.wDay || 1 != st_new.wMonth
+ || 2005 != st_new.wYear)
+ error = TRUE;
+
+ if (error) {
+ skip("cannot perform today link test\n");
+ return;
+ }
+
+ res = SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELONG(70, 370));
+ expect(0, res);
+
+ memset(&st_new, 0, sizeof(SYSTEMTIME));
+ res = SendMessage(hwnd, MCM_GETCURSEL, 0, (LPARAM)&st_new);
+ expect(1, res);
+ expect(1, st_new.wDay);
+ expect(1, st_new.wMonth);
+ expect(2005, st_new.wYear);
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_todaylink_seq, "monthcal hit test", TRUE);
+}
+
+static void test_monthcal_today(HWND hwnd)
+{
+ SYSTEMTIME st_test, st_new;
+ int res;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Setter and Getters for "today" information */
+
+ /* check for overflow, should be ok */
+ st_test.wDay = 38;
+ st_test.wMonth = 38;
+
+ st_new.wDay = 27;
+ st_new.wMonth = 27;
+
+ SendMessage(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
+
+ res = SendMessage(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
+ expect(1, res);
+
+ /* st_test should not change */
+ expect(38, st_test.wDay);
+ expect(38, st_test.wMonth);
+
+ /* st_new should change, overflow does not matter */
+ expect(38, st_new.wDay);
+ expect(38, st_new.wMonth);
+
+ /* check for zero, should be ok*/
+ st_test.wDay = 0;
+ st_test.wMonth = 0;
+
+ SendMessage(hwnd, MCM_SETTODAY, 0, (LPARAM)&st_test);
+
+ res = SendMessage(hwnd, MCM_GETTODAY, 0, (LPARAM)&st_new);
+ expect(1, res);
+
+ /* st_test should not change */
+ expect(0, st_test.wDay);
+ expect(0, st_test.wMonth);
+
+ /* st_new should change to zero*/
+ expect(0, st_new.wDay);
+ expect(0, st_new.wMonth);
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_today_seq, "monthcal today", TRUE);
+}
+
+static void test_monthcal_scroll(HWND hwnd)
+{
+ int res;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Setter and Getters for scroll rate */
+ res = SendMessage(hwnd, MCM_SETMONTHDELTA, 2, 0);
+ expect(0, res);
+
+ res = SendMessage(hwnd, MCM_SETMONTHDELTA, 3, 0);
+ expect(2, res);
+ res = SendMessage(hwnd, MCM_GETMONTHDELTA, 0, 0);
+ expect(3, res);
+
+ res = SendMessage(hwnd, MCM_SETMONTHDELTA, 12, 0);
+ expect(3, res);
+ res = SendMessage(hwnd, MCM_GETMONTHDELTA, 0, 0);
+ expect(12, res);
+
+ res = SendMessage(hwnd, MCM_SETMONTHDELTA, 15, 0);
+ expect(12, res);
+ res = SendMessage(hwnd, MCM_GETMONTHDELTA, 0, 0);
+ expect(15, res);
+
+ res = SendMessage(hwnd, MCM_SETMONTHDELTA, -5, 0);
+ expect(15, res);
+ res = SendMessage(hwnd, MCM_GETMONTHDELTA, 0, 0);
+ expect(-5, res);
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_scroll_seq, "monthcal scroll", FALSE);
+}
+
+static void test_monthcal_monthrange(HWND hwnd)
+{
+ int res;
+ SYSTEMTIME st_visible[2], st_daystate[2];
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ st_visible[0].wYear = 0;
+ st_visible[0].wMonth = 0;
+ st_visible[0].wDay = 0;
+ st_daystate[1] = st_daystate[0] = st_visible[1] = st_visible[0];
+
+ res = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_VISIBLE, (LPARAM)st_visible);
+ todo_wine {
+ expect(2, res);
+ expect(2000, st_visible[0].wYear);
+ expect(11, st_visible[0].wMonth);
+ expect(1, st_visible[0].wDay);
+ expect(2000, st_visible[1].wYear);
+ expect(12, st_visible[1].wMonth);
+ expect(31, st_visible[1].wDay);
+ }
+ res = SendMessage(hwnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, (LPARAM)st_daystate);
+ todo_wine {
+ expect(4, res);
+ expect(2000, st_daystate[0].wYear);
+ expect(10, st_daystate[0].wMonth);
+ expect(29, st_daystate[0].wDay);
+ expect(2001, st_daystate[1].wYear);
+ expect(1, st_daystate[1].wMonth);
+ expect(6, st_daystate[1].wDay);
+ }
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_monthrange_seq, "monthcal monthrange", FALSE);
+}
+
+static void test_monthcal_MaxSelDay(HWND hwnd)
+{
+ int res;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Setter and Getters for max selected days */
+ res = SendMessage(hwnd, MCM_SETMAXSELCOUNT, 5, 0);
+ expect(1, res);
+ res = SendMessage(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
+ expect(5, res);
+
+ res = SendMessage(hwnd, MCM_SETMAXSELCOUNT, 15, 0);
+ expect(1, res);
+ res = SendMessage(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
+ expect(15, res);
+
+ res = SendMessage(hwnd, MCM_SETMAXSELCOUNT, -1, 0);
+ todo_wine {expect(0, res);}
+ res = SendMessage(hwnd, MCM_GETMAXSELCOUNT, 0, 0);
+ todo_wine {expect(15, res);}
+
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, monthcal_max_sel_day_seq, "monthcal MaxSelDay", FALSE);
+}
+
+
START_TEST(monthcal)
{
+ HWND hwnd, parent_wnd;
test_monthcal();
+
+ init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ parent_wnd = create_parent_window();
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hwnd = create_monthcal_control(WS_CHILD | WS_BORDER | WS_VISIBLE, parent_wnd);
+ assert(hwnd);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_control_seq, "create monthcal control", TRUE);
+
+ SendMessage(hwnd, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
+
+ test_monthcal_color(hwnd);
+ test_monthcal_currDate(hwnd);
+ test_monthcal_firstDay(hwnd);
+ test_monthcal_unicode(hwnd);
+ test_monthcal_today(hwnd);
+ test_monthcal_scroll(hwnd);
+ test_monthcal_monthrange(hwnd);
+ test_monthcal_HitTest(hwnd);
+ test_monthcal_todaylink(hwnd);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ DestroyWindow(hwnd);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, destroy_monthcal_parent_msgs_seq, "Destroy monthcal (parent msg)", FALSE);
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_child_msgs_seq, "Destroy monthcal (child msg)", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ hwnd = create_monthcal_control(MCS_MULTISELECT, parent_wnd);
+ assert(hwnd);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, create_monthcal_multi_sel_style_seq, "create monthcal (multi sel style)", TRUE);
+
+ test_monthcal_MaxSelDay(hwnd);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ DestroyWindow(hwnd);
+ ok_sequence(sequences, MONTHCAL_SEQ_INDEX, destroy_monthcal_multi_sel_style_seq, "Destroy monthcal (multi sel style)", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ DestroyWindow(parent_wnd);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, destroy_parent_seq, "Destroy parent window", FALSE);
}
buff[0] = '\0';
ret = RegQueryValueExA(hKey, "MRUList", NULL, &type, (LPBYTE)buff, &size);
- ok(!ret && buff[0], "Checking MRU: got %ld from RegQueryValueExW\n", ret);
+ ok(!ret && buff[0], "Checking MRU: got %d from RegQueryValueExW\n", ret);
if(ret || !buff[0]) return;
ok(strcmp(buff, mrulist) == 0, "Checking MRU: Expected list %s, got %s\n",
buff[0] = '\0';
ret = RegQueryValueExA(hKey, name, NULL, &type, (LPBYTE)buff, &size);
ok(!ret && buff[0],
- "Checking MRU item %d ('%c'): got %ld from RegQueryValueExW\n",
+ "Checking MRU item %d ('%c'): got %d from RegQueryValueExW\n",
i, mrulist[i], ret);
if(ret || !buff[0]) return;
ok(!strcmp(buff, items[mrulist[i]-'a']),
if (!pCreateMRUListA || !pFreeMRUList || !pAddMRUStringA)
return;
-#if 0 /* Create (NULL) - crashes native */
+ if (0)
+ {
+ /* Create (NULL) - crashes native */
hMRU = pCreateMRUListA(NULL);
-#endif
+ }
/* Create (size too small) */
mruA.cbSize = sizeof(mruA) - 2;
- hMRU = create_mruA(NULL, MRUF_STRING_LIST, cmp_mru_strA);
+ hMRU = create_mruA(NULL, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
ok (!hMRU && !GetLastError(),
- "CreateMRUListA(too small) expected NULL,0 got %p,%ld\n",
+ "CreateMRUListA(too small) expected NULL,0 got %p,%d\n",
hMRU, GetLastError());
mruA.cbSize = sizeof(mruA);
/* Create (size too big) */
mruA.cbSize = sizeof(mruA) + 2;
- hMRU = create_mruA(NULL, MRUF_STRING_LIST, cmp_mru_strA);
+ hMRU = create_mruA(NULL, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
ok (!hMRU && !GetLastError(),
- "CreateMRUListA(too big) expected NULL,0 got %p,%ld\n",
+ "CreateMRUListA(too big) expected NULL,0 got %p,%d\n",
hMRU, GetLastError());
mruA.cbSize = sizeof(mruA);
/* Create (NULL hKey) */
- hMRU = create_mruA(NULL, MRUF_STRING_LIST, cmp_mru_strA);
+ hMRU = create_mruA(NULL, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
ok (!hMRU && !GetLastError(),
- "CreateMRUListA(NULL key) expected NULL,0 got %p,%ld\n",
+ "CreateMRUListA(NULL key) expected NULL,0 got %p,%d\n",
hMRU, GetLastError());
/* Create (NULL name) */
mruA.lpszSubKey = NULL;
- hMRU = create_mruA(NULL, MRUF_STRING_LIST, cmp_mru_strA);
+ hMRU = create_mruA(NULL, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
ok (!hMRU && !GetLastError(),
- "CreateMRUListA(NULL name) expected NULL,0 got %p,%ld\n",
+ "CreateMRUListA(NULL name) expected NULL,0 got %p,%d\n",
hMRU, GetLastError());
mruA.lpszSubKey = REG_TEST_SUBKEYA;
"Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
if (!hKey)
return;
- hMRU = create_mruA(hKey, MRUF_STRING_LIST, cmp_mru_strA);
+ hMRU = create_mruA(hKey, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
ok(hMRU && !GetLastError(),
- "CreateMRUListA(string) expected non-NULL,0 got %p,%ld\n",
+ "CreateMRUListA(string) expected non-NULL,0 got %p,%d\n",
hMRU, GetLastError());
if (hMRU)
SetLastError(0);
iRet = pAddMRUStringA(NULL, checks[0]);
ok(iRet == -1 && !GetLastError(),
- "AddMRUStringA(NULL list) expected -1,0 got %d,%ld\n",
+ "AddMRUStringA(NULL list) expected -1,0 got %d,%d\n",
iRet, GetLastError());
/* Add (NULL string) */
-#if 0
+ if (0)
+ {
/* Some native versions crash when passed NULL or fail to SetLastError() */
SetLastError(0);
iRet = pAddMRUStringA(hMRU, NULL);
ok(iRet == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
- "AddMRUStringA(NULL str) expected 0,ERROR_INVALID_PARAMETER got %d,%ld\n",
+ "AddMRUStringA(NULL str) expected 0,ERROR_INVALID_PARAMETER got %d,%d\n",
iRet, GetLastError());
-#endif
+ }
/* Add 3 strings. Check the registry is correct after each add */
SetLastError(0);
iRet = pAddMRUStringA(hMRU, checks[0]);
ok(iRet == 0 && !GetLastError(),
- "AddMRUStringA(1) expected 0,0 got %d,%ld\n",
+ "AddMRUStringA(1) expected 0,0 got %d,%d\n",
iRet, GetLastError());
check_reg_entries("a", checks);
SetLastError(0);
iRet = pAddMRUStringA(hMRU, checks[1]);
ok(iRet == 1 && !GetLastError(),
- "AddMRUStringA(2) expected 1,0 got %d,%ld\n",
+ "AddMRUStringA(2) expected 1,0 got %d,%d\n",
iRet, GetLastError());
check_reg_entries("ba", checks);
SetLastError(0);
iRet = pAddMRUStringA(hMRU, checks[2]);
ok(iRet == 2 && !GetLastError(),
- "AddMRUStringA(2) expected 2,0 got %d,%ld\n",
+ "AddMRUStringA(2) expected 2,0 got %d,%d\n",
iRet, GetLastError());
check_reg_entries("cba", checks);
SetLastError(0);
iRet = pAddMRUStringA(hMRU, checks[1]);
ok(iRet == 1 && !GetLastError(),
- "AddMRUStringA(re-add 1) expected 1,0 got %d,%ld\n",
+ "AddMRUStringA(re-add 1) expected 1,0 got %d,%d\n",
iRet, GetLastError());
check_reg_entries("bca", checks);
SetLastError(0);
iRet = pAddMRUStringA(hMRU, checks[3]);
ok(iRet == 0 && !GetLastError(),
- "AddMRUStringA(add new) expected 0,0 got %d,%ld\n",
+ "AddMRUStringA(add new) expected 0,0 got %d,%d\n",
iRet, GetLastError());
checks[0] = checks[3];
check_reg_entries("abc", checks);
START_TEST(mru)
{
hComctl32 = GetModuleHandleA("comctl32.dll");
- if (!hComctl32)
- return;
delete_reg_entries();
if (!create_reg_entries())
--- /dev/null
+/* Message Sequence Testing Code
+ *
+ * Copyright (C) 2007 James Hawkins
+ * Copyright (C) 2007 Lei Zhang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "msg.h"
+
+void add_message(struct msg_sequence **seq, int sequence_index,
+ const struct message *msg)
+{
+ struct msg_sequence *msg_seq = seq[sequence_index];
+
+ if (!msg_seq->sequence)
+ {
+ msg_seq->size = 10;
+ msg_seq->sequence = HeapAlloc(GetProcessHeap(), 0,
+ msg_seq->size * sizeof (struct message));
+ }
+
+ if (msg_seq->count == msg_seq->size)
+ {
+ msg_seq->size *= 2;
+ msg_seq->sequence = HeapReAlloc(GetProcessHeap(), 0,
+ msg_seq->sequence,
+ msg_seq->size * sizeof (struct message));
+ }
+
+ assert(msg_seq->sequence);
+
+ msg_seq->sequence[msg_seq->count].message = msg->message;
+ msg_seq->sequence[msg_seq->count].flags = msg->flags;
+ msg_seq->sequence[msg_seq->count].wParam = msg->wParam;
+ msg_seq->sequence[msg_seq->count].lParam = msg->lParam;
+ msg_seq->sequence[msg_seq->count].id = msg->id;
+
+ msg_seq->count++;
+}
+
+void flush_sequence(struct msg_sequence **seg, int sequence_index)
+{
+ struct msg_sequence *msg_seq = seg[sequence_index];
+ HeapFree(GetProcessHeap(), 0, msg_seq->sequence);
+ msg_seq->sequence = NULL;
+ msg_seq->count = msg_seq->size = 0;
+}
+
+void flush_sequences(struct msg_sequence **seq, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ flush_sequence(seq, i);
+}
+
+void ok_sequence_(struct msg_sequence **seq, int sequence_index,
+ const struct message *expected, const char *context, int todo,
+ const char *file, int line)
+{
+ struct msg_sequence *msg_seq = seq[sequence_index];
+ static const struct message end_of_sequence = {0, 0, 0, 0};
+ const struct message *actual, *sequence;
+ int failcount = 0;
+
+ add_message(seq, sequence_index, &end_of_sequence);
+
+ sequence = msg_seq->sequence;
+ actual = sequence;
+
+ while (expected->message && actual->message)
+ {
+ trace_( file, line)("expected %04x - actual %04x\n", expected->message, actual->message);
+
+ if (expected->message == actual->message)
+ {
+ if (expected->flags & wparam)
+ {
+ if (expected->wParam != actual->wParam && todo)
+ {
+ todo_wine
+ {
+ failcount++;
+ ok_(file, line) (FALSE,
+ "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
+ context, expected->message, expected->wParam, actual->wParam);
+ }
+ }
+ else
+ {
+ ok_(file, line) (expected->wParam == actual->wParam,
+ "%s: in msg 0x%04x expecting wParam 0x%lx got 0x%lx\n",
+ context, expected->message, expected->wParam, actual->wParam);
+ }
+ }
+
+ if (expected->flags & lparam)
+ {
+ if (expected->lParam != actual->lParam && todo)
+ {
+ todo_wine
+ {
+ failcount++;
+ ok_(file, line) (FALSE,
+ "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
+ context, expected->message, expected->lParam, actual->lParam);
+ }
+ }
+ else
+ {
+ ok_(file, line) (expected->lParam == actual->lParam,
+ "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
+ context, expected->message, expected->lParam, actual->lParam);
+ }
+ }
+
+ if (expected->flags & id)
+ {
+ if (expected->id != actual->id && todo)
+ {
+ todo_wine
+ {
+ failcount++;
+ ok_(file, line) (FALSE,
+ "%s: in msg 0x%04x expecting id 0x%x got 0x%x\n",
+ context, expected->message, expected->id, actual->id);
+ }
+ }
+ else
+ {
+ ok_(file, line) (expected->id == actual->id,
+ "%s: in msg 0x%04x expecting id 0x%x got 0x%x\n",
+ context, expected->message, expected->id, actual->id);
+ }
+ }
+
+ if ((expected->flags & defwinproc) != (actual->flags & defwinproc) && todo)
+ {
+ todo_wine
+ {
+ failcount++;
+ ok_(file, line) (FALSE,
+ "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
+ context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
+ }
+ }
+ else
+ {
+ ok_(file, line) ((expected->flags & defwinproc) == (actual->flags & defwinproc),
+ "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
+ context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
+ }
+
+ ok_(file, line) ((expected->flags & beginpaint) == (actual->flags & beginpaint),
+ "%s: the msg 0x%04x should %shave been sent by BeginPaint\n",
+ context, expected->message, (expected->flags & beginpaint) ? "" : "NOT ");
+ ok_(file, line) ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
+ "%s: the msg 0x%04x should have been %s\n",
+ context, expected->message, (expected->flags & posted) ? "posted" : "sent");
+ ok_(file, line) ((expected->flags & parent) == (actual->flags & parent),
+ "%s: the msg 0x%04x was expected in %s\n",
+ context, expected->message, (expected->flags & parent) ? "parent" : "child");
+ ok_(file, line) ((expected->flags & hook) == (actual->flags & hook),
+ "%s: the msg 0x%04x should have been sent by a hook\n",
+ context, expected->message);
+ ok_(file, line) ((expected->flags & winevent_hook) == (actual->flags & winevent_hook),
+ "%s: the msg 0x%04x should have been sent by a winevent hook\n",
+ context, expected->message);
+ expected++;
+ actual++;
+ }
+ else if (expected->flags & optional)
+ expected++;
+ else if (todo)
+ {
+ failcount++;
+ todo_wine
+ {
+ ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
+ context, expected->message, actual->message);
+ }
+
+ flush_sequence(seq, sequence_index);
+ return;
+ }
+ else
+ {
+ ok_(file, line) (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
+ context, expected->message, actual->message);
+ expected++;
+ actual++;
+ }
+ }
+
+ /* skip all optional trailing messages */
+ while (expected->message && ((expected->flags & optional)))
+ expected++;
+
+ if (todo)
+ {
+ todo_wine
+ {
+ if (expected->message || actual->message)
+ {
+ failcount++;
+ ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
+ context, expected->message, actual->message);
+ }
+ }
+ }
+ else if (expected->message || actual->message)
+ {
+ ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
+ context, expected->message, actual->message);
+ }
+
+ if(todo && !failcount) /* succeeded yet marked todo */
+ {
+ todo_wine
+ {
+ ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
+ }
+ }
+
+ flush_sequence(seq, sequence_index);
+}
+
+void init_msg_sequences(struct msg_sequence **seq, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ seq[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct msg_sequence));
+}
+
+START_TEST(msg)
+{
+}
--- /dev/null
+/* Message Sequence Testing Code
+ *
+ * Copyright (C) 2007 James Hawkins
+ * Copyright (C) 2007 Lei Zhang
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <assert.h>
+#include <windows.h>
+#include "wine/test.h"
+
+/* undocumented SWP flags - from SDK 3.1 */
+#define SWP_NOCLIENTSIZE 0x0800
+#define SWP_NOCLIENTMOVE 0x1000
+
+typedef enum
+{
+ sent = 0x1,
+ posted = 0x2,
+ parent = 0x4,
+ wparam = 0x8,
+ lparam = 0x10,
+ defwinproc = 0x20,
+ beginpaint = 0x40,
+ optional = 0x80,
+ hook = 0x100,
+ winevent_hook =0x200,
+ id = 0x400
+} msg_flags_t;
+
+struct message
+{
+ UINT message; /* the WM_* code */
+ msg_flags_t flags; /* message props */
+ WPARAM wParam; /* expected value of wParam */
+ LPARAM lParam; /* expected value of lParam */
+ UINT id; /* id of the window */
+};
+
+struct msg_sequence
+{
+ int count;
+ int size;
+ struct message *sequence;
+};
+
+void add_message(struct msg_sequence **seq, int sequence_index,
+ const struct message *msg);
+void flush_sequence(struct msg_sequence **seg, int sequence_index);
+void flush_sequences(struct msg_sequence **seq, int n);
+
+#define ok_sequence(seq, index, exp, contx, todo) \
+ ok_sequence_(seq, index, (exp), (contx), (todo), __FILE__, __LINE__)
+
+
+void ok_sequence_(struct msg_sequence **seq, int sequence_index,
+ const struct message *expected, const char *context, int todo,
+ const char *file, int line);
+
+void init_msg_sequences(struct msg_sequence **seq, int n);
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
-#include "commctrl.h"
+#include "commctrl.h"
#include "wine/test.h"
-HWND hProgressParentWnd, hProgressWnd;
+static HWND hProgressParentWnd, hProgressWnd;
static const char progressTestClass[] = "ProgressBarTestClass";
-LRESULT CALLBACK ProgressTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+/* try to make sure pending X events have been processed before continuing */
+static void flush_events(void)
+{
+ MSG msg;
+ int diff = 100;
+ DWORD time = GetTickCount() + diff;
+
+ while (diff > 0)
+ {
+ if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min(10,diff), QS_ALLINPUT ) == WAIT_TIMEOUT) break;
+ while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
+ diff = time - GetTickCount();
+ }
+}
+
+static LRESULT CALLBACK ProgressTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
-
+
default:
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
-
+
return 0L;
}
static BOOL erased;
static RECT last_paint_rect;
-LRESULT CALLBACK ProgressSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+static LRESULT CALLBACK ProgressSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_PAINT)
{
static void update_window(HWND hWnd)
{
UpdateWindow(hWnd);
- ok(!GetUpdateRect(hWnd, NULL, FALSE), "GetUpdateRect must return zero after UpdateWindow\n");
+ ok(!GetUpdateRect(hWnd, NULL, FALSE), "GetUpdateRect must return zero after UpdateWindow\n");
}
WNDCLASSA wc;
INITCOMMONCONTROLSEX icex;
RECT rect;
-
+
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_PROGRESS_CLASS;
InitCommonControlsEx(&icex);
-
+
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandleA(NULL);
wc.hIcon = NULL;
- wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW));
+ wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = progressTestClass;
wc.lpfnWndProc = ProgressTestWndProc;
RegisterClassA(&wc);
-
+
rect.left = 0;
rect.top = 0;
rect.right = 400;
rect.bottom = 20;
assert(AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE));
-
+
hProgressParentWnd = CreateWindowExA(0, progressTestClass, "Progress Bar Test", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, GetModuleHandleA(NULL), 0);
assert(hProgressParentWnd != NULL);
0, 0, rect.right, rect.bottom, hProgressParentWnd, NULL, GetModuleHandleA(NULL), 0);
assert(hProgressWnd != NULL);
progress_wndproc = (WNDPROC)SetWindowLongPtr(hProgressWnd, GWLP_WNDPROC, (LPARAM)ProgressSubclassProc);
-
+
ShowWindow(hProgressParentWnd, SW_SHOWNORMAL);
ok(GetUpdateRect(hProgressParentWnd, NULL, FALSE), "GetUpdateRect: There should be a region that needs to be updated\n");
- update_window(hProgressParentWnd);
+ flush_events();
+ update_window(hProgressParentWnd);
}
static void cleanup(void)
{
MSG msg;
-
+
PostMessageA(hProgressParentWnd, WM_CLOSE, 0, 0);
while (GetMessageA(&msg,0,0,0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
-
+
UnregisterClassA(progressTestClass, GetModuleHandleA(NULL));
}
/* PBM_SETPOS */
ok(SendMessageA(hProgressWnd, PBM_SETPOS, 50, 0) == 10, "PBM_SETPOS must return the previous position\n");
ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_SETPOS: The progress bar should be redrawn immediately\n");
-
+
/* PBM_DELTAPOS */
ok(SendMessageA(hProgressWnd, PBM_DELTAPOS, 15, 0) == 50, "PBM_DELTAPOS must return the previous position\n");
ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_DELTAPOS: The progress bar should be redrawn immediately\n");
-
+
/* PBM_SETPOS */
ok(SendMessageA(hProgressWnd, PBM_SETPOS, 80, 0) == 65, "PBM_SETPOS must return the previous position\n");
ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_SETPOS: The progress bar should be redrawn immediately\n");
-
+
/* PBM_STEPIT */
ok(SendMessageA(hProgressWnd, PBM_STEPIT, 0, 0) == 80, "PBM_STEPIT must return the previous position\n");
ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_STEPIT: The progress bar should be redrawn immediately\n");
ok((UINT)SendMessageA(hProgressWnd, PBM_GETPOS, 0, 0) == 100, "PBM_GETPOS returned a wrong position\n");
-
+
/* PBM_SETRANGE and PBM_SETRANGE32:
Usually the progress bar doesn't repaint itself immediately. If the
position is not in the new range, it does.
SendMessage(hProgressWnd, PBM_SETPOS, 10, 0);
GetClientRect(hProgressWnd, &client_rect);
ok(EqualRect(&last_paint_rect, &client_rect),
- "last_paint_rect was { %ld, %ld, %ld, %ld } instead of { %ld, %ld, %ld, %ld }\n",
+ "last_paint_rect was { %d, %d, %d, %d } instead of { %d, %d, %d, %d }\n",
last_paint_rect.left, last_paint_rect.top, last_paint_rect.right, last_paint_rect.bottom,
client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
update_window(hProgressWnd);
SendMessage(hProgressWnd, PBM_SETPOS, 0, 0);
GetClientRect(hProgressWnd, &client_rect);
ok(EqualRect(&last_paint_rect, &client_rect),
- "last_paint_rect was { %ld, %ld, %ld, %ld } instead of { %ld, %ld, %ld, %ld }\n",
+ "last_paint_rect was { %d, %d, %d, %d } instead of { %d, %d, %d, %d }\n",
last_paint_rect.left, last_paint_rect.top, last_paint_rect.right, last_paint_rect.bottom,
client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
update_window(hProgressWnd);
START_TEST(progress)
{
init();
-
+
test_redraw();
-
+
cleanup();
}
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-
#include <windows.h>
#include <commctrl.h>
}
return 0;
}
-
+
static INT_PTR CALLBACK page_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
LPARAM lparam)
{
psp.dwSize = sizeof(psp);
psp.dwFlags = 0;
psp.hInstance = GetModuleHandleW(NULL);
- psp.u.pszTemplate = "prop_page1";
- psp.u2.pszIcon = NULL;
+ U(psp).pszTemplate = "prop_page1";
+ U2(psp).pszIcon = NULL;
+ psp.pfnDlgProc = page_dlg_proc;
+ psp.lParam = 0;
+
+ hpsp[0] = CreatePropertySheetPageA(&psp);
+
+ memset(&psh, 0, sizeof(psh));
+ psh.dwSize = sizeof(psh);
+ psh.dwFlags = PSH_MODELESS | PSH_USECALLBACK;
+ psh.pszCaption = "test caption";
+ psh.nPages = 1;
+ psh.hwndParent = GetDesktopWindow();
+ U3(psh).phpage = hpsp;
+ psh.pfnCallback = sheet_callback;
+
+ hdlg = (HWND)PropertySheetA(&psh);
+ DestroyWindow(hdlg);
+}
+
+static void test_nopage(void)
+{
+ HPROPSHEETPAGE hpsp[1];
+ PROPSHEETPAGEA psp;
+ PROPSHEETHEADERA psh;
+ HWND hdlg;
+
+ memset(&psp, 0, sizeof(psp));
+ psp.dwSize = sizeof(psp);
+ psp.dwFlags = 0;
+ psp.hInstance = GetModuleHandleW(NULL);
+ U(psp).pszTemplate = "prop_page1";
+ U2(psp).pszIcon = NULL;
psp.pfnDlgProc = page_dlg_proc;
psp.lParam = 0;
psh.pszCaption = "test caption";
psh.nPages = 1;
psh.hwndParent = GetDesktopWindow();
- psh.u3.phpage = hpsp;
+ U3(psh).phpage = hpsp;
psh.pfnCallback = sheet_callback;
hdlg = (HWND)PropertySheetA(&psh);
+ ShowWindow(hdlg,SW_NORMAL);
+ SendMessage(hdlg, PSM_REMOVEPAGE, 0, 0);
+ RedrawWindow(hdlg,NULL,NULL,RDW_UPDATENOW|RDW_ERASENOW);
DestroyWindow(hdlg);
}
START_TEST(propsheet)
{
test_title();
+ test_nopage();
}
--- /dev/null
+/* Unit tests for rebar.
+ *
+ * Copyright 2007 Mikolaj Zalewski
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+
+#include <windows.h>
+#include <commctrl.h>
+#include <uxtheme.h>
+
+#include "wine/test.h"
+
+RECT height_change_notify_rect;
+static HWND hMainWnd;
+static HWND hRebar;
+
+
+#define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
+ val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
+ val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
+
+#define check_rect_no_top(name, val, exp) { \
+ ok((val.bottom - val.top == exp.bottom - exp.top) && \
+ val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d), ignoring top\n", \
+ val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom); \
+ }
+
+#define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
+
+#define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format " got " format "\n", (value), (ret)); }
+
+static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
+{
+ return 0;
+}
+
+static BOOL is_font_installed(const char *name)
+{
+ HDC hdc = GetDC(0);
+ BOOL ret = FALSE;
+
+ if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
+ ret = TRUE;
+
+ ReleaseDC(0, hdc);
+ return ret;
+}
+
+static void rebuild_rebar(HWND *hRebar)
+{
+ if (*hRebar)
+ DestroyWindow(*hRebar);
+
+ *hRebar = CreateWindow(REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
+ hMainWnd, (HMENU)17, GetModuleHandle(NULL), NULL);
+ SendMessageA(*hRebar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
+}
+
+static HWND build_toolbar(int nr, HWND hParent)
+{
+ TBBUTTON btns[8];
+ HWND hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE, 0, 0, 0, 0,
+ hParent, (HMENU)5, GetModuleHandle(NULL), NULL);
+ int iBitmapId = 0;
+ int i;
+
+ ok(hToolbar != NULL, "Toolbar creation problem\n");
+ ok(SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
+ ok(SendMessage(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
+ ok(SendMessage(hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
+
+ for (i=0; i<5+nr; i++)
+ {
+ btns[i].iBitmap = i;
+ btns[i].idCommand = i;
+ btns[i].fsStyle = BTNS_BUTTON;
+ btns[i].fsState = TBSTATE_ENABLED;
+ btns[i].iString = 0;
+ }
+
+ switch (nr)
+ {
+ case 0: iBitmapId = IDB_HIST_SMALL_COLOR; break;
+ case 1: iBitmapId = IDB_VIEW_SMALL_COLOR; break;
+ case 2: iBitmapId = IDB_STD_SMALL_COLOR; break;
+ }
+ ok(SendMessage(hToolbar, TB_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGE failed\n");
+ ok(SendMessage(hToolbar, TB_ADDBUTTONS, 5+nr, (LPARAM)btns), "TB_ADDBUTTONS failed\n");
+ return hToolbar;
+}
+
+static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_NOTIFY:
+ {
+ NMHDR *lpnm = (NMHDR *)lParam;
+ if (lpnm->code == RBN_HEIGHTCHANGE)
+ GetClientRect(hRebar, &height_change_notify_rect);
+ }
+ break;
+ }
+ return DefWindowProcA(hWnd, msg, wParam, lParam);
+}
+
+#if 0 /* use this to generate more tests*/
+
+static void dump_sizes(HWND hRebar)
+{
+ SIZE sz;
+ RECT r;
+ int count;
+ int i, h;
+
+ GetClientRect(hRebar, &r);
+ count = SendMessageA(hRebar, RB_GETROWCOUNT, 0, 0);
+ printf(" { {%d, %d, %d, %d}, %d, %d, {", r.left, r.top, r.right, r.bottom,
+ SendMessageA(hRebar, RB_GETBARHEIGHT, 0, 0), count);
+ if (count == 0)
+ printf("0, ");
+ for (i = 0; i < count; i++) /* rows */
+ printf("%d, ", SendMessageA(hRebar, RB_GETROWHEIGHT, i, 0));
+ printf("}, ");
+
+ count = SendMessageA(hRebar, RB_GETBANDCOUNT, 0, 0);
+ printf("%d, {", count);
+ if (count == 0)
+ printf("{{0, 0, 0, 0}, 0, 0},");
+ for (i=0; i<count; i++)
+ {
+ REBARBANDINFO rbi;
+ rbi.cbSize = sizeof(REBARBANDINFO);
+ rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE;
+ ok(SendMessageA(hRebar, RB_GETBANDINFOA, i, (LPARAM)&rbi), "RB_GETBANDINFO failed\n");
+ ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&r), "RB_GETRECT failed\n");
+ printf("%s{ {%3d, %3d, %3d, %3d}, 0x%02x, %d}, ", (i%2==0 ? "\n " : ""), r.left, r.top, r.right, r.bottom,
+ rbi.fStyle, rbi.cx);
+ }
+ printf("\n }, }, \n");
+}
+
+#define check_sizes() dump_sizes(hRebar);
+#define check_sizes_todo(todomask) dump_sizes(hRebar);
+
+#else
+
+typedef struct {
+ RECT rc;
+ DWORD fStyle;
+ INT cx;
+} rbband_result_t;
+
+typedef struct {
+ RECT rcClient;
+ int cyBarHeight;
+ int nRows;
+ int cyRowHeights[50];
+ int nBands;
+ rbband_result_t bands[50];
+} rbsize_result_t;
+
+rbsize_result_t rbsize_results[] = {
+ { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
+ }, },
+ { {0, 0, 672, 4}, 4, 1, {4, }, 1, {
+ { { 0, 0, 672, 4}, 0x00, 200},
+ }, },
+ { {0, 0, 672, 4}, 4, 1, {4, }, 2, {
+ { { 0, 0, 200, 4}, 0x00, 200}, { {200, 0, 672, 4}, 0x04, 200},
+ }, },
+ { {0, 0, 672, 30}, 30, 1, {30, }, 3, {
+ { { 0, 0, 200, 30}, 0x00, 200}, { {200, 0, 400, 30}, 0x04, 200},
+ { {400, 0, 672, 30}, 0x00, 200},
+ }, },
+ { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
+ { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
+ { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
+ }, },
+ { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
+ { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
+ { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
+ }, },
+ { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
+ { { 0, 0, 200, 34}, 0x00, 200}, { {202, 0, 402, 34}, 0x04, 200},
+ { {404, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
+ }, },
+ { {0, 0, 672, 70}, 70, 2, {34, 34, }, 5, {
+ { { 0, 0, 142, 34}, 0x00, 200}, { {144, 0, 557, 34}, 0x00, 200},
+ { {559, 0, 672, 34}, 0x04, 200}, { { 0, 36, 200, 70}, 0x00, 200},
+ { {202, 36, 672, 70}, 0x04, 66},
+ }, },
+ { {0, 0, 672, 34}, 34, 1, {34, }, 5, {
+ { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
+ { {559, 0, 759, 34}, 0x08, 200}, { {584, 0, 627, 34}, 0x00, 200},
+ { {629, 0, 672, 34}, 0x04, 66},
+ }, },
+ { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
+ { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
+ { {584, 0, 627, 34}, 0x00, 200}, { {629, 0, 672, 34}, 0x04, 66},
+ }, },
+ { {0, 0, 672, 34}, 34, 1, {34, }, 3, {
+ { { 0, 0, 413, 34}, 0x00, 200}, { {415, 0, 615, 34}, 0x00, 200},
+ { {617, 0, 672, 34}, 0x04, 66},
+ }, },
+ { {0, 0, 672, 34}, 34, 1, {34, }, 2, {
+ { { 0, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
+ }, },
+ { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+ { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 184, 20}, 0x00, 70},
+ { {184, 0, 424, 20}, 0x00, 240}, { {424, 0, 672, 20}, 0x00, 60},
+ { { 0, 20, 672, 40}, 0x00, 200},
+ }, },
+ { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+ { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 227, 20}, 0x00, 113},
+ { {227, 0, 424, 20}, 0x00, 197}, { {424, 0, 672, 20}, 0x00, 60},
+ { { 0, 20, 672, 40}, 0x00, 200},
+ }, },
+ { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+ { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
+ { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
+ { { 0, 20, 672, 40}, 0x00, 200},
+ }, },
+ { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+ { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 167, 20}, 0x00, 53},
+ { {167, 0, 511, 20}, 0x00, 344}, { {511, 0, 672, 20}, 0x00, 161},
+ { { 0, 20, 672, 40}, 0x00, 200},
+ }, },
+ { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+ { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
+ { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
+ { { 0, 20, 672, 40}, 0x00, 200},
+ }, },
+ { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
+ { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
+ { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
+ { { 0, 20, 672, 40}, 0x00, 200},
+ }, },
+ { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
+ }, },
+ { {0, 0, 672, 65}, 65, 1, {65, }, 3, {
+ { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 180, 65}, 0x40, 90},
+ { {180, 0, 672, 65}, 0x40, 90},
+ }, },
+ { {0, 0, 0, 226}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
+ }, },
+ { {0, 0, 65, 226}, 65, 1, {65, }, 1, {
+ { { 0, 0, 226, 65}, 0x40, 90},
+ }, },
+ { {0, 0, 65, 226}, 65, 1, {65, }, 2, {
+ { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 226, 65}, 0x40, 90},
+ }, },
+ { {0, 0, 65, 226}, 65, 1, {65, }, 3, {
+ { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 163, 65}, 0x40, 90},
+ { {163, 0, 226, 65}, 0x40, 90},
+ }, },
+};
+
+static int rbsize_numtests = 0;
+
+#define check_sizes_todo(todomask) { \
+ RECT rc; \
+ REBARBANDINFO rbi; \
+ int count, i/*, mask=(todomask)*/; \
+ rbsize_result_t *res = &rbsize_results[rbsize_numtests]; \
+ assert(rbsize_numtests < sizeof(rbsize_results)/sizeof(rbsize_results[0])); \
+ GetClientRect(hRebar, &rc); \
+ check_rect("client", rc, res->rcClient); \
+ count = SendMessage(hRebar, RB_GETROWCOUNT, 0, 0); \
+ compare(count, res->nRows, "%d"); \
+ for (i=0; i<min(count, res->nRows); i++) { \
+ int height = SendMessageA(hRebar, RB_GETROWHEIGHT, 0, 0);\
+ ok(height == res->cyRowHeights[i], "Height mismatch for row %d - %d vs %d\n", i, res->cyRowHeights[i], height); \
+ } \
+ count = SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0); \
+ compare(count, res->nBands, "%d"); \
+ for (i=0; i<min(count, res->nBands); i++) { \
+ ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_ITEMRECT\n"); \
+ if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \
+ check_rect("band", rc, res->bands[i].rc); \
+ rbi.cbSize = sizeof(REBARBANDINFO); \
+ rbi.fMask = RBBIM_STYLE | RBBIM_SIZE; \
+ ok(SendMessageA(hRebar, RB_GETBANDINFO, i, (LPARAM)&rbi) == 1, "RB_GETBANDINFO\n"); \
+ compare(rbi.fStyle, res->bands[i].fStyle, "%x"); \
+ compare(rbi.cx, res->bands[i].cx, "%d"); \
+ } \
+ rbsize_numtests++; \
+ }
+
+#define check_sizes() check_sizes_todo(0)
+
+#endif
+
+static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int cxIdeal)
+{
+ CHAR buffer[MAX_PATH];
+ REBARBANDINFO rbi;
+
+ if (lpszText != NULL)
+ strcpy(buffer, lpszText);
+ rbi.cbSize = sizeof(rbi);
+ rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_TEXT;
+ rbi.cx = cx;
+ rbi.cxMinChild = cxMinChild;
+ rbi.cxIdeal = cxIdeal;
+ rbi.cyMinChild = 20;
+ rbi.hwndChild = build_toolbar(1, hRebar);
+ rbi.lpText = (lpszText ? buffer : NULL);
+ SendMessage(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+}
+
+static void layout_test(void)
+{
+ HWND hRebar = NULL;
+ REBARBANDINFO rbi;
+
+ rebuild_rebar(&hRebar);
+ check_sizes();
+ rbi.cbSize = sizeof(rbi);
+ rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
+ rbi.cx = 200;
+ rbi.cxMinChild = 100;
+ rbi.cyMinChild = 30;
+ rbi.hwndChild = NULL;
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+ check_sizes();
+
+ rbi.fMask |= RBBIM_STYLE;
+ rbi.fStyle = RBBS_CHILDEDGE;
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+ check_sizes();
+
+ rbi.fStyle = 0;
+ rbi.cx = 200;
+ rbi.cxMinChild = 30;
+ rbi.cyMinChild = 30;
+ rbi.hwndChild = build_toolbar(0, hRebar);
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+ check_sizes();
+
+ rbi.fStyle = RBBS_CHILDEDGE;
+ rbi.cx = 68;
+ rbi.hwndChild = build_toolbar(0, hRebar);
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+ check_sizes();
+
+ SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_BANDBORDERS);
+ check_sizes(); /* a style change won't start a relayout */
+ rbi.fMask = RBBIM_SIZE;
+ rbi.cx = 66;
+ SendMessageA(hRebar, RB_SETBANDINFO, 3, (LPARAM)&rbi);
+ check_sizes(); /* here it will be relayouted */
+
+ /* this will force a new row */
+ rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
+ rbi.cx = 200;
+ rbi.cxMinChild = 400;
+ rbi.cyMinChild = 30;
+ rbi.hwndChild = build_toolbar(0, hRebar);
+ SendMessageA(hRebar, RB_INSERTBAND, 1, (LPARAM)&rbi);
+ check_sizes();
+
+ rbi.fMask = RBBIM_STYLE;
+ rbi.fStyle = RBBS_HIDDEN;
+ SendMessageA(hRebar, RB_SETBANDINFO, 2, (LPARAM)&rbi);
+ check_sizes();
+
+ SendMessageA(hRebar, RB_DELETEBAND, 2, 0);
+ check_sizes();
+ SendMessageA(hRebar, RB_DELETEBAND, 0, 0);
+ check_sizes();
+ SendMessageA(hRebar, RB_DELETEBAND, 1, 0);
+ check_sizes();
+
+ rebuild_rebar(&hRebar);
+ add_band_w(hRebar, "ABC", 70, 40, 100);
+ add_band_w(hRebar, NULL, 40, 70, 100);
+ add_band_w(hRebar, NULL, 170, 240, 100);
+ add_band_w(hRebar, "MMMMMMM", 60, 60, 100);
+ add_band_w(hRebar, NULL, 200, 200, 100);
+ check_sizes();
+ SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
+ check_sizes();
+ SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
+ check_sizes();
+ SendMessageA(hRebar, RB_MAXIMIZEBAND, 2, FALSE);
+ check_sizes();
+ SendMessageA(hRebar, RB_MINIMIZEBAND, 2, 0);
+ check_sizes();
+ SendMessageA(hRebar, RB_MINIMIZEBAND, 0, 0);
+ check_sizes();
+
+ /* VARHEIGHT resizing test on a horizontal rebar */
+ rebuild_rebar(&hRebar);
+ SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_AUTOSIZE);
+ check_sizes();
+ rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
+ rbi.fStyle = RBBS_VARIABLEHEIGHT;
+ rbi.cxMinChild = 50;
+ rbi.cyMinChild = 10;
+ rbi.cyIntegral = 11;
+ rbi.cyChild = 70;
+ rbi.cyMaxChild = 200;
+ rbi.cx = 90;
+ rbi.hwndChild = build_toolbar(0, hRebar);
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+
+ rbi.cyChild = 50;
+ rbi.hwndChild = build_toolbar(0, hRebar);
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+
+ rbi.cyMinChild = 40;
+ rbi.cyChild = 50;
+ rbi.cyIntegral = 5;
+ rbi.hwndChild = build_toolbar(0, hRebar);
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+ check_sizes();
+
+ /* VARHEIGHT resizing on a vertical rebar */
+ rebuild_rebar(&hRebar);
+ SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | CCS_VERT | RBS_AUTOSIZE);
+ check_sizes();
+ rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
+ rbi.fStyle = RBBS_VARIABLEHEIGHT;
+ rbi.cxMinChild = 50;
+ rbi.cyMinChild = 10;
+ rbi.cyIntegral = 11;
+ rbi.cyChild = 70;
+ rbi.cyMaxChild = 90;
+ rbi.cx = 90;
+ rbi.hwndChild = build_toolbar(0, hRebar);
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+ check_sizes();
+
+ rbi.cyChild = 50;
+ rbi.hwndChild = build_toolbar(0, hRebar);
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+ check_sizes();
+
+ rbi.cyMinChild = 40;
+ rbi.cyChild = 50;
+ rbi.cyIntegral = 5;
+ rbi.hwndChild = build_toolbar(0, hRebar);
+ SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
+ check_sizes();
+
+ DestroyWindow(hRebar);
+}
+
+#if 0 /* use this to generate more tests */
+
+static void dump_client(HWND hRebar)
+{
+ RECT r;
+ BOOL notify;
+ GetWindowRect(hRebar, &r);
+ MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
+ if (height_change_notify_rect.top != -1)
+ {
+ RECT rcClient;
+ GetClientRect(hRebar, &rcClient);
+ assert(EqualRect(&rcClient, &height_change_notify_rect));
+ notify = TRUE;
+ }
+ else
+ notify = FALSE;
+ printf(" {{%d, %d, %d, %d}, %d, %s},\n", r.left, r.top, r.right, r.bottom, SendMessage(hRebar, RB_GETROWCOUNT, 0, 0),
+ notify ? "TRUE" : "FALSE");
+ SetRect(&height_change_notify_rect, -1, -1, -1, -1);
+}
+
+#define comment(fmt, arg1) printf("/* " fmt " */\n", arg1);
+#define check_client() dump_client(hRebar)
+
+#else
+
+typedef struct {
+ RECT rc;
+ INT iNumRows;
+ BOOL heightNotify;
+} rbresize_test_result_t;
+
+rbresize_test_result_t resize_results[] = {
+/* style 00000001 */
+ {{0, 2, 672, 2}, 0, FALSE},
+ {{0, 2, 672, 22}, 1, TRUE},
+ {{0, 2, 672, 22}, 1, FALSE},
+ {{0, 2, 672, 22}, 1, FALSE},
+ {{0, 2, 672, 22}, 1, FALSE},
+ {{0, 2, 672, 22}, 0, FALSE},
+/* style 00000041 */
+ {{0, 0, 672, 0}, 0, FALSE},
+ {{0, 0, 672, 20}, 1, TRUE},
+ {{0, 0, 672, 20}, 1, FALSE},
+ {{0, 0, 672, 20}, 1, FALSE},
+ {{0, 0, 672, 20}, 1, FALSE},
+ {{0, 0, 672, 20}, 0, FALSE},
+/* style 00000003 */
+ {{0, 226, 672, 226}, 0, FALSE},
+ {{0, 206, 672, 226}, 1, TRUE},
+ {{0, 206, 672, 226}, 1, FALSE},
+ {{0, 206, 672, 226}, 1, FALSE},
+ {{0, 206, 672, 226}, 1, FALSE},
+ {{0, 206, 672, 226}, 0, FALSE},
+/* style 00000043 */
+ {{0, 226, 672, 226}, 0, FALSE},
+ {{0, 206, 672, 226}, 1, TRUE},
+ {{0, 206, 672, 226}, 1, FALSE},
+ {{0, 206, 672, 226}, 1, FALSE},
+ {{0, 206, 672, 226}, 1, FALSE},
+ {{0, 206, 672, 226}, 0, FALSE},
+/* style 00000080 */
+ {{2, 0, 2, 226}, 0, FALSE},
+ {{2, 0, 22, 226}, 1, TRUE},
+ {{2, 0, 22, 226}, 1, FALSE},
+ {{2, 0, 22, 226}, 1, FALSE},
+ {{2, 0, 22, 226}, 1, FALSE},
+ {{2, 0, 22, 226}, 0, FALSE},
+/* style 00000083 */
+ {{672, 0, 672, 226}, 0, FALSE},
+ {{652, 0, 672, 226}, 1, TRUE},
+ {{652, 0, 672, 226}, 1, FALSE},
+ {{652, 0, 672, 226}, 1, FALSE},
+ {{652, 0, 672, 226}, 1, FALSE},
+ {{652, 0, 672, 226}, 0, FALSE},
+/* style 00000008 */
+ {{10, 11, 510, 11}, 0, FALSE},
+ {{10, 15, 510, 35}, 1, TRUE},
+ {{10, 17, 510, 37}, 1, FALSE},
+ {{10, 14, 110, 54}, 2, TRUE},
+ {{0, 4, 0, 44}, 2, FALSE},
+ {{0, 6, 0, 46}, 2, FALSE},
+ {{0, 8, 0, 48}, 2, FALSE},
+ {{0, 12, 0, 32}, 1, TRUE},
+ {{0, 4, 100, 24}, 0, FALSE},
+/* style 00000048 */
+ {{10, 5, 510, 5}, 0, FALSE},
+ {{10, 5, 510, 25}, 1, TRUE},
+ {{10, 5, 510, 25}, 1, FALSE},
+ {{10, 10, 110, 50}, 2, TRUE},
+ {{0, 0, 0, 40}, 2, FALSE},
+ {{0, 0, 0, 40}, 2, FALSE},
+ {{0, 0, 0, 40}, 2, FALSE},
+ {{0, 0, 0, 20}, 1, TRUE},
+ {{0, 0, 100, 20}, 0, FALSE},
+/* style 00000004 */
+ {{10, 5, 510, 20}, 0, FALSE},
+ {{10, 5, 510, 20}, 1, TRUE},
+ {{10, 10, 110, 110}, 2, TRUE},
+ {{0, 0, 0, 0}, 2, FALSE},
+ {{0, 0, 0, 0}, 2, FALSE},
+ {{0, 0, 0, 0}, 2, FALSE},
+ {{0, 0, 0, 0}, 1, TRUE},
+ {{0, 0, 100, 100}, 0, FALSE},
+/* style 00000002 */
+ {{0, 5, 672, 5}, 0, FALSE},
+ {{0, 5, 672, 25}, 1, TRUE},
+ {{0, 10, 672, 30}, 1, FALSE},
+ {{0, 0, 672, 20}, 1, FALSE},
+ {{0, 0, 672, 20}, 1, FALSE},
+ {{0, 0, 672, 20}, 0, FALSE},
+/* style 00000082 */
+ {{10, 0, 10, 226}, 0, FALSE},
+ {{10, 0, 30, 226}, 1, TRUE},
+ {{10, 0, 30, 226}, 1, FALSE},
+ {{0, 0, 20, 226}, 1, FALSE},
+ {{0, 0, 20, 226}, 1, FALSE},
+ {{0, 0, 20, 226}, 0, FALSE},
+/* style 00800001 */
+ {{-2, 0, 674, 4}, 0, FALSE},
+ {{-2, 0, 674, 24}, 1, TRUE},
+ {{-2, 0, 674, 24}, 1, FALSE},
+ {{-2, 0, 674, 24}, 1, FALSE},
+ {{-2, 0, 674, 24}, 1, FALSE},
+ {{-2, 0, 674, 24}, 0, FALSE},
+/* style 00800048 */
+ {{10, 5, 510, 9}, 0, FALSE},
+ {{10, 5, 510, 29}, 1, TRUE},
+ {{10, 5, 510, 29}, 1, FALSE},
+ {{10, 10, 110, 54}, 2, TRUE},
+ {{0, 0, 0, 44}, 2, FALSE},
+ {{0, 0, 0, 44}, 2, FALSE},
+ {{0, 0, 0, 44}, 2, FALSE},
+ {{0, 0, 0, 24}, 1, TRUE},
+ {{0, 0, 100, 24}, 0, FALSE},
+/* style 00800004 */
+ {{10, 5, 510, 20}, 0, FALSE},
+ {{10, 5, 510, 20}, 1, TRUE},
+ {{10, 10, 110, 110}, 2, TRUE},
+ {{0, 0, 0, 0}, 2, FALSE},
+ {{0, 0, 0, 0}, 2, FALSE},
+ {{0, 0, 0, 0}, 2, FALSE},
+ {{0, 0, 0, 0}, 1, TRUE},
+ {{0, 0, 100, 100}, 0, FALSE},
+/* style 00800002 */
+ {{-2, 5, 674, 9}, 0, FALSE},
+ {{-2, 5, 674, 29}, 1, TRUE},
+ {{-2, 10, 674, 34}, 1, FALSE},
+ {{-2, 0, 674, 24}, 1, FALSE},
+ {{-2, 0, 674, 24}, 1, FALSE},
+ {{-2, 0, 674, 24}, 0, FALSE},
+};
+
+static int resize_numtests = 0;
+
+#define comment(fmt, arg1)
+#define check_client() { \
+ RECT r; \
+ rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
+ assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
+ GetWindowRect(hRebar, &r); \
+ MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
+ if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
+ check_rect_no_top("client", r, res->rc); /* the top coordinate changes after every layout and is very implementation-dependent */ \
+ } else { \
+ check_rect("client", r, res->rc); \
+ } \
+ expect_eq((int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0), res->iNumRows, int, "%d"); \
+ if (res->heightNotify) { \
+ RECT rcClient; \
+ GetClientRect(hRebar, &rcClient); \
+ check_rect("notify", height_change_notify_rect, rcClient); \
+ } else ok(height_change_notify_rect.top == -1, "Unexpected RBN_HEIGHTCHANGE received\n"); \
+ SetRect(&height_change_notify_rect, -1, -1, -1, -1); \
+ }
+
+#endif
+
+static void resize_test(void)
+{
+ DWORD dwStyles[] = {CCS_TOP, CCS_TOP | CCS_NODIVIDER, CCS_BOTTOM, CCS_BOTTOM | CCS_NODIVIDER, CCS_VERT, CCS_RIGHT,
+ CCS_NOPARENTALIGN, CCS_NOPARENTALIGN | CCS_NODIVIDER, CCS_NORESIZE, CCS_NOMOVEY, CCS_NOMOVEY | CCS_VERT,
+ CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE | WS_BORDER,
+ CCS_NOMOVEY | WS_BORDER};
+
+ const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
+ int i;
+
+ for (i = 0; i < styles_count; i++)
+ {
+ comment("style %08x", dwStyles[i]);
+ SetRect(&height_change_notify_rect, -1, -1, -1, -1);
+ hRebar = CreateWindow(REBARCLASSNAME, "A", dwStyles[i] | WS_CHILD | WS_VISIBLE, 10, 5, 500, 15, hMainWnd, NULL, GetModuleHandle(NULL), 0);
+ check_client();
+ add_band_w(hRebar, NULL, 70, 100, 0);
+ if (dwStyles[i] & CCS_NOPARENTALIGN) /* the window drifts downward for CCS_NOPARENTALIGN without CCS_NODIVIDER */
+ check_client();
+ add_band_w(hRebar, NULL, 70, 100, 0);
+ check_client();
+ MoveWindow(hRebar, 10, 10, 100, 100, TRUE);
+ check_client();
+ MoveWindow(hRebar, 0, 0, 0, 0, TRUE);
+ check_client();
+ /* try to fool the rebar by sending invalid width/height - won't work */
+ if (dwStyles[i] & (CCS_NORESIZE | CCS_NOPARENTALIGN))
+ {
+ WINDOWPOS pos;
+ pos.hwnd = hRebar;
+ pos.hwndInsertAfter = NULL;
+ pos.cx = 500;
+ pos.cy = 500;
+ pos.x = 10;
+ pos.y = 10;
+ pos.flags = 0;
+ SendMessage(hRebar, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pos);
+ SendMessage(hRebar, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pos);
+ check_client();
+ SendMessage(hRebar, WM_SIZE, SIZE_RESTORED, MAKELONG(500, 500));
+ check_client();
+ }
+ SendMessage(hRebar, RB_DELETEBAND, 0, 0);
+ check_client();
+ SendMessage(hRebar, RB_DELETEBAND, 0, 0);
+ MoveWindow(hRebar, 0, 0, 100, 100, TRUE);
+ check_client();
+ DestroyWindow(hRebar);
+ }
+}
+
+static void expect_band_content(UINT uBand, INT fStyle, COLORREF clrFore,
+ COLORREF clrBack, LPCSTR lpText, int iImage, HWND hwndChild,
+ INT cxMinChild, INT cyMinChild, INT cx, HBITMAP hbmBack, INT wID,
+ INT cyChild, INT cyMaxChild, INT cyIntegral, INT cxIdeal, LPARAM lParam,
+ INT cxHeader)
+{
+ CHAR buf[MAX_PATH] = "abc";
+ REBARBANDINFO rb;
+
+ memset(&rb, 0xdd, sizeof(rb));
+ rb.cbSize = sizeof(rb);
+ rb.fMask = RBBIM_BACKGROUND | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_COLORS
+ | RBBIM_HEADERSIZE | RBBIM_ID | RBBIM_IDEALSIZE | RBBIM_IMAGE | RBBIM_LPARAM
+ | RBBIM_SIZE | RBBIM_STYLE | RBBIM_TEXT;
+ rb.lpText = buf;
+ rb.cch = MAX_PATH;
+ ok(SendMessageA(hRebar, RB_GETBANDINFOA, uBand, (LPARAM)&rb), "RB_GETBANDINFO failed\n");
+ expect_eq(rb.fStyle, fStyle, int, "%x");
+ todo_wine expect_eq(rb.clrFore, clrFore, COLORREF, "%x");
+ todo_wine expect_eq(rb.clrBack, clrBack, unsigned, "%x");
+ expect_eq(strcmp(rb.lpText, lpText), 0, int, "%d");
+ expect_eq(rb.iImage, iImage, int, "%x");
+ expect_eq(rb.hwndChild, hwndChild, HWND, "%p");
+ expect_eq(rb.cxMinChild, cxMinChild, int, "%d");
+ expect_eq(rb.cyMinChild, cyMinChild, int, "%d");
+ expect_eq(rb.cx, cx, int, "%d");
+ expect_eq(rb.hbmBack, hbmBack, HBITMAP, "%p");
+ expect_eq(rb.wID, wID, int, "%d");
+ /* the values of cyChild, cyMaxChild and cyIntegral can't be read unless the band is RBBS_VARIABLEHEIGHT */
+ expect_eq(rb.cyChild, cyChild, int, "%x");
+ expect_eq(rb.cyMaxChild, cyMaxChild, int, "%x");
+ expect_eq(rb.cyIntegral, cyIntegral, int, "%x");
+ expect_eq(rb.cxIdeal, cxIdeal, int, "%d");
+ expect_eq(rb.lParam, lParam, LPARAM, "%ld");
+ expect_eq(rb.cxHeader, cxHeader, int, "%d");
+}
+
+static void bandinfo_test(void)
+{
+ REBARBANDINFOA rb;
+ CHAR szABC[] = "ABC";
+ CHAR szABCD[] = "ABCD";
+
+ rebuild_rebar(&hRebar);
+ rb.cbSize = sizeof(REBARBANDINFO);
+ rb.fMask = 0;
+ ok(SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
+ expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
+
+ rb.fMask = RBBIM_CHILDSIZE;
+ rb.cxMinChild = 15;
+ rb.cyMinChild = 20;
+ rb.cyChild = 30;
+ rb.cyMaxChild = 20;
+ rb.cyIntegral = 10;
+ ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
+ expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
+
+ rb.fMask = RBBIM_TEXT;
+ rb.lpText = szABC;
+ ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
+ expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 35);
+
+ rb.cbSize = sizeof(REBARBANDINFO);
+ rb.fMask = 0;
+ ok(SendMessageA(hRebar, RB_INSERTBANDA, 1, (LPARAM)&rb), "RB_INSERTBAND failed\n");
+ expect_band_content(1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9);
+ expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 40);
+
+ rb.fMask = RBBIM_HEADERSIZE;
+ rb.cxHeader = 50;
+ ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
+ expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 50);
+
+ rb.cxHeader = 5;
+ ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
+ expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
+
+ rb.fMask = RBBIM_TEXT;
+ rb.lpText = szABCD;
+ ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
+ expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
+ rb.fMask = RBBIM_STYLE | RBBIM_TEXT;
+ rb.fStyle = RBBS_VARIABLEHEIGHT;
+ rb.lpText = szABC;
+ ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
+ expect_band_content(0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 40);
+
+ DestroyWindow(hRebar);
+}
+
+START_TEST(rebar)
+{
+ INITCOMMONCONTROLSEX icc;
+ WNDCLASSA wc;
+ MSG msg;
+ RECT rc;
+
+ icc.dwSize = sizeof(icc);
+ icc.dwICC = ICC_COOL_CLASSES;
+ InitCommonControlsEx(&icc);
+
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = GetModuleHandleA(NULL);
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
+ wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = "MyTestWnd";
+ wc.lpfnWndProc = MyWndProc;
+ RegisterClassA(&wc);
+ hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
+ CW_USEDEFAULT, CW_USEDEFAULT, 672+2*GetSystemMetrics(SM_CXSIZEFRAME),
+ 226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
+ NULL, NULL, GetModuleHandleA(NULL), 0);
+ GetClientRect(hMainWnd, &rc);
+ ShowWindow(hMainWnd, SW_SHOW);
+
+ bandinfo_test();
+
+ if(is_font_installed("System") && is_font_installed("Tahoma"))
+ {
+ layout_test();
+ resize_test();
+ } else
+ skip("Missing System or Tahoma font\n");
+
+ PostQuitMessage(0);
+ while(GetMessageA(&msg,0,0,0)) {
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+ DestroyWindow(hMainWnd);
+}
--- /dev/null
+/*
+ * Resource IDs
+ *
+ * Copyright 2006 Mikolaj Zalewski
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_COMCTL32_TEST_RESOURCES_H
+#define __WINE_COMCTL32_TEST_RESOURCES_H
+
+#define IDB_BITMAP_128x15 10
+#define IDB_BITMAP_80x15 11
+
+#define IDS_TBADD1 16
+#define IDS_TBADD2 17
+#define IDS_TBADD3 18
+#define IDS_TBADD4 19
+#define IDS_TBADD5 20
+#define IDS_TBADD7 22
+
+#endif /* __WINE_COMCTL32_TEST_RESOURCES_H */
-/* Resources for the unit test suite for property sheet control.
+/* Resources for the common control unit test suite.
*
* Copyright 2006 Huw Davies
+ * Copyright 2006 Mikolaj Zalewski
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "windef.h"
#include "winuser.h"
+#include "resources.h"
PROP_PAGE1 DIALOG LOADONCALL MOVEABLE DISCARDABLE 5, 43, 227, 215
STYLE WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS | WS_VISIBLE
{
LTEXT "Test", -1, 10, 6, 100, 8
}
+
+STRINGTABLE
+{
+ IDS_TBADD1 "abc"
+ IDS_TBADD2 "|p|q|r"
+ IDS_TBADD3 "*p*q*"
+ IDS_TBADD4 "#p#q##"
+ IDS_TBADD5 "|p||q|r|"
+ IDS_TBADD7 "abracadabra"
+}
+
+/* @makedep: bmp128x15.bmp */
+IDB_BITMAP_128x15 BITMAP bmp128x15.bmp
+
+/* @makedep: bmp80x15.bmp */
+IDB_BITMAP_80x15 BITMAP bmp80x15.bmp
--- /dev/null
+/* Unit test suite for status control.
+ *
+ * Copyright 2007 Google (Lei Zhang)
+ * Copyright 2007 Alex Arazi
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <assert.h>
+#include <windows.h>
+#include <commctrl.h>
+
+#include "wine/test.h"
+
+#define expect(expected,got) ok (expected == got,"Expected %d, got %d\n",expected,got);
+
+static HINSTANCE hinst;
+
+static HWND create_status_control(DWORD style, DWORD exstyle)
+{
+ HWND hWndStatus;
+
+ /* make the control */
+ hWndStatus = CreateWindowEx(exstyle, STATUSCLASSNAME, NULL, style,
+ /* placement */
+ 0, 0, 300, 20,
+ /* parent, etc */
+ NULL, NULL, hinst, NULL);
+ assert (hWndStatus);
+ return hWndStatus;
+}
+
+static void test_status_control(void)
+{
+ HWND hWndStatus;
+ int r;
+ int nParts[] = {50, 150, -1};
+ int checkParts[] = {0, 0, 0};
+ int borders[] = {0, 0, 0};
+ RECT rc;
+ CHAR charArray[20];
+ HICON hIcon;
+
+ hWndStatus = create_status_control(WS_VISIBLE, 0);
+
+ /* Divide into parts and set text */
+ r = SendMessage(hWndStatus, SB_SETPARTS, 3, (long)nParts);
+ expect(TRUE,r);
+ r = SendMessage(hWndStatus, SB_SETTEXT, 0, (LPARAM)"First");
+ expect(TRUE,r);
+ r = SendMessage(hWndStatus, SB_SETTEXT, 1, (LPARAM)"Second");
+ expect(TRUE,r);
+ r = SendMessage(hWndStatus, SB_SETTEXT, 2, (LPARAM)"Third");
+ expect(TRUE,r);
+
+ /* Get RECT Information */
+ r = SendMessage(hWndStatus, SB_GETRECT, 0, (LPARAM)&rc);
+ expect(TRUE,r);
+ expect(2,rc.top);
+ /* The rc.bottom test is system dependent
+ expect(22,rc.bottom); */
+ expect(0,rc.left);
+ expect(50,rc.right);
+ r = SendMessage(hWndStatus, SB_GETRECT, -1, (LPARAM)&rc);
+ expect(FALSE,r);
+ r = SendMessage(hWndStatus, SB_GETRECT, 3, (LPARAM)&rc);
+ expect(FALSE,r);
+ /* Get text length and text */
+ r = SendMessage(hWndStatus, SB_GETTEXTLENGTH, 2, 0);
+ expect(5,LOWORD(r));
+ expect(0,HIWORD(r));
+ r = SendMessage(hWndStatus, SB_GETTEXT, 2, (LPARAM) charArray);
+ ok(strcmp(charArray,"Third") == 0, "Expected Third, got %s\n", charArray);
+ expect(5,LOWORD(r));
+ expect(0,HIWORD(r));
+
+ /* Get parts and borders */
+ r = SendMessage(hWndStatus, SB_GETPARTS, 3, (long)checkParts);
+ ok(r == 3, "Expected 3, got %d\n", r);
+ expect(50,checkParts[0]);
+ expect(150,checkParts[1]);
+ expect(-1,checkParts[2]);
+ r = SendMessage(hWndStatus, SB_GETBORDERS, 0, (long)borders);
+ ok(r == TRUE, "Expected TRUE, got %d\n", r);
+ expect(0,borders[0]);
+ expect(2,borders[1]);
+ expect(2,borders[2]);
+
+ /* Test resetting text with different characters */
+ r = SendMessage(hWndStatus, SB_SETTEXT, 0, (LPARAM)"First@Again");
+ expect(TRUE,r);
+ r = SendMessage(hWndStatus, SB_SETTEXT, 1, (LPARAM)"InvalidChars\\7\7");
+ expect(TRUE,r);
+ r = SendMessage(hWndStatus, SB_SETTEXT, 2, (LPARAM)"InvalidChars\\n\n");
+ expect(TRUE,r);
+
+ /* Get text again */
+ r = SendMessage(hWndStatus, SB_GETTEXT, 0, (LPARAM) charArray);
+ ok(strcmp(charArray,"First@Again") == 0, "Expected First@Again, got %s\n", charArray);
+ expect(11,LOWORD(r));
+ expect(0,HIWORD(r));
+ r = SendMessage(hWndStatus, SB_GETTEXT, 1, (LPARAM) charArray);
+ todo_wine
+ {
+ ok(strcmp(charArray,"InvalidChars\\7 ") == 0, "Expected InvalidChars\\7 , got %s\n", charArray);
+ }
+ expect(15,LOWORD(r));
+ expect(0,HIWORD(r));
+ r = SendMessage(hWndStatus, SB_GETTEXT, 2, (LPARAM) charArray);
+ todo_wine
+ {
+ ok(strcmp(charArray,"InvalidChars\\n ") == 0, "Expected InvalidChars\\n , got %s\n", charArray);
+ }
+ expect(15,LOWORD(r));
+ expect(0,HIWORD(r));
+
+ /* Set background color */
+ r = SendMessage(hWndStatus, SB_SETBKCOLOR , 0, RGB(255,0,0));
+ expect(CLR_DEFAULT,r);
+ r = SendMessage(hWndStatus, SB_SETBKCOLOR , 0, CLR_DEFAULT);
+ expect(RGB(255,0,0),r);
+
+ /* Add an icon to the status bar */
+ hIcon = LoadIcon(NULL, IDI_QUESTION);
+ r = SendMessage(hWndStatus, SB_SETICON, 1, (LPARAM) NULL);
+ ok(r != 0, "Expected non-zero, got %d\n", r);
+ r = SendMessage(hWndStatus, SB_SETICON, 1, (LPARAM) hIcon);
+ ok(r != 0, "Expected non-zero, got %d\n", r);
+ r = SendMessage(hWndStatus, SB_SETICON, 1, (LPARAM) NULL);
+ ok(r != 0, "Expected non-zero, got %d\n", r);
+
+ /* Set the Unicode format */
+ r = SendMessage(hWndStatus, SB_SETUNICODEFORMAT, FALSE, 0);
+ r = SendMessage(hWndStatus, SB_GETUNICODEFORMAT, 0, 0);
+ expect(FALSE,r);
+ r = SendMessage(hWndStatus, SB_SETUNICODEFORMAT, TRUE, 0);
+ expect(FALSE,r);
+ r = SendMessage(hWndStatus, SB_GETUNICODEFORMAT, 0, 0);
+ expect(TRUE,r);
+
+ /* Reset number of parts */
+ r = SendMessage(hWndStatus, SB_SETPARTS, 2, (long)nParts);
+ expect(TRUE,r);
+
+ /* Set the minimum height and get rectangle information again */
+ SendMessage(hWndStatus, SB_SETMINHEIGHT, 50, (LPARAM) 0);
+ r = SendMessage(hWndStatus, WM_SIZE, 0, (LPARAM) 0);
+ expect(0,r);
+ r = SendMessage(hWndStatus, SB_GETRECT, 0, (LPARAM)&rc);
+ expect(TRUE,r);
+ expect(2,rc.top);
+ /* The rc.bottom test is system dependent
+ expect(22,rc.bottom); */
+ expect(0,rc.left);
+ expect(50,rc.right);
+ r = SendMessage(hWndStatus, SB_GETRECT, -1, (LPARAM)&rc);
+ expect(FALSE,r);
+ r = SendMessage(hWndStatus, SB_GETRECT, 3, (LPARAM)&rc);
+ expect(FALSE,r);
+
+ /* Set the ToolTip text */
+ todo_wine
+ {
+ SendMessage(hWndStatus, SB_SETTIPTEXT, 0,(LPARAM) "Tooltip Text");
+ SendMessage(hWndStatus, SB_GETTIPTEXT, MAKEWPARAM (0, 20),(LPARAM) charArray);
+ ok(strcmp(charArray,"Tooltip Text") == 0, "Expected Tooltip Text, got %s\n", charArray);
+ }
+
+ /* Make simple */
+ SendMessage(hWndStatus, SB_SIMPLE, TRUE, 0);
+ r = SendMessage(hWndStatus, SB_ISSIMPLE, 0, 0);
+ expect(TRUE,r);
+
+ DestroyWindow(hWndStatus);
+}
+
+START_TEST(status)
+{
+ hinst = GetModuleHandleA(NULL);
+
+ InitCommonControls();
+
+ test_status_control();
+}
"%s: the procnum %d was expected, but got procnum %d instead\n",
context, expected->procnum, actual->procnum);
ok(expected->wParam == actual->wParam,
- "%s: in procnum %d expecting wParam 0x%x got 0x%x\n",
+ "%s: in procnum %d expecting wParam 0x%lx got 0x%lx\n",
context, expected->procnum, expected->wParam, actual->wParam);
expected++;
actual++;
static LRESULT WINAPI WndProc1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
struct message msg;
-
+
if(message == WM_USER) {
msg.wParam = wParam;
msg.procnum = 1;
static LRESULT WINAPI WndProc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
struct message msg;
-
+
if(message == WM_USER) {
msg.wParam = wParam;
msg.procnum = 3;
static LRESULT WINAPI WndProcSub(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR uldSubclass, DWORD_PTR dwRefData)
{
struct message msg;
-
+
if(message == WM_USER) {
msg.wParam = wParam;
msg.procnum = uldSubclass;
add_message(&msg);
-
+
if(lParam) {
if(dwRefData & DELETE_SELF) {
pRemoveWindowSubclass(hwnd, WndProcSub, uldSubclass);
cls.lpszMenuName = NULL;
cls.lpszClassName = "TestSubclass";
if(!RegisterClassA(&cls)) return FALSE;
-
+
return TRUE;
}
START_TEST(subclass)
{
HMODULE hdll;
-
+
hdll = GetModuleHandleA("comctl32.dll");
assert(hdll);
- pSetWindowSubclass = (void*)GetProcAddress(hdll, "SetWindowSubclass");
- pRemoveWindowSubclass = (void*)GetProcAddress(hdll, "RemoveWindowSubclass");
- pDefSubclassProc = (void*)GetProcAddress(hdll, "DefSubclassProc");
-
+ /* Functions have to be loaded by ordinal. Only XP and W2K3 export
+ * them by name.
+ */
+ pSetWindowSubclass = (void*)GetProcAddress(hdll, (LPSTR)410);
+ pRemoveWindowSubclass = (void*)GetProcAddress(hdll, (LPSTR)412);
+ pDefSubclassProc = (void*)GetProcAddress(hdll, (LPSTR)413);
+
if(!pSetWindowSubclass || !pRemoveWindowSubclass || !pDefSubclassProc)
return;
/* Unit test suite for tab control.
*
* Copyright 2003 Vitaliy Margolen
+ * Copyright 2007 Hagop Hagopian
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <assert.h>
#include <windows.h>
#include <commctrl.h>
+#include <stdio.h>
#include "wine/test.h"
+#include "msg.h"
#define DEFAULT_MIN_TAB_WIDTH 54
#define TAB_DEFAULT_WIDTH 96
#define TAB_PADDING_X 6
#define EXTRA_ICON_PADDING 3
+#define MAX_TABLEN 32
+
+#define NUM_MSG_SEQUENCES 2
+#define PARENT_SEQ_INDEX 0
+#define TAB_SEQ_INDEX 1
+
+#define expect(expected, got) ok ( expected == got, "Expected %d, got %d\n", expected, got)
+#define expect_str(expected, got)\
+ ok ( strcmp(expected, got) == 0, "Expected '%s', got '%s'\n", expected, got)
#define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num)
#define CheckSize(hwnd,width,height,msg)\
SendMessage (hwnd, TCM_GETITEMRECT, 0, (LPARAM) &rTab);\
if ((width >= 0) && (height < 0))\
- ok (width == rTab.right - rTab.left, "%s: Expected width [%d] got [%ld]\n",\
+ ok (width == rTab.right - rTab.left, "%s: Expected width [%d] got [%d]\n",\
msg, (int)width, rTab.right - rTab.left);\
else if ((height >= 0) && (width < 0))\
- ok (height == rTab.bottom - rTab.top, "%s: Expected height [%d] got [%ld]\n",\
+ ok (height == rTab.bottom - rTab.top, "%s: Expected height [%d] got [%d]\n",\
msg, (int)height, rTab.bottom - rTab.top);\
else\
ok ((width == rTab.right - rTab.left) &&\
(height == rTab.bottom - rTab.top ),\
- "%s: Expected [%d,%d] got [%ld,%ld]\n", msg, (int)width, (int)height,\
+ "%s: Expected [%d,%d] got [%d,%d]\n", msg, (int)width, (int)height,\
rTab.right - rTab.left, rTab.bottom - rTab.top);
static HFONT hFont = 0;
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+
+static const struct message create_parent_wnd_seq[] = {
+ { WM_GETMINMAXINFO, sent },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { WM_SHOWWINDOW, sent|wparam, 1 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_ACTIVATEAPP, sent|wparam, 1 },
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATE, sent|wparam, 1 },
+ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+ { WM_IME_NOTIFY, sent|defwinproc|optional },
+ { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+ /* Win9x adds SWP_NOZORDER below */
+ { WM_WINDOWPOSCHANGED, sent},
+ { WM_NCCALCSIZE, sent|wparam|optional, 1 },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
+ { 0 }
+};
+
+static const struct message add_tab_to_parent[] = {
+ { TCM_INSERTITEMA, sent },
+ { TCM_INSERTITEMA, sent },
+ { WM_NOTIFYFORMAT, sent|defwinproc },
+ { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc, 0, 0 },
+ { WM_PARENTNOTIFY, sent|defwinproc },
+ { TCM_INSERTITEMA, sent },
+ { TCM_INSERTITEMA, sent },
+ { TCM_INSERTITEMA, sent },
+ { 0 }
+};
+
+static const struct message add_tab_to_parent_interactive[] = {
+ { TCM_INSERTITEMA, sent },
+ { TCM_INSERTITEMA, sent },
+ { WM_NOTIFYFORMAT, sent|defwinproc },
+ { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc, 0, 0 },
+ { WM_PARENTNOTIFY, sent|defwinproc },
+ { TCM_INSERTITEMA, sent },
+ { TCM_INSERTITEMA, sent },
+ { TCM_INSERTITEMA, sent },
+ { WM_SHOWWINDOW, sent},
+ { WM_WINDOWPOSCHANGING, sent},
+ { WM_WINDOWPOSCHANGING, sent},
+ { WM_NCACTIVATE, sent},
+ { WM_ACTIVATE, sent},
+ { WM_IME_SETCONTEXT, sent|defwinproc|optional},
+ { WM_IME_NOTIFY, sent|defwinproc|optional},
+ { WM_SETFOCUS, sent|defwinproc},
+ { WM_WINDOWPOSCHANGED, sent},
+ { WM_SIZE, sent},
+ { WM_MOVE, sent},
+ { 0 }
+};
+
+static const struct message add_tab_control_parent_seq[] = {
+ { WM_NOTIFYFORMAT, sent },
+ { WM_QUERYUISTATE, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+static const struct message add_tab_control_parent_seq_interactive[] = {
+ { WM_NOTIFYFORMAT, sent },
+ { WM_QUERYUISTATE, sent|wparam|lparam, 0, 0 },
+ { WM_WINDOWPOSCHANGING, sent|optional},
+ { WM_NCACTIVATE, sent},
+ { WM_ACTIVATE, sent},
+ { WM_WINDOWPOSCHANGING, sent|optional},
+ { WM_KILLFOCUS, sent},
+ { WM_IME_SETCONTEXT, sent|optional},
+ { WM_IME_NOTIFY, sent|optional},
+ { 0 }
+};
+
+static const struct message empty_sequence[] = {
+ { 0 }
+};
+
+static const struct message set_min_tab_width_seq[] = {
+ { TCM_SETMINTABWIDTH, sent|wparam, 0 },
+ { TCM_SETMINTABWIDTH, sent|wparam, 0 },
+ { 0 }
+};
+
+static const struct message get_item_count_seq[] = {
+ { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+static const struct message get_row_count_seq[] = {
+ { TCM_GETROWCOUNT, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+static const struct message get_item_rect_seq[] = {
+ { TCM_GETITEMRECT, sent },
+ { TCM_GETITEMRECT, sent },
+ { 0 }
+};
+
+static const struct message getset_cur_focus_seq[] = {
+ { TCM_SETCURFOCUS, sent|lparam, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_SETCURFOCUS, sent|lparam, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_SETCURSEL, sent|lparam, 0 },
+ { TCM_SETCURFOCUS, sent|lparam, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+static const struct message getset_cur_sel_seq[] = {
+ { TCM_SETCURSEL, sent|lparam, 0 },
+ { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_SETCURSEL, sent|lparam, 0 },
+ { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
+ { TCM_SETCURSEL, sent|lparam, 0 },
+ { TCM_SETCURSEL, sent|lparam, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+static const struct message getset_extended_style_seq[] = {
+ { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
+ { TCM_SETEXTENDEDSTYLE, sent },
+ { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
+ { TCM_SETEXTENDEDSTYLE, sent },
+ { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+static const struct message getset_unicode_format_seq[] = {
+ { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
+ { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
+ { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
+ { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
+ { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
+ { 0 }
+};
+
+static const struct message getset_item_seq[] = {
+ { TCM_SETITEMA, sent },
+ { TCM_GETITEMA, sent },
+ { TCM_GETITEMA, sent },
+ { 0 }
+};
+
+static const struct message getset_tooltip_seq[] = {
+ { WM_NOTIFYFORMAT, sent },
+ { WM_QUERYUISTATE, sent|wparam|lparam, 0, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_NOTIFYFORMAT, sent },
+ { TCM_SETTOOLTIPS, sent|lparam, 0 },
+ { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
+ { TCM_SETTOOLTIPS, sent|lparam, 0 },
+ { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+static const struct message getset_tooltip_parent_seq[] = {
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { 0 }
+};
+
+static const struct message insert_focus_seq[] = {
+ { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_INSERTITEM, sent|wparam, 1 },
+ { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_INSERTITEM, sent|wparam, 2 },
+ { WM_NOTIFYFORMAT, sent|defwinproc, },
+ { WM_QUERYUISTATE, sent|defwinproc, },
+ { WM_PARENTNOTIFY, sent|defwinproc, },
+ { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_INSERTITEM, sent|wparam, 3 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+static const struct message delete_focus_seq[] = {
+ { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_DELETEITEM, sent|wparam|lparam, 1, 0 },
+ { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { TCM_DELETEITEM, sent|wparam|lparam, 0, 0 },
+ { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
+ { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+
static HWND
create_tabcontrol (DWORD style, DWORD mask)
{
return handle;
}
+static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ /* do not log painting messages */
+ if (message != WM_PAINT &&
+ message != WM_ERASEBKGND &&
+ message != WM_NCPAINT &&
+ message != WM_NCHITTEST &&
+ message != WM_GETTEXT &&
+ message != WM_GETICON &&
+ message != WM_DEVICECHANGE)
+ {
+ trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, PARENT_SEQ_INDEX, &msg);
+ }
+
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static BOOL registerParentWindowClass(void)
+{
+ WNDCLASSA cls;
+
+ cls.style = 0;
+ cls.lpfnWndProc = parentWindowProcess;
+ cls.cbClsExtra = 0;
+ cls.cbWndExtra = 0;
+ cls.hInstance = GetModuleHandleA(NULL);
+ cls.hIcon = 0;
+ cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
+ cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+ cls.lpszMenuName = NULL;
+ cls.lpszClassName = "Tab test parent class";
+ return RegisterClassA(&cls);
+}
+
+static HWND createParentWindow(void)
+{
+ if (!registerParentWindowClass())
+ return NULL;
+
+ return CreateWindowEx(0, "Tab test parent class",
+ "Tab test parent window",
+ WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
+ WS_MAXIMIZEBOX | WS_VISIBLE,
+ 0, 0, 100, 100,
+ GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
+}
+
+struct subclass_info
+{
+ WNDPROC oldproc;
+};
+
+static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ /* do not log painting messages */
+ if (message != WM_PAINT &&
+ message != WM_ERASEBKGND &&
+ message != WM_NCPAINT &&
+ message != WM_NCHITTEST &&
+ message != WM_GETTEXT &&
+ message != WM_GETICON &&
+ message != WM_DEVICECHANGE)
+ {
+ trace("tab: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, TAB_SEQ_INDEX, &msg);
+ }
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT nTabs)
+{
+ HWND tabHandle;
+ TCITEM tcNewTab;
+ struct subclass_info *info;
+ RECT rect;
+ INT i;
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ GetClientRect(parent_wnd, &rect);
+
+ tabHandle = CreateWindow (
+ WC_TABCONTROLA,
+ "TestTab",
+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
+ 0, 0, rect.right, rect.bottom,
+ parent_wnd, NULL, NULL, 0);
+
+ assert(tabHandle);
+
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tabSubclassProcess);
+ SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)info);
+
+ tcNewTab.mask = mask;
+
+ for (i = 0; i < nTabs; i++)
+ {
+ char tabName[MAX_TABLEN];
+
+ sprintf(tabName, "Tab %d", i+1);
+ tcNewTab.pszText = tabName;
+ tcNewTab.iImage = i;
+ SendMessage (tabHandle, TCM_INSERTITEM, i, (LPARAM) &tcNewTab);
+ }
+
+ if (winetest_interactive)
+ {
+ ShowWindow (tabHandle, SW_SHOW);
+ RedrawWindow (tabHandle, NULL, 0, RDW_UPDATENOW);
+ Sleep (1000);
+ }
+
+ return tabHandle;
+}
+
+static HWND create_tooltip (HWND hTab, char toolTipText[])
+{
+ HWND hwndTT;
+
+ TOOLINFO ti;
+ LPTSTR lptstr = toolTipText;
+ RECT rect;
+
+ /* Creating a tooltip window*/
+ hwndTT = CreateWindowEx(
+ WS_EX_TOPMOST,
+ TOOLTIPS_CLASS,
+ NULL,
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ hTab, NULL, 0, NULL);
+
+ SetWindowPos(
+ hwndTT,
+ HWND_TOPMOST,
+ 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+
+ GetClientRect (hTab, &rect);
+
+ /* Initialize members of toolinfo*/
+ ti.cbSize = sizeof(TOOLINFO);
+ ti.uFlags = TTF_SUBCLASS;
+ ti.hwnd = hTab;
+ ti.hinst = 0;
+ ti.uId = 0;
+ ti.lpszText = lptstr;
+
+ ti.rect = rect;
+
+ /* Add toolinfo structure to the tooltip control */
+ SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
+
+ return hwndTT;
+}
+
static void test_tab(INT nMinTabWidth)
{
HWND hwTab;
hdc = GetDC(hwTab);
hOldFont = SelectObject(hdc, (HFONT)SendMessage(hwTab, WM_GETFONT, 0, 0));
GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size);
- trace("Tab1 text size: size.cx=%ld size.cy=%ld\n", size.cx, size.cy);
+ trace("Tab1 text size: size.cx=%d size.cy=%d\n", size.cx, size.cy);
SelectObject(hdc, hOldFont);
ReleaseDC(hwTab, hdc);
DeleteObject(hFont);
}
+static void test_getters_setters(HWND parent_wnd, INT nTabs)
+{
+ HWND hTab;
+ RECT rTab;
+ INT nTabsRetrieved;
+ INT rowCount;
+
+ ok(parent_wnd != NULL, "no parent window!\n");
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
+ ok(hTab != NULL, "Failed to create tab control\n");
+
+ if(!winetest_interactive)
+ ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent,
+ "Tab sequence, after adding tab control to parent", TRUE);
+ else
+ ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent_interactive,
+ "Tab sequence, after adding tab control to parent", TRUE);
+
+ if(!winetest_interactive)
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq,
+ "Parent after sequence, adding tab control to parent", TRUE);
+ else
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq_interactive,
+ "Parent after sequence, adding tab control to parent", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ todo_wine{
+ expect(DEFAULT_MIN_TAB_WIDTH, (int)SendMessage(hTab, TCM_SETMINTABWIDTH, 0, -1));
+ }
+ ok_sequence(sequences, TAB_SEQ_INDEX, set_min_tab_width_seq, "Set minTabWidth test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Set minTabWidth test parent sequence", FALSE);
+
+ /* Testing GetItemCount */
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
+ expect(nTabs, nTabsRetrieved);
+ ok_sequence(sequences, TAB_SEQ_INDEX, get_item_count_seq, "Get itemCount test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset itemCount test parent sequence", FALSE);
+
+ /* Testing GetRowCount */
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ rowCount = SendMessage(hTab, TCM_GETROWCOUNT, 0, 0);
+ expect(1, rowCount);
+ ok_sequence(sequences, TAB_SEQ_INDEX, get_row_count_seq, "Get rowCount test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get rowCount test parent sequence", FALSE);
+
+ /* Testing GetItemRect */
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+ ok(SendMessage(hTab, TCM_GETITEMRECT, 0, (LPARAM) &rTab), "GetItemRect failed.\n");
+ CheckSize(hTab, TAB_DEFAULT_WIDTH, -1 , "Default Width");
+ ok_sequence(sequences, TAB_SEQ_INDEX, get_item_rect_seq, "Get itemRect test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get itemRect test parent sequence", FALSE);
+
+ /* Testing CurFocus */
+ {
+ INT focusIndex;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Testing CurFocus with largest appropriate value */
+ SendMessage(hTab, TCM_SETCURFOCUS, nTabs-1, 0);
+ focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(nTabs-1, focusIndex);
+
+ /* Testing CurFocus with negative value */
+ SendMessage(hTab, TCM_SETCURFOCUS, -10, 0);
+ focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(-1, focusIndex);
+
+ /* Testing CurFocus with value larger than number of tabs */
+ focusIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
+ todo_wine{
+ expect(-1, focusIndex);
+ }
+
+ SendMessage(hTab, TCM_SETCURFOCUS, nTabs+1, 0);
+ focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(1, focusIndex);
+
+ ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_seq, "Getset curFoc test sequence", FALSE);
+ }
+
+ /* Testing CurSel */
+ {
+ INT selectionIndex;
+ INT focusIndex;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Testing CurSel with largest appropriate value */
+ selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs-1, 0);
+ expect(1, selectionIndex);
+ selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
+ expect(nTabs-1, selectionIndex);
+
+ /* Focus should switch with selection */
+ focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(nTabs-1, focusIndex);
+
+ /* Testing CurSel with negative value */
+ SendMessage(hTab, TCM_SETCURSEL, -10, 0);
+ selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
+ expect(-1, selectionIndex);
+
+ /* Testing CurSel with value larger than number of tabs */
+ selectionIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
+ expect(-1, selectionIndex);
+
+ selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs+1, 0);
+ expect(-1, selectionIndex);
+ selectionIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(1, selectionIndex);
+
+ ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_sel_seq, "Getset curSel test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset curSel test parent sequence", FALSE);
+ }
+
+ /* Testing ExtendedStyle */
+ {
+ DWORD prevExtendedStyle;
+ DWORD extendedStyle;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Testing Flat Separators */
+ extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
+ prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_FLATSEPARATORS);
+ expect(extendedStyle, prevExtendedStyle);
+
+ extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
+ todo_wine{
+ expect(TCS_EX_FLATSEPARATORS, extendedStyle);
+ }
+
+ /* Testing Register Drop */
+ prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_REGISTERDROP);
+ expect(extendedStyle, prevExtendedStyle);
+
+ extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
+ todo_wine{
+ expect(TCS_EX_REGISTERDROP, extendedStyle);
+ }
+
+ ok_sequence(sequences, TAB_SEQ_INDEX, getset_extended_style_seq, "Getset extendedStyle test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset extendedStyle test parent sequence", FALSE);
+ }
+
+ /* Testing UnicodeFormat */
+ {
+ INT unicodeFormat;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
+ todo_wine{
+ expect(0, unicodeFormat);
+ }
+ unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
+ expect(1, unicodeFormat);
+
+ unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, FALSE, 0);
+ expect(1, unicodeFormat);
+ unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
+ expect(0, unicodeFormat);
+
+ unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
+ expect(0, unicodeFormat);
+
+ ok_sequence(sequences, TAB_SEQ_INDEX, getset_unicode_format_seq, "Getset unicodeFormat test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset unicodeFormat test parent sequence", FALSE);
+ }
+
+ /* Testing GetSet Item */
+ {
+ TCITEM tcItem;
+ char szText[32] = "New Label";
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ tcItem.mask = TCIF_TEXT;
+ tcItem.pszText = &szText[0];
+ tcItem.cchTextMax = sizeof(szText);
+
+ ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
+ ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
+ expect_str("New Label", tcItem.pszText);
+
+ ok ( SendMessage(hTab, TCM_GETITEM, 1, (LPARAM) &tcItem), "Getting item failed.\n");
+ expect_str("Tab 2", tcItem.pszText);
+
+ ok_sequence(sequences, TAB_SEQ_INDEX, getset_item_seq, "Getset item test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset item test parent sequence", FALSE);
+ }
+
+ /* Testing GetSet ToolTip */
+ {
+ HWND toolTip;
+ char toolTipText[32] = "ToolTip Text Test";
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ toolTip = create_tooltip(hTab, toolTipText);
+ SendMessage(hTab, TCM_SETTOOLTIPS, (LPARAM) toolTip, 0);
+ ok (toolTip == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
+
+ SendMessage(hTab, TCM_SETTOOLTIPS, (LPARAM) NULL, 0);
+ ok (NULL == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
+
+ ok_sequence(sequences, TAB_SEQ_INDEX, getset_tooltip_seq, "Getset tooltip test sequence", TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, getset_tooltip_parent_seq, "Getset tooltip test parent sequence", TRUE);
+ }
+
+ DestroyWindow(hTab);
+}
+
+static void test_insert_focus(HWND parent_wnd)
+{
+ HWND hTab;
+ INT nTabsRetrieved;
+ INT r;
+ TCITEM tcNewTab;
+ DWORD mask = TCIF_TEXT|TCIF_IMAGE;
+ static char tabName[] = "TAB";
+ tcNewTab.mask = mask;
+ tcNewTab.pszText = tabName;
+
+ ok(parent_wnd != NULL, "no parent window!\n");
+
+ hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, mask, 0);
+ ok(hTab != NULL, "Failed to create tab control\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
+ expect(0, nTabsRetrieved);
+
+ r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(-1, r);
+
+ tcNewTab.iImage = 1;
+ r = SendMessage(hTab, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
+ expect(0, r);
+
+ nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
+ expect(1, nTabsRetrieved);
+
+ r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(0, r);
+
+ tcNewTab.iImage = 2;
+ r = SendMessage(hTab, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
+ expect(1, r);
+
+ nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
+ expect(2, nTabsRetrieved);
+
+ r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(0, r);
+
+ r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
+ expect(0, r);
+
+ r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(-1, r);
+
+ tcNewTab.iImage = 3;
+ r = SendMessage(hTab, TCM_INSERTITEM, 3, (LPARAM) &tcNewTab);
+ expect(2, r);
+
+ r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(2, r);
+
+ ok_sequence(sequences, TAB_SEQ_INDEX, insert_focus_seq, "insert_focus test sequence", TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "insert_focus parent test sequence", FALSE);
+
+ DestroyWindow(hTab);
+}
+
+static void test_delete_focus(HWND parent_wnd)
+{
+ HWND hTab;
+ INT nTabsRetrieved;
+ INT r;
+
+ ok(parent_wnd != NULL, "no parent window!\n");
+
+ hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 2);
+ ok(hTab != NULL, "Failed to create tab control\n");
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
+ expect(2, nTabsRetrieved);
+
+ r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(0, r);
+
+ r = SendMessage(hTab, TCM_DELETEITEM, 1, 0);
+ expect(1, r);
+
+ nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
+ expect(1, nTabsRetrieved);
+
+ r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(0, r);
+
+ r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
+ expect(0, r);
+
+ r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(-1, r);
+
+ r = SendMessage(hTab, TCM_DELETEITEM, 0, 0);
+ expect(1, r);
+
+ nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
+ expect(0, nTabsRetrieved);
+
+ r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
+ expect(-1, r);
+
+ ok_sequence(sequences, TAB_SEQ_INDEX, delete_focus_seq, "delete_focus test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "delete_focus parent test sequence", FALSE);
+
+ DestroyWindow(hTab);
+}
+
START_TEST(tab)
{
+ HWND parent_wnd;
LOGFONTA logfont;
lstrcpyA(logfont.lfFaceName, "Arial");
test_tab(54);
trace ("Testing with MinWidth set to 94\n");
test_tab(94);
+
+ init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ parent_wnd = createParentWindow();
+ ok(parent_wnd != NULL, "Failed to create parent window!\n");
+
+ /* Testing getters and setters with 5 tabs */
+ test_getters_setters(parent_wnd, 5);
+
+ test_insert_focus(parent_wnd);
+ test_delete_focus(parent_wnd);
+
+ DestroyWindow(parent_wnd);
}
+/* Automatically generated file; DO NOT EDIT!! */
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "wine/test.h"
extern void func_comboex(void);
+extern void func_datetime(void);
extern void func_dpa(void);
extern void func_header(void);
extern void func_imagelist(void);
extern void func_listview(void);
+extern void func_misc(void);
extern void func_monthcal(void);
extern void func_mru(void);
+extern void func_msg(void);
extern void func_progress(void);
extern void func_propsheet(void);
+extern void func_rebar(void);
+extern void func_status(void);
extern void func_subclass(void);
extern void func_tab(void);
extern void func_toolbar(void);
extern void func_tooltips(void);
+extern void func_trackbar(void);
extern void func_treeview(void);
extern void func_updown(void);
const struct test winetest_testlist[] =
{
{ "comboex", func_comboex },
+ { "datetime", func_datetime },
{ "dpa", func_dpa },
{ "header", func_header },
{ "imagelist", func_imagelist },
{ "listview", func_listview },
+ { "misc", func_misc },
{ "monthcal", func_monthcal },
{ "mru", func_mru },
+ { "msg", func_msg },
{ "progress", func_progress },
{ "propsheet", func_propsheet },
+ { "rebar", func_rebar },
+ { "status", func_status },
{ "subclass", func_subclass },
{ "tab", func_tab },
{ "toolbar", func_toolbar },
{ "tooltips", func_tooltips },
+ { "trackbar", func_trackbar },
{ "treeview", func_treeview },
{ "updown", func_updown },
{ 0, 0 }
/* Unit tests for treeview.
*
* Copyright 2005 Krzysztof Foltman
+ * Copyright 2007 Mikolaj Zalewski
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "winuser.h"
#include "winnls.h"
#include "winreg.h"
-#include "commctrl.h"
+#include "commctrl.h"
+
+#include "resources.h"
#include "wine/test.h"
+static HWND hMainWnd;
+static BOOL g_fBlockHotItemChange;
+static BOOL g_fReceivedHotItemChange;
+static BOOL g_fExpectedHotItemOld;
+static BOOL g_fExpectedHotItemNew;
+static DWORD g_dwExpectedDispInfoMask;
+
+#define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
+ val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
+ val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
+
+#define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
+
static void MakeButton(TBBUTTON *p, int idCommand, int fsStyle, int nString) {
p->iBitmap = -2;
p->idCommand = idCommand;
p->iString = nString;
}
+static LRESULT MyWnd_Notify(LPARAM lParam)
+{
+ NMHDR *hdr = (NMHDR *)lParam;
+ NMTBHOTITEM *nmhi;
+ NMTBDISPINFO *nmdisp;
+ switch (hdr->code)
+ {
+ case TBN_HOTITEMCHANGE:
+ nmhi = (NMTBHOTITEM *)lParam;
+ g_fReceivedHotItemChange = TRUE;
+ if (g_fExpectedHotItemOld != g_fExpectedHotItemNew)
+ {
+ compare(nmhi->idOld, g_fExpectedHotItemOld, "%d");
+ compare(nmhi->idNew, g_fExpectedHotItemNew, "%d");
+ }
+ if (g_fBlockHotItemChange)
+ return 1;
+ break;
+
+ case TBN_GETDISPINFOA:
+ ok(FALSE, "TBN_GETDISPINFOA received\n");
+ break;
+
+ case TBN_GETDISPINFOW:
+ nmdisp = (NMTBDISPINFOA *)lParam;
+
+ compare(nmdisp->dwMask, g_dwExpectedDispInfoMask, "%x");
+ compare(nmdisp->iImage, -1, "%d");
+ ok(nmdisp->pszText == NULL, "pszText is not NULL\n");
+ break;
+ }
+ return 0;
+}
+
static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
- switch(msg) {
+ switch (msg)
+ {
+ case WM_NOTIFY:
+ return MyWnd_Notify(lParam);
+ }
+ return DefWindowProcA(hWnd, msg, wParam, lParam);
+}
+
+static void basic_test(void)
+{
+ TBBUTTON buttons[9];
+ HWND hToolbar;
+ int i;
+ for (i=0; i<9; i++)
+ MakeButton(buttons+i, 1000+i, TBSTYLE_CHECKGROUP, 0);
+ MakeButton(buttons+3, 1003, TBSTYLE_SEP|TBSTYLE_GROUP, 0);
+ MakeButton(buttons+6, 1006, TBSTYLE_SEP, 0);
+
+ hToolbar = CreateToolbarEx(hMainWnd,
+ WS_VISIBLE | WS_CLIPCHILDREN | CCS_TOP |
+ WS_CHILD | TBSTYLE_LIST,
+ 100,
+ 0, NULL, (UINT)0,
+ buttons, sizeof(buttons)/sizeof(buttons[0]),
+ 0, 0, 20, 16, sizeof(TBBUTTON));
+ ok(hToolbar != NULL, "Toolbar creation\n");
+ SendMessage(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"test\000");
+
+ /* test for exclusion working inside a separator-separated :-) group */
+ SendMessage(hToolbar, TB_CHECKBUTTON, 1000, 1); /* press A1 */
+ ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 pressed\n");
+ ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1001, 0), "A2 not pressed\n");
+
+ SendMessage(hToolbar, TB_CHECKBUTTON, 1004, 1); /* press A5, release A1 */
+ ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1004, 0), "A5 pressed\n");
+ ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 not pressed anymore\n");
+
+ SendMessage(hToolbar, TB_CHECKBUTTON, 1005, 1); /* press A6, release A5 */
+ ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 pressed\n");
+ ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1004, 0), "A5 not pressed anymore\n");
+
+ /* test for inter-group crosstalk, ie. two radio groups interfering with each other */
+ SendMessage(hToolbar, TB_CHECKBUTTON, 1007, 1); /* press B2 */
+ ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 still pressed, no inter-group crosstalk\n");
+ ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 still not pressed\n");
+ ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1007, 0), "B2 pressed\n");
+
+ SendMessage(hToolbar, TB_CHECKBUTTON, 1000, 1); /* press A1 and ensure B group didn't suffer */
+ ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 not pressed anymore\n");
+ ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 pressed\n");
+ ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1007, 0), "B2 still pressed\n");
+
+ SendMessage(hToolbar, TB_CHECKBUTTON, 1008, 1); /* press B3, and ensure A group didn't suffer */
+ ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 pressed\n");
+ ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 pressed\n");
+ ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1007, 0), "B2 not pressed\n");
+ ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1008, 0), "B3 pressed\n");
+
+ /* tests with invalid index */
+ compare(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 0xdeadbeef, 0), -1L, "%ld");
+ compare(SendMessage(hToolbar, TB_ISBUTTONPRESSED, 0xdeadbeef, 0), -1L, "%ld");
+ compare(SendMessage(hToolbar, TB_ISBUTTONENABLED, 0xdeadbeef, 0), -1L, "%ld");
+ compare(SendMessage(hToolbar, TB_ISBUTTONINDETERMINATE, 0xdeadbeef, 0), -1L, "%ld");
+ compare(SendMessage(hToolbar, TB_ISBUTTONHIGHLIGHTED, 0xdeadbeef, 0), -1L, "%ld");
+ compare(SendMessage(hToolbar, TB_ISBUTTONHIDDEN, 0xdeadbeef, 0), -1L, "%ld");
+
+ DestroyWindow(hToolbar);
+}
+
+static void rebuild_toolbar(HWND *hToolbar)
+{
+ if (*hToolbar != NULL)
+ DestroyWindow(*hToolbar);
+ *hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
+ hMainWnd, (HMENU)5, GetModuleHandle(NULL), NULL);
+ ok(*hToolbar != NULL, "Toolbar creation problem\n");
+ ok(SendMessage(*hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
+ ok(SendMessage(*hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
+ ok(SendMessage(*hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
+}
+
+static void rebuild_toolbar_with_buttons(HWND *hToolbar)
+{
+ TBBUTTON buttons[5];
+ rebuild_toolbar(hToolbar);
+
+ ZeroMemory(&buttons, sizeof(buttons));
+ buttons[0].idCommand = 1;
+ buttons[0].fsStyle = BTNS_BUTTON;
+ buttons[0].fsState = TBSTATE_ENABLED;
+ buttons[0].iString = -1;
+ buttons[1].idCommand = 3;
+ buttons[1].fsStyle = BTNS_BUTTON;
+ buttons[1].fsState = TBSTATE_ENABLED;
+ buttons[1].iString = -1;
+ buttons[2].idCommand = 5;
+ buttons[2].fsStyle = BTNS_SEP;
+ buttons[2].fsState = TBSTATE_ENABLED;
+ buttons[2].iString = -1;
+ buttons[3].idCommand = 7;
+ buttons[3].fsStyle = BTNS_BUTTON;
+ buttons[3].fsState = TBSTATE_ENABLED;
+ buttons[3].iString = -1;
+ buttons[4].idCommand = 9;
+ buttons[4].fsStyle = BTNS_BUTTON;
+ buttons[4].fsState = 0; /* disabled */
+ buttons[4].iString = -1;
+ ok(SendMessage(*hToolbar, TB_ADDBUTTONS, 5, (LPARAM)buttons) == 1, "TB_ADDBUTTONS failed\n");
+ ok(SendMessage(*hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
+}
+
+
+#define CHECK_IMAGELIST(count, dx, dy) { \
+ int cx, cy; \
+ HIMAGELIST himl = (HIMAGELIST)SendMessageA(hToolbar, TB_GETIMAGELIST, 0, 0); \
+ ok(himl != NULL, "No image list\n"); \
+ if (himl != NULL) {\
+ ok(ImageList_GetImageCount(himl) == count, "Images count mismatch - %d vs %d\n", count, ImageList_GetImageCount(himl)); \
+ ImageList_GetIconSize(himl, &cx, &cy); \
+ ok(cx == dx && cy == dy, "Icon size mismatch - %dx%d vs %dx%d\n", dx, dy, cx, cy); \
+ } \
+}
+
+static void test_add_bitmap(void)
+{
+ HWND hToolbar = NULL;
+ TBADDBITMAP bmp128;
+ TBADDBITMAP bmp80;
+ TBADDBITMAP stdsmall;
+ TBADDBITMAP addbmp;
+ HIMAGELIST himl;
+ INT ret;
+
+ /* empty 128x15 bitmap */
+ bmp128.hInst = GetModuleHandle(NULL);
+ bmp128.nID = IDB_BITMAP_128x15;
+
+ /* empty 80x15 bitmap */
+ bmp80.hInst = GetModuleHandle(NULL);
+ bmp80.nID = IDB_BITMAP_80x15;
+
+ /* standard bitmap - 240x15 pixels */
+ stdsmall.hInst = HINST_COMMCTRL;
+ stdsmall.nID = IDB_STD_SMALL_COLOR;
+
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 8, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(8, 16, 16);
+
+ /* adding more bitmaps */
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp80) == 8, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(13, 16, 16);
+ /* adding the same bitmap will simply return the index of the already loaded block */
+ ret = SendMessageA(hToolbar, TB_ADDBITMAP, 8, (LPARAM)&bmp128);
+ ok(ret == 0, "TB_ADDBITMAP - unexpected return %d\n", ret);
+ CHECK_IMAGELIST(13, 16, 16);
+ ret = SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp80);
+ ok(ret == 8, "TB_ADDBITMAP - unexpected return %d\n", ret);
+ CHECK_IMAGELIST(13, 16, 16);
+ /* even if we increase the wParam */
+ ret = SendMessageA(hToolbar, TB_ADDBITMAP, 55, (LPARAM)&bmp80);
+ ok(ret == 8, "TB_ADDBITMAP - unexpected return %d\n", ret);
+ CHECK_IMAGELIST(13, 16, 16);
+
+ /* when the wParam is smaller than the bitmaps count but non-zero, all the bitmaps will be added*/
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 3, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(8, 16, 16);
+ ret = SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp80);
+ ok(ret == 3, "TB_ADDBITMAP - unexpected return %d\n", ret);
+ /* the returned value is misleading - id 8 is the id of the first icon from bmp80 */
+ CHECK_IMAGELIST(13, 16, 16);
+
+ /* the same for negative wParam */
+ rebuild_toolbar(&hToolbar);
+ ret = SendMessageA(hToolbar, TB_ADDBITMAP, -143, (LPARAM)&bmp128);
+ ok(ret == 0, "TB_ADDBITMAP - unexpected return %d\n", ret);
+ CHECK_IMAGELIST(8, 16, 16);
+ ret = SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&bmp80);
+ ok(ret == -143, "TB_ADDBITMAP - unexpected return %d\n", ret);
+ CHECK_IMAGELIST(13, 16, 16);
+
+ /* for zero only one bitmap will be added */
+ rebuild_toolbar(&hToolbar);
+ ret = SendMessageA(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&bmp80);
+ ok(ret == 0, "TB_ADDBITMAP - unexpected return %d\n", ret);
+ CHECK_IMAGELIST(1, 16, 16);
+
+ /* if wParam is larger than the amount of icons, the list is grown */
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 100, (LPARAM)&bmp80) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(100, 16, 16);
+ ret = SendMessageA(hToolbar, TB_ADDBITMAP, 100, (LPARAM)&bmp128);
+ ok(ret == 100, "TB_ADDBITMAP - unexpected return %d\n", ret);
+ CHECK_IMAGELIST(200, 16, 16);
+
+ /* adding built-in items - the wParam is ignored */
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp80) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(5, 16, 16);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&stdsmall) == 5, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(20, 16, 16);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp128) == 20, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(28, 16, 16);
+
+ /* when we increase the bitmap size, less icons will be created */
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(20, 20)) == TRUE, "TB_SETBITMAPSIZE failed\n");
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(6, 20, 20);
+ ret = SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&bmp80);
+ ok(ret == 1, "TB_ADDBITMAP - unexpected return %d\n", ret);
+ CHECK_IMAGELIST(10, 20, 20);
+ /* the icons can be resized - an UpdateWindow is needed as this probably happens during WM_PAINT */
+ ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(8, 8)) == TRUE, "TB_SETBITMAPSIZE failed\n");
+ UpdateWindow(hToolbar);
+ CHECK_IMAGELIST(26, 8, 8);
+ /* loading a standard bitmaps automatically resizes the icons */
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&stdsmall) == 2, "TB_ADDBITMAP - unexpected return\n");
+ UpdateWindow(hToolbar);
+ CHECK_IMAGELIST(28, 16, 16);
+
+ /* two more SETBITMAPSIZE tests */
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 100, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(100, 16, 16);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 100, (LPARAM)&bmp80) == 100, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(200, 16, 16);
+ ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(8, 8)) == TRUE, "TB_SETBITMAPSIZE failed\n");
+ UpdateWindow(hToolbar);
+ CHECK_IMAGELIST(200, 8, 8);
+ ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(30, 30)) == TRUE, "TB_SETBITMAPSIZE failed\n");
+ UpdateWindow(hToolbar);
+ CHECK_IMAGELIST(200, 30, 30);
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(8, 16, 16);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 3, (LPARAM)&bmp80) == 5, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(13, 16, 16);
+ ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(30, 30)) == TRUE, "TB_SETBITMAPSIZE failed\n");
+ UpdateWindow(hToolbar);
+ CHECK_IMAGELIST(8, 30, 30);
+ /* when the width or height is zero, set it to 1 */
+ ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(0, 0)) == TRUE, "TB_SETBITMAPSIZE failed\n");
+ UpdateWindow(hToolbar);
+ CHECK_IMAGELIST(208, 1, 1);
+ ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(0, 5)) == TRUE, "TB_SETBITMAPSIZE failed\n");
+ UpdateWindow(hToolbar);
+ CHECK_IMAGELIST(208, 1, 5);
+ ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(5, 0)) == TRUE, "TB_SETBITMAPSIZE failed\n");
+ UpdateWindow(hToolbar);
+ CHECK_IMAGELIST(41, 5, 1);
+
+ /* the control can add bitmaps to an existing image list */
+ rebuild_toolbar(&hToolbar);
+ himl = ImageList_LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP_80x15), 20, 2, CLR_NONE, IMAGE_BITMAP, LR_DEFAULTCOLOR);
+ ok(himl != NULL, "failed to create imagelist\n");
+ ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl) == 0, "TB_SETIMAGELIST failed\n");
+ CHECK_IMAGELIST(4, 20, 15);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(10, 20, 15);
+ /* however TB_SETBITMAPSIZE/add std bitmap won't change the image size (the button size does change) */
+ ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(8, 8)) == TRUE, "TB_SETBITMAPSIZE failed\n");
+ UpdateWindow(hToolbar);
+ compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(15, 14), "%x");
+ CHECK_IMAGELIST(10, 20, 15);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&stdsmall) == 1, "TB_SETBITMAPSIZE failed\n");
+ UpdateWindow(hToolbar);
+ compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(23, 22), "%x");
+ CHECK_IMAGELIST(22, 20, 15);
+
+ /* check standard bitmaps */
+ addbmp.hInst = HINST_COMMCTRL;
+ addbmp.nID = IDB_STD_SMALL_COLOR;
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(15, 16, 16);
+ compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(23, 22), "%x");
+ addbmp.nID = IDB_STD_LARGE_COLOR;
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(15, 24, 24);
+ compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(31, 30), "%x");
+
+ addbmp.nID = IDB_VIEW_SMALL_COLOR;
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(12, 16, 16);
+ addbmp.nID = IDB_VIEW_LARGE_COLOR;
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(12, 24, 24);
+
+ addbmp.nID = IDB_HIST_SMALL_COLOR;
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(5, 16, 16);
+ addbmp.nID = IDB_HIST_LARGE_COLOR;
+ rebuild_toolbar(&hToolbar);
+ ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
+ CHECK_IMAGELIST(5, 24, 24);
+
+
+ DestroyWindow(hToolbar);
+}
+
+#define CHECK_STRING_TABLE(count, tab) { \
+ INT _i; \
+ CHAR _buf[260]; \
+ for (_i = 0; _i < (count); _i++) {\
+ ret = SendMessageA(hToolbar, TB_GETSTRING, MAKEWPARAM(260, _i), (LPARAM)_buf); \
+ ok(ret >= 0, "TB_GETSTRING - unexpected return %d while checking string %d\n", ret, _i); \
+ if (ret >= 0) \
+ ok(strcmp(_buf, (tab)[_i]) == 0, "Invalid string #%d - '%s' vs '%s'\n", _i, (tab)[_i], _buf); \
+ } \
+ ok(SendMessageA(hToolbar, TB_GETSTRING, MAKEWPARAM(260, (count)), (LPARAM)_buf) == -1, \
+ "Too many string in table\n"); \
+ }
+
+static void test_add_string(void)
+{
+ LPCSTR test1 = "a\0b\0";
+ LPCSTR test2 = "|a|b||\0";
+ LPCSTR ret1[] = {"a", "b"};
+ LPCSTR ret2[] = {"a", "b", "|a|b||"};
+ LPCSTR ret3[] = {"a", "b", "|a|b||", "p", "q"};
+ LPCSTR ret4[] = {"a", "b", "|a|b||", "p", "q", "p"};
+ LPCSTR ret5[] = {"a", "b", "|a|b||", "p", "q", "p", "p", "q"};
+ LPCSTR ret6[] = {"a", "b", "|a|b||", "p", "q", "p", "p", "q", "p", "", "q"};
+ LPCSTR ret7[] = {"a", "b", "|a|b||", "p", "q", "p", "p", "q", "p", "", "q", "br", "c", "d"};
+ HWND hToolbar = NULL;
+ TBBUTTON button;
+ int ret;
+
+ rebuild_toolbar(&hToolbar);
+ ret = SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)test1);
+ ok(ret == 0, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+ CHECK_STRING_TABLE(2, ret1);
+ ret = SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)test2);
+ ok(ret == 2, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+ CHECK_STRING_TABLE(3, ret2);
+
+ ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD1);
+ ok(ret == 3, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+ CHECK_STRING_TABLE(3, ret2);
+ ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD2);
+ ok(ret == 3, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+ CHECK_STRING_TABLE(5, ret3);
+ ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD3);
+ ok(ret == 5, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+ CHECK_STRING_TABLE(6, ret4);
+ ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD4);
+ ok(ret == 6, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+ CHECK_STRING_TABLE(8, ret5);
+ ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD5);
+ ok(ret == 8, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+ CHECK_STRING_TABLE(11, ret6);
+ ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD7);
+ ok(ret == 11, "TB_ADDSTRINGA - unexpected return %d\n", ret);
+ CHECK_STRING_TABLE(14, ret7);
+
+ ZeroMemory(&button, sizeof(button));
+ button.iString = (UINT_PTR)"Test";
+ SendMessageA(hToolbar, TB_INSERTBUTTONA, 0, (LPARAM)&button);
+ CHECK_STRING_TABLE(14, ret7);
+ SendMessageA(hToolbar, TB_ADDBUTTONSA, 1, (LPARAM)&button);
+ CHECK_STRING_TABLE(14, ret7);
+
+ DestroyWindow(hToolbar);
+}
+
+static void expect_hot_notify(int idold, int idnew)
+{
+ g_fExpectedHotItemOld = idold;
+ g_fExpectedHotItemNew = idnew;
+ g_fReceivedHotItemChange = FALSE;
+}
+
+#define check_hot_notify() \
+ ok(g_fReceivedHotItemChange, "TBN_HOTITEMCHANGE not received\n"); \
+ g_fExpectedHotItemOld = g_fExpectedHotItemNew = 0;
+
+static void test_hotitem(void)
+{
+ HWND hToolbar = NULL;
+ TBBUTTONINFO tbinfo;
+ LRESULT ret;
+
+ g_fBlockHotItemChange = FALSE;
+
+ rebuild_toolbar_with_buttons(&hToolbar);
+ /* set TBSTYLE_FLAT. comctl5 allows hot items only for such toolbars.
+ * comctl6 doesn't have this requirement even when theme == NULL */
+ SetWindowLong(hToolbar, GWL_STYLE, TBSTYLE_FLAT | GetWindowLong(hToolbar, GWL_STYLE));
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == -1, "Hot item: %ld, expected -1\n", ret);
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, 1, 0);
+ ok(ret == -1, "TB_SETHOTITEM returned %ld, expected -1\n", ret);
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == 1, "Hot item: %ld, expected 1\n", ret);
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, 2, 0);
+ ok(ret == 1, "TB_SETHOTITEM returned %ld, expected 1\n", ret);
+
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, 0xbeef, 0);
+ ok(ret == 2, "TB_SETHOTITEM returned %ld, expected 2\n", ret);
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == 2, "Hot item: %lx, expected 2\n", ret);
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, -0xbeef, 0);
+ ok(ret == 2, "TB_SETHOTITEM returned %ld, expected 2\n", ret);
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == -1, "Hot item: %lx, expected -1\n", ret);
+
+ expect_hot_notify(0, 7);
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, 3, 0);
+ ok(ret == -1, "TB_SETHOTITEM returned %ld, expected -1\n", ret);
+ check_hot_notify();
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == 3, "Hot item: %lx, expected 3\n", ret);
+ g_fBlockHotItemChange = TRUE;
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, 2, 0);
+ ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 2\n", ret);
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == 3, "Hot item: %lx, expected 3\n", ret);
+ g_fBlockHotItemChange = FALSE;
+
+ g_fReceivedHotItemChange = FALSE;
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, 0xbeaf, 0);
+ ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
+ ok(g_fReceivedHotItemChange == FALSE, "TBN_HOTITEMCHANGE received for invalid parameter\n");
+
+ g_fReceivedHotItemChange = FALSE;
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, 3, 0);
+ ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
+ ok(g_fReceivedHotItemChange == FALSE, "TBN_HOTITEMCHANGE received after a duplication\n");
+
+ expect_hot_notify(7, 0);
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, -0xbeaf, 0);
+ ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
+ check_hot_notify();
+ SendMessage(hToolbar, TB_SETHOTITEM, 3, 0);
+
+ /* setting disabled buttons will generate a notify with the button id but no button will be hot */
+ expect_hot_notify(7, 9);
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, 4, 0);
+ ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
+ check_hot_notify();
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == -1, "Hot item: %lx, expected -1\n", ret);
+ /* enabling the button won't change that */
+ SendMessage(hToolbar, TB_ENABLEBUTTON, 9, TRUE);
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == -1, "TB_SETHOTITEM returned %ld, expected -1\n", ret);
+
+ /* disabling a hot button works */
+ ret = SendMessage(hToolbar, TB_SETHOTITEM, 3, 0);
+ ok(ret == -1, "TB_SETHOTITEM returned %ld, expected -1\n", ret);
+ g_fReceivedHotItemChange = FALSE;
+ SendMessage(hToolbar, TB_ENABLEBUTTON, 7, FALSE);
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
+ ok(g_fReceivedHotItemChange == FALSE, "Unexpected TBN_HOTITEMCHANGE\n");
+
+ SendMessage(hToolbar, TB_SETHOTITEM, 1, 0);
+ tbinfo.cbSize = sizeof(TBBUTTONINFO);
+ tbinfo.dwMask = TBIF_STATE;
+ tbinfo.fsState = 0; /* disabled */
+ g_fReceivedHotItemChange = FALSE;
+ ok(SendMessage(hToolbar, TB_SETBUTTONINFO, 1, (LPARAM)&tbinfo) == TRUE, "TB_SETBUTTONINFO failed\n");
+ ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
+ ok(ret == 1, "TB_SETHOTITEM returned %ld, expected 1\n", ret);
+ ok(g_fReceivedHotItemChange == FALSE, "Unexpected TBN_HOTITEMCHANGE\n");
+
+ DestroyWindow(hToolbar);
+}
+
+#if 0 /* use this to generate more tests*/
+
+static void dump_sizes(HWND hToolbar)
+{
+ SIZE sz;
+ RECT r;
+ int count = SendMessage(hToolbar, TB_BUTTONCOUNT, 0, 0);
+ int i;
- case WM_CREATE:
+ GetClientRect(hToolbar, &r);
+ SendMessageA(hToolbar, TB_GETMAXSIZE, 0, &sz);
+ printf(" { {%d, %d, %d, %d}, {%d, %d}, %d, {", r.left, r.top, r.right, r.bottom,
+ sz.cx, sz.cy, count);
+ for (i=0; i<count; i++)
{
- TBBUTTON buttons[9];
- int i;
- HWND hToolbar;
- for (i=0; i<9; i++)
- MakeButton(buttons+i, 1000+i, TBSTYLE_CHECKGROUP, 0);
- MakeButton(buttons+3, 1003, TBSTYLE_SEP|TBSTYLE_GROUP, 0);
- MakeButton(buttons+6, 1006, TBSTYLE_SEP, 0);
-
- hToolbar = CreateToolbarEx(hWnd,
- WS_VISIBLE | WS_CLIPCHILDREN | CCS_TOP |
- WS_CHILD | TBSTYLE_LIST,
- 100,
- 0, NULL, (UINT)0,
- buttons, sizeof(buttons)/sizeof(buttons[0]),
- 0, 0, 20, 16, sizeof(TBBUTTON));
- ok(hToolbar != NULL, "Toolbar creation\n");
-
- SendMessage(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"test\000");
-
- /* test for exclusion working inside a separator-separated :-) group */
- SendMessage(hToolbar, TB_CHECKBUTTON, 1000, 1); /* press A1 */
- ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 pressed\n");
- ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1001, 0), "A2 not pressed\n");
-
- SendMessage(hToolbar, TB_CHECKBUTTON, 1004, 1); /* press A5, release A1 */
- ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1004, 0), "A5 pressed\n");
- ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 not pressed anymore\n");
-
- SendMessage(hToolbar, TB_CHECKBUTTON, 1005, 1); /* press A6, release A5 */
- ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 pressed\n");
- ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1004, 0), "A5 not pressed anymore\n");
-
- /* test for inter-group crosstalk, ie. two radio groups interfering with each other */
- SendMessage(hToolbar, TB_CHECKBUTTON, 1007, 1); /* press B2 */
- ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 still pressed, no inter-group crosstalk\n");
- ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 still not pressed\n");
- ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1007, 0), "B2 pressed\n");
-
- SendMessage(hToolbar, TB_CHECKBUTTON, 1000, 1); /* press A1 and ensure B group didn't suffer */
- ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 not pressed anymore\n");
- ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 pressed\n");
- ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1007, 0), "B2 still pressed\n");
-
- SendMessage(hToolbar, TB_CHECKBUTTON, 1008, 1); /* press B3, and ensure A group didn't suffer */
- ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 pressed\n");
- ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 pressed\n");
- ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1007, 0), "B2 not pressed\n");
- ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1008, 0), "B3 pressed\n");
- PostMessage(hWnd, WM_CLOSE, 0, 0);
- return 0;
+ SendMessageA(hToolbar, TB_GETITEMRECT, i, &r);
+ printf("%s{%3d, %3d, %3d, %3d}, ", (i%3==0 ? "\n " : ""), r.left, r.top, r.right, r.bottom);
}
- case WM_DESTROY:
- PostQuitMessage(0);
- break;
+ printf("\n }, }, \n");
+}
+
+#define check_sizes() dump_sizes(hToolbar);
+#define check_sizes_todo(todomask) dump_sizes(hToolbar);
+
+#else
+
+typedef struct
+{
+ RECT rcClient;
+ SIZE szMin;
+ INT nButtons;
+ RECT rcButtons[100];
+} tbsize_result_t;
- default:
- return DefWindowProcA(hWnd, msg, wParam, lParam);
+static tbsize_result_t tbsize_results[] =
+{
+ { {0, 0, 672, 26}, {100, 22}, 5, {
+ { 0, 2, 23, 24}, { 23, 2, 46, 24}, { 46, 2, 54, 24},
+ { 54, 2, 77, 24}, { 77, 2, 100, 24},
+ }, },
+ { {0, 0, 672, 26}, {146, 22}, 7, {
+ { 0, 2, 23, 24}, { 23, 2, 46, 24}, { 46, 2, 54, 24},
+ { 54, 2, 77, 24}, { 77, 2, 100, 24}, {100, 2, 123, 24},
+ { 0, 24, 23, 46},
+ }, },
+ { {0, 0, 672, 48}, {146, 22}, 7, {
+ { 0, 2, 23, 24}, { 23, 2, 46, 24}, { 46, 2, 54, 24},
+ { 54, 2, 77, 24}, { 77, 2, 100, 24}, {100, 2, 123, 24},
+ { 0, 24, 23, 46},
+ }, },
+ { {0, 0, 672, 26}, {146, 22}, 7, {
+ { 0, 2, 23, 24}, { 23, 2, 46, 24}, { 46, 2, 54, 24},
+ { 54, 2, 77, 24}, { 77, 2, 100, 24}, {100, 2, 123, 24},
+ {123, 2, 146, 24},
+ }, },
+ { {0, 0, 672, 26}, {192, 22}, 9, {
+ { 0, 2, 23, 24}, { 23, 2, 46, 24}, { 46, 2, 54, 24},
+ { 54, 2, 77, 24}, { 77, 2, 100, 24}, {100, 2, 123, 24},
+ {123, 2, 146, 24}, {146, 2, 169, 24}, {169, 2, 192, 24},
+ }, },
+ { {0, 0, 672, 92}, {882, 22}, 39, {
+ { 0, 2, 23, 24}, { 23, 2, 46, 24}, { 0, 2, 8, 29},
+ { 0, 29, 23, 51}, { 23, 29, 46, 51}, { 46, 29, 69, 51},
+ { 69, 29, 92, 51}, { 92, 29, 115, 51}, {115, 29, 138, 51},
+ {138, 29, 161, 51}, {161, 29, 184, 51}, {184, 29, 207, 51},
+ {207, 29, 230, 51}, {230, 29, 253, 51}, {253, 29, 276, 51},
+ {276, 29, 299, 51}, {299, 29, 322, 51}, {322, 29, 345, 51},
+ {345, 29, 368, 51}, {368, 29, 391, 51}, {391, 29, 414, 51},
+ {414, 29, 437, 51}, {437, 29, 460, 51}, {460, 29, 483, 51},
+ {483, 29, 506, 51}, {506, 29, 529, 51}, {529, 29, 552, 51},
+ {552, 29, 575, 51}, {575, 29, 598, 51}, {598, 29, 621, 51},
+ {621, 29, 644, 51}, {644, 29, 667, 51}, { 0, 51, 23, 73},
+ { 23, 51, 46, 73}, { 46, 51, 69, 73}, { 69, 51, 92, 73},
+ { 92, 51, 115, 73}, {115, 51, 138, 73}, {138, 51, 161, 73},
+ }, },
+ { {0, 0, 48, 226}, {23, 140}, 7, {
+ { 0, 2, 23, 24}, { 23, 2, 46, 24}, { 46, 2, 94, 24},
+ { 94, 2, 117, 24}, {117, 2, 140, 24}, {140, 2, 163, 24},
+ { 0, 24, 23, 46},
+ }, },
+ { {0, 0, 92, 226}, {23, 140}, 7, {
+ { 0, 2, 23, 24}, { 23, 2, 46, 24}, { 0, 24, 92, 32},
+ { 0, 32, 23, 54}, { 23, 32, 46, 54}, { 46, 32, 69, 54},
+ { 69, 32, 92, 54},
+ }, },
+ { {0, 0, 672, 26}, {194, 30}, 7, {
+ { 0, 2, 31, 32}, { 31, 2, 62, 32}, { 62, 2, 70, 32},
+ { 70, 2, 101, 32}, {101, 2, 132, 32}, {132, 2, 163, 32},
+ { 0, 32, 31, 62},
+ }, },
+ { {0, 0, 672, 64}, {194, 30}, 7, {
+ { 0, 2, 31, 32}, { 31, 2, 62, 32}, { 62, 2, 70, 32},
+ { 70, 2, 101, 32}, {101, 2, 132, 32}, {132, 2, 163, 32},
+ { 0, 32, 31, 62},
+ }, },
+ { {0, 0, 672, 64}, {194, 30}, 7, {
+ { 0, 0, 31, 30}, { 31, 0, 62, 30}, { 62, 0, 70, 30},
+ { 70, 0, 101, 30}, {101, 0, 132, 30}, {132, 0, 163, 30},
+ { 0, 30, 31, 60},
+ }, },
+ { {0, 0, 124, 226}, {31, 188}, 7, {
+ { 0, 0, 31, 30}, { 31, 0, 62, 30}, { 0, 30, 124, 38},
+ { 0, 38, 31, 68}, { 31, 38, 62, 68}, { 62, 38, 93, 68},
+ { 93, 38, 124, 68},
+ }, },
+ { {0, 0, 672, 26}, {146, 22}, 7, {
+ { 0, 2, 23, 24}, { 23, 2, 46, 24}, { 46, 2, 54, 24},
+ { 54, 2, 77, 24}, { 77, 2, 100, 24}, {100, 2, 123, 24},
+ {123, 2, 146, 24},
+ }, },
+ { {0, 0, 672, 26}, {146, 100}, 7, {
+ { 0, 0, 23, 100}, { 23, 0, 46, 100}, { 46, 0, 54, 100},
+ { 54, 0, 77, 100}, { 77, 0, 100, 100}, {100, 0, 123, 100},
+ {123, 0, 146, 100},
+ }, },
+ { {0, 0, 672, 26}, {215, 100}, 10, {
+ { 0, 0, 23, 100}, { 23, 0, 46, 100}, { 46, 0, 54, 100},
+ { 54, 0, 77, 100}, { 77, 0, 100, 100}, {100, 0, 123, 100},
+ {123, 0, 146, 100}, {146, 0, 169, 100}, {169, 0, 192, 100},
+ {192, 0, 215, 100},
+ }, },
+ { {0, 0, 672, 26}, {238, 39}, 11, {
+ { 0, 0, 23, 39}, { 23, 0, 46, 39}, { 46, 0, 54, 39},
+ { 54, 0, 77, 39}, { 77, 0, 100, 39}, {100, 0, 123, 39},
+ {123, 0, 146, 39}, {146, 0, 169, 39}, {169, 0, 192, 39},
+ {192, 0, 215, 39}, {215, 0, 238, 39},
+ }, },
+ { {0, 0, 672, 26}, {238, 22}, 11, {
+ { 0, 0, 23, 22}, { 23, 0, 46, 22}, { 46, 0, 54, 22},
+ { 54, 0, 77, 22}, { 77, 0, 100, 22}, {100, 0, 123, 22},
+ {123, 0, 146, 22}, {146, 0, 169, 22}, {169, 0, 192, 22},
+ {192, 0, 215, 22}, {215, 0, 238, 22},
+ }, },
+ { {0, 0, 672, 26}, {489, 39}, 3, {
+ { 0, 2, 163, 41}, {163, 2, 330, 41}, {330, 2, 493, 41},
+ }, },
+ { {0, 0, 672, 104}, {978, 24}, 6, {
+ { 0, 2, 163, 26}, {163, 2, 326, 26}, {326, 2, 489, 26},
+ {489, 2, 652, 26}, {652, 2, 819, 26}, {819, 2, 850, 26},
+ }, },
+ { {0, 0, 672, 28}, {978, 38}, 6, {
+ { 0, 0, 163, 38}, {163, 0, 326, 38}, {326, 0, 489, 38},
+ {489, 0, 652, 38}, {652, 0, 819, 38}, {819, 0, 850, 38},
+ }, },
+};
+
+static int tbsize_numtests = 0;
+
+#define check_sizes_todo(todomask) { \
+ RECT rc; \
+ int buttonCount, i, mask=(todomask); \
+ tbsize_result_t *res = &tbsize_results[tbsize_numtests]; \
+ assert(tbsize_numtests < sizeof(tbsize_results)/sizeof(tbsize_results[0])); \
+ GetClientRect(hToolbar, &rc); \
+ /*check_rect("client", rc, res->rcClient);*/ \
+ buttonCount = SendMessage(hToolbar, TB_BUTTONCOUNT, 0, 0); \
+ compare(buttonCount, res->nButtons, "%d"); \
+ for (i=0; i<min(buttonCount, res->nButtons); i++) { \
+ ok(SendMessageA(hToolbar, TB_GETITEMRECT, i, (LPARAM)&rc) == 1, "TB_GETITEMRECT\n"); \
+ if (!(mask&1)) { \
+ check_rect("button", rc, res->rcButtons[i]); \
+ } else {\
+ todo_wine { check_rect("button", rc, res->rcButtons[i]); } \
+ } \
+ mask >>= 1; \
+ } \
+ tbsize_numtests++; \
}
- return 0L;
+
+#define check_sizes() check_sizes_todo(0)
+
+#endif
+
+static TBBUTTON buttons1[] = {
+ {0, 10, TBSTATE_WRAP|TBSTATE_ENABLED, 0, {0, }, 0, -1},
+ {0, 11, 0, 0, {0, }, 0, -1},
+};
+static TBBUTTON buttons2[] = {
+ {0, 20, TBSTATE_ENABLED, 0, {0, }, 0, -1},
+ {0, 21, TBSTATE_ENABLED, 0, {0, }, 0, -1},
+};
+static TBBUTTON buttons3[] = {
+ {0, 30, TBSTATE_ENABLED, 0, {0, }, 0, 0},
+ {0, 31, TBSTATE_ENABLED, 0, {0, }, 0, 1},
+ {0, 32, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0, }, 0, 1},
+ {0, 33, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0, }, 0, (UINT_PTR)"Tst"}
+};
+
+static void test_sizes(void)
+{
+ HWND hToolbar = NULL;
+ HIMAGELIST himl;
+ int style;
+ int i;
+
+ rebuild_toolbar_with_buttons(&hToolbar);
+ style = GetWindowLong(hToolbar, GWL_STYLE);
+ ok(style == (WS_CHILD|WS_VISIBLE|CCS_TOP), "Invalid style %x\n", style);
+ check_sizes();
+ /* the TBSTATE_WRAP makes a second row */
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
+ check_sizes();
+ SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0);
+ check_sizes();
+ /* after setting the TBSTYLE_WRAPABLE the TBSTATE_WRAP is ignored */
+ SetWindowLong(hToolbar, GWL_STYLE, style|TBSTYLE_WRAPABLE);
+ check_sizes();
+ /* adding new buttons with TBSTYLE_WRAPABLE doesn't add a new row */
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
+ check_sizes();
+ /* only after adding enough buttons the bar will be wrapped on a
+ * separator and then on the first button */
+ for (i=0; i<15; i++)
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
+ check_sizes_todo(0x4);
+
+ rebuild_toolbar_with_buttons(&hToolbar);
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
+ /* setting the buttons vertical will only change the window client size */
+ SetWindowLong(hToolbar, GWL_STYLE, style | CCS_VERT);
+ SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
+ check_sizes_todo(0x3c);
+ /* with a TBSTYLE_WRAPABLE a wrapping will occur on the separator */
+ SetWindowLong(hToolbar, GWL_STYLE, style | TBSTYLE_WRAPABLE | CCS_VERT);
+ SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
+ check_sizes_todo(0x7c);
+
+ rebuild_toolbar_with_buttons(&hToolbar);
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
+ /* a TB_SETBITMAPSIZE changes button sizes*/
+ SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(24, 24));
+ check_sizes();
+
+ /* setting a TBSTYLE_FLAT doesn't change anything - even after a TB_AUTOSIZE */
+ SetWindowLong(hToolbar, GWL_STYLE, style | TBSTYLE_FLAT);
+ SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0);
+ check_sizes();
+ /* but after a TB_SETBITMAPSIZE the top margins is changed */
+ SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(20, 20));
+ SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(24, 24));
+ check_sizes();
+ /* some vertical toolbar sizes */
+ SetWindowLong(hToolbar, GWL_STYLE, style | TBSTYLE_FLAT | TBSTYLE_WRAPABLE | CCS_VERT);
+ check_sizes_todo(0x7c);
+
+ rebuild_toolbar_with_buttons(&hToolbar);
+ SetWindowLong(hToolbar, GWL_STYLE, style | TBSTYLE_FLAT);
+ /* newly added buttons will be use the previous margin */
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons2);
+ check_sizes();
+ /* TB_SETBUTTONSIZE can't be used to reduce the size of a button below the default */
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
+ ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(22, 21))==1, "TB_SETBUTTONSIZE\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
+ ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(5, 100))==1, "TB_SETBUTTONSIZE\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 100), "Unexpected button size\n");
+ ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(3, 3))==1, "TB_SETBUTTONSIZE\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
+ ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(5, 100))==1, "TB_SETBUTTONSIZE\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 100), "Unexpected button size\n");
+ check_sizes();
+ /* add some buttons with non-default sizes */
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons2);
+ SendMessageA(hToolbar, TB_INSERTBUTTON, -1, (LPARAM)&buttons2[0]);
+ check_sizes();
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[0]);
+ /* TB_ADDSTRING resets the size */
+ SendMessageA(hToolbar, TB_ADDSTRING, 0, (LPARAM)"A\0MMMMMMMMMMMMM\0");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 39), "Unexpected button size\n");
+ check_sizes();
+ /* TB_SETBUTTONSIZE can be used to crop the text */
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(3, 3));
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
+ check_sizes();
+ /* the default size is bitmap size + padding */
+ SendMessageA(hToolbar, TB_SETPADDING, 0, MAKELONG(1, 1));
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(3, 3));
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(17, 17), "Unexpected button size\n");
+ SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(3, 3));
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(3, 3));
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(4, 4), "Unexpected button size\n");
+
+ rebuild_toolbar(&hToolbar);
+ /* sending a TB_SETBITMAPSIZE with the same sizes is enough to make the button smaller */
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
+ SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(16, 15));
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 21), "Unexpected button size\n");
+
+ rebuild_toolbar(&hToolbar);
+ SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"A\0MMMMMMMMMMMMM\0");
+ /* the height is increased after a TB_ADDSTRING */
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 39), "Unexpected button size\n");
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
+ /* if a string is in the pool, even adding a button without a string resets the size */
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons2[0]);
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
+ /* an BTNS_AUTOSIZE button is also considered when computing the new size */
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[2]);
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(163, 39), "Unexpected button size\n");
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[0]);
+ check_sizes();
+ /* delete button doesn't change the buttons size */
+ SendMessageA(hToolbar, TB_DELETEBUTTON, 2, 0);
+ SendMessageA(hToolbar, TB_DELETEBUTTON, 1, 0);
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(163, 39), "Unexpected button size\n");
+ /* TB_INSERTBUTTONS will */
+ SendMessageA(hToolbar, TB_INSERTBUTTON, 1, (LPARAM)&buttons2[0]);
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
+
+ /* TB_HIDEBUTTON and TB_MOVEBUTTON doesn't force a recalc */
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
+ ok(SendMessageA(hToolbar, TB_MOVEBUTTON, 0, 1), "TB_MOVEBUTTON failed\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 100), "Unexpected button size\n");
+ ok(SendMessageA(hToolbar, TB_HIDEBUTTON, 20, TRUE), "TB_HIDEBUTTON failed\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 100), "Unexpected button size\n");
+ /* however changing the hidden flag with TB_SETSTATE does */
+ ok(SendMessageA(hToolbar, TB_SETSTATE, 20, TBSTATE_ENABLED|TBSTATE_HIDDEN), "TB_SETSTATE failed\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 100), "Unexpected button size\n");
+ ok(SendMessageA(hToolbar, TB_SETSTATE, 20, TBSTATE_ENABLED), "TB_SETSTATE failed\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
+
+ /* TB_SETIMAGELIST always changes the height but the width only if necessary */
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
+ himl = ImageList_LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP_80x15), 20, 2, CLR_NONE, IMAGE_BITMAP, LR_DEFAULTCOLOR);
+ ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl) == 0, "TB_SETIMAGELIST failed\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 21), "Unexpected button size\n");
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 100), "Unexpected button size\n");
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(1, 1));
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 21), "Unexpected button size\n");
+ ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, 0) == (LRESULT)himl, "TB_SETIMAGELIST failed\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 7), "Unexpected button size\n");
+ SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(1, 1));
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(8, 7), "Unexpected button size\n");
+ ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl) == 0, "TB_SETIMAGELIST failed\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 21), "Unexpected button size\n");
+ /* the text is taken into account */
+ SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"A\0MMMMMMMMMMMMM\0");
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 4, (LPARAM)buttons3);
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(163, 38), "Unexpected button size\n");
+ ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, 0) == (LRESULT)himl, "TB_SETIMAGELIST failed\n");
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(163, 24), "Unexpected button size\n");
+ /* the style change also comes into effect */
+ check_sizes();
+ SetWindowLong(hToolbar, GWL_STYLE, GetWindowLong(hToolbar, GWL_STYLE) | TBSTYLE_FLAT);
+ ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl) == 0, "TB_SETIMAGELIST failed\n");
+ check_sizes_todo(0x30); /* some small problems with BTNS_AUTOSIZE button sizes */
+
+ rebuild_toolbar(&hToolbar);
+ ImageList_Destroy(himl);
+
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[3]);
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 39), "Unexpected button size\n");
+ SendMessageA(hToolbar, TB_DELETEBUTTON, 0, 0);
+ ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 39), "Unexpected button size\n");
+
+ DestroyWindow(hToolbar);
+}
+
+static void test_getbuttoninfo(void)
+{
+ HWND hToolbar = NULL;
+ int i;
+
+ rebuild_toolbar_with_buttons(&hToolbar);
+ for (i = 0; i < 128; i++)
+ {
+ TBBUTTONINFO tbi;
+ int ret;
+
+ tbi.cbSize = i;
+ tbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
+ ret = (int)SendMessage(hToolbar, TB_GETBUTTONINFO, 0, (LPARAM)&tbi);
+ if (i == sizeof(TBBUTTONINFO)) {
+ compare(ret, 0, "%d");
+ } else {
+ compare(ret, -1, "%d");
+ }
+ }
+ DestroyWindow(hToolbar);
+}
+
+static void test_createtoolbarex(void)
+{
+ HWND hToolbar;
+ TBBUTTON btns[3];
+ ZeroMemory(&btns, sizeof(btns));
+
+ hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
+ 3, 20, 20, 16, 16, sizeof(TBBUTTON));
+ CHECK_IMAGELIST(16, 20, 20);
+ compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0x1a001b, "%x");
+ DestroyWindow(hToolbar);
+
+ hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
+ 3, 4, 4, 16, 16, sizeof(TBBUTTON));
+ CHECK_IMAGELIST(32, 4, 4);
+ compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0xa000b, "%x");
+ DestroyWindow(hToolbar);
+
+ hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
+ 3, 0, 8, 12, 12, sizeof(TBBUTTON));
+ CHECK_IMAGELIST(16, 12, 12);
+ compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0x120013, "%x");
+ DestroyWindow(hToolbar);
+
+ hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
+ 3, -1, 8, 12, 12, sizeof(TBBUTTON));
+ CHECK_IMAGELIST(16, 12, 8);
+ compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0xe0013, "%x");
+ DestroyWindow(hToolbar);
+
+ hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
+ 3, -1, 8, -1, 12, sizeof(TBBUTTON));
+ CHECK_IMAGELIST(16, 16, 8);
+ compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0xe0017, "%x");
+ DestroyWindow(hToolbar);
+
+ hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
+ 3, 0, 0, 12, -1, sizeof(TBBUTTON));
+ CHECK_IMAGELIST(16, 12, 16);
+ compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0x160013, "%x");
+ DestroyWindow(hToolbar);
+
+ hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
+ 3, 0, 0, 0, 12, sizeof(TBBUTTON));
+ CHECK_IMAGELIST(16, 16, 16);
+ compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0x160017, "%x");
+ DestroyWindow(hToolbar);
+}
+
+static void test_dispinfo(void)
+{
+ HWND hToolbar = NULL;
+ const TBBUTTON buttons_disp[] = {
+ {-1, 20, TBSTATE_ENABLED, 0, {0, }, 0, -1},
+ {0, 21, TBSTATE_ENABLED, 0, {0, }, 0, -1},
+ };
+ BOOL ret;
+
+ rebuild_toolbar(&hToolbar);
+ SendMessageA(hToolbar, TB_LOADIMAGES, IDB_HIST_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
+ SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons_disp);
+ g_dwExpectedDispInfoMask = 1;
+ /* Some TBN_GETDISPINFO tests will be done in MyWnd_Notify function.
+ * We will receive TBN_GETDISPINFOW even if the control is ANSI */
+ compare((BOOL)SendMessageA(hToolbar, CCM_GETUNICODEFORMAT, 0, 0), 0, "%d");
+ ShowWindow(hToolbar, SW_SHOW);
+ UpdateWindow(hToolbar);
+
+ ret = (BOOL)SendMessageA(hToolbar, CCM_SETUNICODEFORMAT, TRUE, 0);
+ compare(ret, FALSE, "%d");
+ compare(SendMessageA(hToolbar, CCM_GETUNICODEFORMAT, 0, 0), 1L, "%ld");
+ InvalidateRect(hToolbar, NULL, FALSE);
+ UpdateWindow(hToolbar);
+
+ ret = (BOOL)SendMessageA(hToolbar, CCM_SETUNICODEFORMAT, FALSE, 0);
+ compare(ret, TRUE, "%d");
+ compare(SendMessageA(hToolbar, CCM_GETUNICODEFORMAT, 0, 0), 0L, "%ld");
+ InvalidateRect(hToolbar, NULL, FALSE);
+ UpdateWindow(hToolbar);
+
+ DestroyWindow(hToolbar);
+ g_dwExpectedDispInfoMask = 0;
+}
+
+typedef struct
+{
+ int nRows;
+ BOOL bLarger;
+ int expectedRows;
+} tbrows_result_t;
+
+static tbrows_result_t tbrows_results[] =
+{
+ {1, TRUE, 1}, /* 0: Simple case 9 in a row */
+ {2, TRUE, 2}, /* 1: Another simple case 5 on one row, 4 on another*/
+ {3, FALSE, 3}, /* 2: 3 lines - should be 3 lines of 3 buttons */
+ {8, FALSE, 5}, /* 3: 8 lines - should be 5 lines of 2 buttons */
+ {8, TRUE, 9}, /* 4: 8 lines but grow - should be 9 lines */
+ {1, TRUE, 1} /* 5: Back to simple case */
+};
+
+static void test_setrows(void)
+{
+ TBBUTTON buttons[9];
+ HWND hToolbar;
+ int i;
+
+ for (i=0; i<9; i++)
+ MakeButton(buttons+i, 1000+i, TBSTYLE_FLAT | TBSTYLE_CHECKGROUP, 0);
+
+ /* Test 1 - 9 buttons */
+ hToolbar = CreateToolbarEx(hMainWnd,
+ WS_VISIBLE | WS_CLIPCHILDREN | WS_CHILD | CCS_NORESIZE | CCS_NOPARENTALIGN
+ | CCS_NOMOVEY | CCS_TOP,
+ 0,
+ 0, NULL, (UINT)0,
+ buttons, sizeof(buttons)/sizeof(buttons[0]),
+ 20, 20, 0, 0, sizeof(TBBUTTON));
+ ok(hToolbar != NULL, "Toolbar creation\n");
+ ok(SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
+
+ /* test setting rows to each of 1-10 with bLarger true and false */
+ for (i=0; i<(sizeof(tbrows_results) / sizeof(tbrows_result_t)); i++) {
+ RECT rc;
+ int rows;
+
+ memset(&rc, 0xCC, sizeof(rc));
+ SendMessageA(hToolbar, TB_SETROWS,
+ MAKELONG(tbrows_results[i].nRows, tbrows_results[i].bLarger),
+ (LONG) &rc);
+
+ rows = SendMessageA(hToolbar, TB_GETROWS, MAKELONG(0,0), MAKELONG(0,0));
+ ok(rows == tbrows_results[i].expectedRows,
+ "[%d] Unexpected number of rows %d (expected %d)\n", i, rows,
+ tbrows_results[i].expectedRows);
+ }
+
+ DestroyWindow(hToolbar);
}
START_TEST(toolbar)
WNDCLASSA wc;
MSG msg;
RECT rc;
- HWND hMainWnd;
-
+
InitCommonControls();
-
+
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandleA(NULL);
wc.hIcon = NULL;
- wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_IBEAM));
+ wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyTestWnd";
wc.lpfnWndProc = MyWndProc;
RegisterClassA(&wc);
-
- hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
+
+ hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
GetClientRect(hMainWnd, &rc);
+ ShowWindow(hMainWnd, SW_SHOW);
+
+ basic_test();
+ test_add_bitmap();
+ test_add_string();
+ test_hotitem();
+ test_sizes();
+ test_getbuttoninfo();
+ test_createtoolbarex();
+ test_dispinfo();
+ test_setrows();
+ PostQuitMessage(0);
while(GetMessageA(&msg,0,0,0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
+ DestroyWindow(hMainWnd);
}
assert(hwnd);
style = GetWindowLong(hwnd, GWL_STYLE);
- trace("style = %08lx\n", style);
+ trace("style = %08x\n", style);
exp_style = 0x7fffffff | WS_POPUP;
exp_style &= ~(WS_CHILD | WS_MAXIMIZE | WS_BORDER | WS_DLGFRAME);
- ok(style == exp_style,"wrong style %08lx/%08lx\n", style, exp_style);
+ ok(style == exp_style,"wrong style %08x/%08x\n", style, exp_style);
DestroyWindow(hwnd);
assert(hwnd);
style = GetWindowLong(hwnd, GWL_STYLE);
- trace("style = %08lx\n", style);
+ trace("style = %08x\n", style);
ok(style == (WS_POPUP | WS_CLIPSIBLINGS | WS_BORDER),
- "wrong style %08lx\n", style);
+ "wrong style %08x\n", style);
DestroyWindow(hwnd);
--- /dev/null
+/* Unit tests for the track bar control.
+ *
+ * Copyright 2007 Keith Stevens
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <assert.h>
+#include <windows.h>
+#include <commctrl.h>
+#include <stdio.h>
+
+#include "wine/test.h"
+#include "msg.h"
+
+#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
+#define NUM_MSG_SEQUENCE 2
+#define PARENT_SEQ_INDEX 0
+#define TRACKBAR_SEQ_INDEX 1
+
+
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCE];
+
+static const struct message create_parent_wnd_seq[] = {
+ { WM_GETMINMAXINFO, sent },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { WM_SHOWWINDOW, sent|wparam, 1 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_ACTIVATEAPP, sent|wparam, 1 },
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATE, sent|wparam, 1 },
+ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+ { WM_IME_NOTIFY, sent|defwinproc|optional },
+ { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+ /* Win9x adds SWP_NOZORDER below */
+ { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
+ { WM_NCCALCSIZE, sent|wparam|optional, 1 },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
+ { 0 }
+};
+
+static const struct message create_trackbar_wnd_seq[] = {
+ {0}
+};
+
+static const struct message parent_empty_test_seq[] = {
+ {0}
+};
+
+static const struct message parent_create_trackbar_wnd_seq[] = {
+ { WM_NOTIFYFORMAT, sent},
+ { 0x0129, sent}, /* should be WM_QUERYUISTATE instead of 0x0129 */
+ { WM_WINDOWPOSCHANGING, sent},
+ { WM_NCACTIVATE, sent},
+ { PBT_APMRESUMECRITICAL, sent},
+ { WM_WINDOWPOSCHANGING, sent},
+ { PBT_APMRESUMESTANDBY, sent},
+ { WM_IME_SETCONTEXT, sent|optional},
+ { WM_IME_NOTIFY, sent|optional},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ {0}
+};
+
+static const struct message parent_new_window_test_seq[] = {
+ { WM_WINDOWPOSCHANGING, sent},
+ { WM_NCACTIVATE, sent},
+ { PBT_APMRESUMECRITICAL, sent},
+ { WM_IME_SETCONTEXT, sent|defwinproc|optional},
+ { WM_IME_NOTIFY, sent|defwinproc|optional},
+ { WM_SETFOCUS, sent|defwinproc},
+ { WM_NOTIFYFORMAT, sent},
+ { 0x0129, sent}, /* should be WM_QUERYUISTATE instead of 0x0129*/
+ {0}
+};
+
+static const struct message buddy_window_test_seq[] = {
+ { TBM_GETBUDDY, sent|wparam, TRUE},
+ { TBM_SETBUDDY, sent|wparam, FALSE},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_SETBUDDY, sent|wparam, FALSE},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETBUDDY, sent|wparam, TRUE},
+ { TBM_SETBUDDY, sent|wparam, TRUE},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_SETBUDDY, sent|wparam, TRUE},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETBUDDY, sent|wparam, FALSE},
+ { TBM_GETBUDDY, sent|wparam, TRUE},
+ {0}
+};
+
+static const struct message parent_buddy_window_test_seq[] = {
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ {0}
+};
+
+static const struct message line_size_test_seq[] = {
+ { TBM_SETLINESIZE, sent|lparam, 0, 10},
+ { TBM_SETLINESIZE, sent|lparam, 0, 4},
+ { TBM_GETLINESIZE, sent},
+ {0}
+};
+
+static const struct message page_size_test_seq[] = {
+ { TBM_SETPAGESIZE, sent|lparam, 0, 10},
+ { TBM_SETPAGESIZE, sent|lparam, 0, -1},
+ { TBM_GETPAGESIZE, sent},
+ {0}
+};
+
+static const struct message position_test_seq[] = {
+ { TBM_SETPOS, sent|wparam|lparam, TRUE, -1},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETPOS, sent},
+ { TBM_SETPOS, sent|wparam|lparam, TRUE, 5},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETPOS, sent},
+ { TBM_SETPOS, sent|wparam|lparam, TRUE, 1000},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETPOS, sent},
+ { TBM_SETPOS, sent|wparam|lparam, FALSE, 20},
+ { TBM_GETPOS, sent},
+ { TBM_GETPOS, sent},
+ {0}
+};
+
+static const struct message parent_position_test_seq[] = {
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ {0}
+};
+
+static const struct message range_test_seq[] = {
+ { TBM_SETRANGE, sent|wparam|lparam, TRUE, MAKELONG(0, 10)},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETRANGEMAX, sent},
+ { TBM_GETRANGEMIN, sent},
+ { TBM_SETRANGE, sent|wparam|lparam, TRUE, MAKELONG(-1, 1000)},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETRANGEMAX, sent},
+ { TBM_GETRANGEMIN, sent},
+ { TBM_SETRANGE, sent|wparam|lparam, TRUE, MAKELONG(10, 0)},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETRANGEMAX, sent},
+ { TBM_GETRANGEMIN, sent},
+ { TBM_SETRANGE, sent|wparam|lparam, FALSE, MAKELONG(0, 10)},
+ { TBM_GETRANGEMAX, sent},
+ { TBM_GETRANGEMIN, sent},
+ { TBM_SETRANGEMAX, sent|wparam|lparam, TRUE, 10},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETRANGEMAX, sent},
+ { TBM_SETRANGEMAX, sent|wparam|lparam, TRUE, -1},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETRANGEMAX, sent},
+ { TBM_SETRANGEMAX, sent|wparam|lparam, FALSE, 10},
+ { TBM_GETRANGEMAX, sent},
+ { TBM_SETRANGEMIN, sent|wparam|lparam, TRUE, 0},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETRANGEMIN, sent},
+ { TBM_SETRANGEMIN, sent|wparam|lparam, TRUE, 10},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETRANGEMIN, sent},
+ { TBM_SETRANGEMIN, sent|wparam|lparam, TRUE, -10},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETRANGEMIN, sent},
+ { TBM_SETRANGEMIN, sent|wparam|lparam, FALSE, 5},
+ { TBM_GETRANGEMIN, sent},
+ { TBM_GETRANGEMAX, sent},
+ { TBM_GETRANGEMIN, sent},
+ {0}
+};
+
+static const struct message parent_range_test_seq[] = {
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ {0}
+};
+
+static const struct message selection_test_seq[] = {
+ { TBM_SETSEL, sent|wparam|lparam, TRUE, MAKELONG(0, 10)},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETSELEND, sent},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSEL, sent|wparam|lparam, TRUE, MAKELONG(5, 20)},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETSELEND, sent},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSEL, sent|wparam|lparam, FALSE, MAKELONG(5, 10)},
+ { TBM_GETSELEND, sent},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSELEND, sent|wparam|lparam, TRUE, 10},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETSELEND, sent},
+ { TBM_SETSELEND, sent|wparam|lparam, TRUE, 20},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETSELEND, sent},
+ { TBM_SETSELEND, sent|wparam|lparam, TRUE, 4},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETSELEND, sent},
+ { TBM_SETSELEND, sent|wparam|lparam, FALSE, 2},
+ { TBM_GETSELEND, sent},
+ { TBM_GETSELEND, sent},
+ { TBM_SETSELSTART, sent|wparam|lparam, TRUE, 5},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSELSTART, sent|wparam|lparam, TRUE, 0},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSELSTART, sent|wparam|lparam, TRUE, 20},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSELSTART, sent|wparam|lparam, FALSE, 8},
+ { TBM_GETSELSTART, sent},
+ { TBM_GETSELSTART, sent},
+ {0}
+};
+
+static const struct message parent_selection_test_seq[] = {
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ {0}
+};
+
+static const struct message tic_settings_test_seq[] = {
+ { TBM_SETTIC, sent|lparam, 0, 0},
+ { TBM_SETTIC, sent|lparam, 0, 5},
+ { TBM_SETTIC, sent|lparam, 0, 10},
+ { TBM_SETTIC, sent|lparam, 0, 20},
+ { TBM_SETRANGE, sent|wparam|lparam, TRUE, MAKELONG(0,10)},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_SETTICFREQ, sent|wparam, 2},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETNUMTICS, sent},
+ { TBM_SETTICFREQ, sent|wparam, 5},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETNUMTICS, sent},
+ { TBM_SETTICFREQ, sent|wparam, 15},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETNUMTICS, sent},
+ { TBM_GETNUMTICS, sent},
+ {0}
+};
+
+static const struct message parent_tic_settings_test_seq[] = {
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ {0}
+};
+
+static const struct message thumb_length_test_seq[] = {
+ { TBM_SETTHUMBLENGTH, sent|wparam|lparam, 15, 0},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETTHUMBLENGTH, sent},
+ { TBM_SETTHUMBLENGTH, sent|wparam|lparam, 20, 0},
+ { WM_PAINT, sent|defwinproc},
+ { TBM_GETTHUMBLENGTH, sent},
+ { TBM_GETTHUMBLENGTH, sent},
+ {0}
+};
+
+static const struct message parent_thumb_length_test_seq[] = {
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ { WM_CTLCOLORSTATIC, sent},
+ { WM_NOTIFY, sent},
+ {0}
+};
+
+static const struct message tic_placement_test_seq[] = {
+ { TBM_GETPTICS, sent},
+ { TBM_GETTIC, sent|wparam, 0},
+ { TBM_GETTIC, sent|wparam, 4},
+ { TBM_GETTIC, sent|wparam, 11},
+ { TBM_GETTICPOS, sent|wparam, 0},
+ { TBM_GETTICPOS, sent|wparam, 4},
+ {0}
+};
+
+static const struct message tool_tips_test_seq[] = {
+ { TBM_SETTIPSIDE, sent|wparam, TBTS_TOP},
+ { TBM_SETTIPSIDE, sent|wparam, TBTS_LEFT},
+ { TBM_SETTIPSIDE, sent|wparam, TBTS_BOTTOM},
+ { TBM_SETTIPSIDE, sent|wparam, TBTS_RIGHT},
+ { TBM_SETTOOLTIPS, sent},
+ { TBM_GETTOOLTIPS, sent},
+ { TBM_SETTOOLTIPS, sent},
+ { TBM_GETTOOLTIPS, sent},
+ { TBM_SETTOOLTIPS, sent},
+ { TBM_GETTOOLTIPS, sent},
+ { TBM_GETTOOLTIPS, sent},
+ {0}
+};
+
+static const struct message unicode_test_seq[] = {
+ { TBM_SETUNICODEFORMAT, sent|wparam, TRUE},
+ { TBM_SETUNICODEFORMAT, sent|wparam, FALSE},
+ { TBM_GETUNICODEFORMAT, sent},
+ {0}
+};
+
+static const struct message ignore_selection_test_seq[] = {
+ { TBM_SETSEL, sent|wparam|lparam, TRUE, MAKELONG(0,10)},
+ { TBM_GETSELEND, sent},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSEL, sent|wparam|lparam, FALSE, MAKELONG(0,10)},
+ { TBM_GETSELEND, sent},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSELEND, sent|wparam|lparam, TRUE,0},
+ { TBM_GETSELEND, sent},
+ { TBM_SETSELEND, sent|wparam|lparam, TRUE, 10},
+ { TBM_GETSELEND, sent},
+ { TBM_SETSELEND, sent|wparam|lparam, FALSE,0},
+ { TBM_GETSELEND, sent},
+ { TBM_SETSELSTART, sent|wparam|lparam, TRUE,0},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSELSTART, sent|wparam|lparam, TRUE, 10},
+ { TBM_GETSELSTART, sent},
+ { TBM_SETSELSTART, sent|wparam|lparam, FALSE,0},
+ { TBM_GETSELSTART, sent},
+ {0}
+};
+
+struct subclass_info
+{
+ WNDPROC oldproc;
+};
+
+static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ /* do not log painting messages */
+ if (message != WM_PAINT &&
+ message != WM_ERASEBKGND &&
+ message != WM_NCPAINT &&
+ message != WM_NCHITTEST &&
+ message != WM_GETTEXT &&
+ message != WM_GETICON &&
+ message != WM_DEVICECHANGE)
+ {
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, PARENT_SEQ_INDEX, &msg);
+ }
+
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static BOOL register_parent_wnd_class(void){
+ WNDCLASSA cls;
+
+ cls.style = 0;
+ cls.lpfnWndProc = parent_wnd_proc;
+ cls.cbClsExtra = 0;
+ cls.cbWndExtra = 0;
+ cls.hInstance = GetModuleHandleA(NULL);
+ cls.hIcon = 0;
+ cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
+ cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+ cls.lpszMenuName = NULL;
+ cls.lpszClassName = "Trackbar test parent class";
+ return RegisterClassA(&cls);
+}
+
+static HWND create_parent_window(void){
+ if (!register_parent_wnd_class())
+ return NULL;
+
+ return CreateWindowEx(0, "Trackbar test parent class",
+ "Trackbar test parent window",
+ WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
+ WS_MAXIMIZEBOX | WS_VISIBLE,
+ 0, 0, 100, 100,
+ GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
+}
+
+static LRESULT WINAPI trackbar_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
+ struct subclass_info *info = (struct subclass_info *) GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, TRACKBAR_SEQ_INDEX, &msg);
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static HWND create_trackbar(DWORD style, HWND parent){
+ struct subclass_info *info;
+ HWND hWndTrack;
+ RECT rect;
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ GetClientRect(parent, &rect);
+ hWndTrack = CreateWindowEx(
+ 0, TRACKBAR_CLASS,"Trackbar Control", style,
+ rect.right,rect.bottom, 100, 50,
+ parent, NULL,GetModuleHandleA(NULL) ,NULL);
+
+ if (!hWndTrack)
+ {
+ HeapFree(GetProcessHeap(), 0, info);
+ return NULL;
+ }
+
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(hWndTrack, GWLP_WNDPROC, (LONG_PTR)trackbar_subclass_proc);
+
+ SetWindowLongPtrA(hWndTrack, GWLP_USERDATA, (LONG_PTR)info);
+
+ return hWndTrack;
+}
+
+/* test functions for setters, getters, and sequences */
+
+static void test_trackbar_buddy(HWND hWndTrackbar){
+ HWND hWndLeftBuddy;
+ HWND hWndRightBuddy;
+ HWND hWndCurrentBuddy;
+ HWND rTest;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+
+ hWndLeftBuddy = (HWND) CreateWindowEx(0, STATUSCLASSNAME, NULL, 0,
+ 0,0,300,20, NULL, NULL, NULL, NULL);
+ ok(hWndLeftBuddy != NULL, "Expected non NULL value\n");
+
+ if (hWndLeftBuddy != NULL){
+ hWndCurrentBuddy = (HWND) SendMessage(hWndTrackbar, TBM_GETBUDDY, TRUE, 0);
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_SETBUDDY, FALSE, (LPARAM) hWndLeftBuddy);
+ ok(rTest == hWndCurrentBuddy, "Expected hWndCurrentBuddy\n");
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_SETBUDDY, FALSE, (LPARAM) hWndLeftBuddy);
+ ok(rTest == hWndLeftBuddy, "Expected hWndLeftBuddy\n");
+ } else
+ skip ("left buddy control not present?\n");
+
+ hWndRightBuddy = (HWND) CreateWindowEx(0, STATUSCLASSNAME, NULL, 0,
+ 0,0,300,20,NULL,NULL, NULL, NULL);
+
+ ok(hWndRightBuddy != NULL, "expected non NULL value\n");
+
+ /* test TBM_SETBUDDY */
+ if (hWndRightBuddy != NULL){
+ hWndCurrentBuddy = (HWND) SendMessage(hWndTrackbar, TBM_GETBUDDY, TRUE, 0);
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_SETBUDDY, TRUE, (LPARAM) hWndRightBuddy);
+ ok(rTest == hWndCurrentBuddy, "Expected hWndCurrentBuddy\n");
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_SETBUDDY, TRUE, (LPARAM) hWndRightBuddy);
+ ok(rTest == hWndRightBuddy, "Expected hWndRightbuddy\n");
+ } else
+ skip("Right buddy control not present?\n");
+
+ /* test TBM_GETBUDDY */
+ if (hWndLeftBuddy != NULL){
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_GETBUDDY, FALSE, 0);
+ ok(rTest == hWndLeftBuddy, "Expected hWndLeftBuddy\n");
+ DestroyWindow(hWndLeftBuddy);
+ }
+ if (hWndRightBuddy != NULL){
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_GETBUDDY, TRUE,0);
+ ok(rTest == hWndRightBuddy, "Expected hWndRightBuddy\n");
+ DestroyWindow(hWndRightBuddy);
+ }
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, buddy_window_test_seq, "buddy test sequence", TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_buddy_window_test_seq, "parent buddy test seq", TRUE);
+
+}
+
+static void test_line_size(HWND hWndTrackbar){
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+
+ /* test TBM_SETLINESIZE */
+ r = SendMessage(hWndTrackbar, TBM_SETLINESIZE, 0, 10);
+ r = SendMessage(hWndTrackbar, TBM_SETLINESIZE, 0, 4);
+ expect(10, r);
+
+ /* test TBM_GETLINESIZE */
+ r = SendMessage(hWndTrackbar, TBM_GETLINESIZE, 0,0);
+ expect(4, r);
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, line_size_test_seq, "linesize test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_empty_test_seq, "parent line test sequence", FALSE);
+}
+
+
+static void test_page_size(HWND hWndTrackbar){
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+
+ /* test TBM_SETPAGESIZE */
+ r = SendMessage(hWndTrackbar, TBM_SETPAGESIZE, 0, 10);
+ expect(20, r);
+ r = SendMessage(hWndTrackbar, TBM_SETPAGESIZE, 0, -1);
+ expect(10, r);
+
+ /* test TBM_GETPAGESIZE */
+ r = SendMessage(hWndTrackbar, TBM_GETPAGESIZE, 0,0);
+ todo_wine{
+ expect(20, r);
+ }
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, page_size_test_seq, "page size test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_empty_test_seq, "parent page size test sequence", FALSE);
+}
+
+static void test_position(HWND hWndTrackbar){
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ /* test TBM_SETPOS */
+ SendMessage(hWndTrackbar, TBM_SETPOS, TRUE, -1);
+ r = SendMessage(hWndTrackbar, TBM_GETPOS, 0, 0);
+ expect(0, r);
+ SendMessage(hWndTrackbar, TBM_SETPOS, TRUE, 5);
+ r = SendMessage(hWndTrackbar, TBM_GETPOS, 0,0);
+ expect(5, r);
+ SendMessage(hWndTrackbar, TBM_SETPOS, TRUE, 1000);
+ r = SendMessage(hWndTrackbar, TBM_GETPOS, 0,0);
+ expect(100, r);
+ SendMessage(hWndTrackbar, TBM_SETPOS, FALSE, 20);
+ r = SendMessage(hWndTrackbar, TBM_GETPOS, 0,0);
+ expect(20, r);
+
+ /* test TBM_GETPOS */
+ r = SendMessage(hWndTrackbar, TBM_GETPOS, 0,0);
+ expect(20, r);
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, position_test_seq, "position test sequence", TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_position_test_seq, "parent position test sequence", TRUE);
+}
+
+static void test_range(HWND hWndTrackbar){
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ /* test TBM_SETRANGE */
+ SendMessage(hWndTrackbar, TBM_SETRANGE, TRUE, MAKELONG(0, 10));
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMAX, 0,0);
+ expect(10, r);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0,0);
+ expect(0, r);
+ SendMessage(hWndTrackbar, TBM_SETRANGE, TRUE, MAKELONG(-1, 1000));
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMAX, 0,0);
+ expect(1000, r);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0,0);
+ expect(-1, r);
+ SendMessage(hWndTrackbar, TBM_SETRANGE, TRUE, MAKELONG(10, 0));
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMAX, 0,0);
+ expect(0, r);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0,0);
+ expect(10, r);
+ SendMessage(hWndTrackbar, TBM_SETRANGE, FALSE, MAKELONG(0,10));
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMAX, 0,0);
+ expect(10, r);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0,0);
+ expect(0, r);
+
+ /*test TBM_SETRANGEMAX */
+ SendMessage(hWndTrackbar, TBM_SETRANGEMAX, TRUE, 10);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMAX, 0,0);
+ expect(10, r);
+ SendMessage(hWndTrackbar, TBM_SETRANGEMAX, TRUE, -1);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMAX, 0,0);
+ expect(-1, r);
+ SendMessage(hWndTrackbar, TBM_SETRANGEMAX, FALSE, 10);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMAX, 0,0);
+ expect(10, r);
+
+ /* testing TBM_SETRANGEMIN */
+ SendMessage(hWndTrackbar, TBM_SETRANGEMIN, TRUE, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0,0);
+ expect(0, r);
+ SendMessage(hWndTrackbar, TBM_SETRANGEMIN, TRUE, 10);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0,0);
+ expect(10, r);
+ SendMessage(hWndTrackbar, TBM_SETRANGEMIN, TRUE, -10);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0,0);
+ expect(-10, r);
+ SendMessage(hWndTrackbar, TBM_SETRANGEMIN, FALSE, 5);
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0,0);
+ expect(5, r);
+
+ /* test TBM_GETRANGEMAX */
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMAX, 0,0);
+ expect(10, r);
+
+ /* test TBM_GETRANGEMIN */
+ r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0,0);
+ expect(5, r);
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, range_test_seq, "range test sequence", TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_range_test_seq, "parent range test sequence", TRUE);
+}
+
+static void test_selection(HWND hWndTrackbar){
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ /* test TBM_SETSEL */
+ SendMessage(hWndTrackbar, TBM_SETSEL, TRUE, MAKELONG(0,10));
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(10, r);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(5, r);
+ SendMessage(hWndTrackbar, TBM_SETSEL, TRUE, MAKELONG(5, 20));
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(10, r);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(5, r);
+ SendMessage(hWndTrackbar, TBM_SETSEL, FALSE, MAKELONG(5, 10));
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(10, r);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(5, r);
+
+ /* test TBM_SETSELEND */
+ SendMessage(hWndTrackbar, TBM_SETSELEND, TRUE, 10);
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(10, r);
+ SendMessage(hWndTrackbar, TBM_SETSELEND, TRUE, 20);
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(10, r);
+ SendMessage(hWndTrackbar, TBM_SETSELEND, TRUE, 4);
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(4, r);
+ SendMessage(hWndTrackbar, TBM_SETSELEND, FALSE, 2);
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(2, r);
+
+ /* test TBM_GETSELEND */
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(2, r);
+
+ /* testing TBM_SETSELSTART */
+ SendMessage(hWndTrackbar, TBM_SETSELSTART, TRUE, 5);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(5, r);
+ SendMessage(hWndTrackbar, TBM_SETSELSTART, TRUE, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(5, r);
+ SendMessage(hWndTrackbar, TBM_SETSELSTART, TRUE, 20);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(20, r);
+ SendMessage(hWndTrackbar, TBM_SETSELSTART, FALSE, 8);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(8, r);
+
+ /* test TBM_GETSELSTART */
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(8, r);
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, selection_test_seq, "selection test sequence", TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_selection_test_seq, "parent selection test seqence", TRUE);
+}
+
+static void test_thumb_length(HWND hWndTrackbar){
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ /* testing TBM_SETTHUMBLENGTH */
+ SendMessage(hWndTrackbar, TBM_SETTHUMBLENGTH, 15, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETTHUMBLENGTH, 0,0);
+ expect(15, r);
+ SendMessage(hWndTrackbar, TBM_SETTHUMBLENGTH, 20, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETTHUMBLENGTH, 0,0);
+ expect(20, r);
+
+ /* test TBM_GETTHUMBLENGTH */
+ r = SendMessage(hWndTrackbar, TBM_GETTHUMBLENGTH, 0,0);
+ expect(20, r);
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, thumb_length_test_seq, "thumb length test sequence", TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_thumb_length_test_seq, "parent thumb lenth test sequence", TRUE);
+}
+
+static void test_tic_settings(HWND hWndTrackbar){
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ /* testing TBM_SETTIC */
+ /* Set tics at 5 and 10 */
+ /* 0 and 20 are out of range and should not be set */
+ r = SendMessage(hWndTrackbar, TBM_SETTIC, 0, 0);
+ ok(r == FALSE, "Expected FALSE, got %d\n", r);
+ r = SendMessage(hWndTrackbar, TBM_SETTIC, 0, 5);
+ todo_wine{
+ ok(r == TRUE, "Expected TRUE, got %d\n", r);
+ r = SendMessage(hWndTrackbar, TBM_SETTIC, 0, 10);
+ ok(r == TRUE, "Expected TRUE, got %d\n", r);
+ }
+ r = SendMessage(hWndTrackbar, TBM_SETTIC, 0, 20);
+ ok(r == FALSE, "Expected False, got %d\n", r);
+
+ /* test TBM_SETTICFREQ */
+ SendMessage(hWndTrackbar, TBM_SETRANGE, TRUE, MAKELONG(0, 10));
+ SendMessage(hWndTrackbar, TBM_SETTICFREQ, 2, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0,0);
+ expect(6, r);
+ SendMessage(hWndTrackbar, TBM_SETTICFREQ, 5, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0,0);
+ expect(3, r);
+ SendMessage(hWndTrackbar, TBM_SETTICFREQ, 15, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0,0);
+ expect(2, r);
+
+ /* test TBM_GETNUMTICS */
+ /* since TIC FREQ is 15, there should be only 2 tics now */
+ r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0,0);
+ expect(2, r);
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, tic_settings_test_seq, "tic settings test sequence", TRUE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_tic_settings_test_seq, "parent tic settings test sequence", TRUE);
+}
+
+static void test_tic_placement(HWND hWndTrackbar){
+ int r;
+ DWORD *rPTics;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ /* test TBM_GETPTICS */
+ rPTics = (DWORD *) SendMessage(hWndTrackbar, TBM_GETPTICS, 0,0);
+ todo_wine{
+ expect(1, rPTics[0]);
+ expect(2, rPTics[1]);
+ expect(3, rPTics[2]);
+ expect(4, rPTics[3]);
+ }
+
+ /* test TBM_GETTIC */
+ r = SendMessage(hWndTrackbar, TBM_GETTIC, 0,0);
+ todo_wine{
+ expect(1, r);
+ r = SendMessage(hWndTrackbar, TBM_GETTIC, 4,0);
+ expect(5, r);
+ }
+ r = SendMessage(hWndTrackbar, TBM_GETTIC, 11,0);
+ expect(-1, r);
+
+ /* test TBM_GETTICPIC */
+ r = SendMessage(hWndTrackbar, TBM_GETTICPOS, 0, 0);
+ todo_wine{
+ ok(r > 0, "Expected r > 0, got %d\n", r);
+ r = SendMessage(hWndTrackbar, TBM_GETTICPOS, 4, 0);
+ ok(r > 0, "Expected r > 0, got %d\n", r);
+ }
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, tic_placement_test_seq, "get tic placement test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_empty_test_seq, "parent get tic placement test sequence", FALSE);
+}
+
+
+static void test_tool_tips(HWND hWndTrackbar){
+ int r;
+ HWND hWndTooltip;
+ HWND rTest;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ /* testing TBM_SETTIPSIDE */
+ r = SendMessage(hWndTrackbar, TBM_SETTIPSIDE, TBTS_TOP, 0);
+ todo_wine{
+ expect(0, r);
+ }
+ r = SendMessage(hWndTrackbar, TBM_SETTIPSIDE, TBTS_LEFT, 0);
+ expect(0, r);
+ r = SendMessage(hWndTrackbar, TBM_SETTIPSIDE, TBTS_BOTTOM, 0);
+ expect(1, r);
+ r = SendMessage(hWndTrackbar, TBM_SETTIPSIDE, TBTS_RIGHT, 0);
+ expect(2, r);
+
+ /* testing TBM_SETTOOLTIPS */
+ hWndTooltip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, 0,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, NULL, NULL);
+
+ ok(hWndTooltip != NULL, "Expected non NULL value\n");
+ if (hWndTooltip != NULL){
+ SendMessage(hWndTrackbar, TBM_SETTOOLTIPS, (LPARAM) hWndTooltip, 0);
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_GETTOOLTIPS, 0,0);
+ ok(rTest == hWndTooltip, "Expected hWndToolTip, got\n");
+ SendMessage(hWndTrackbar, TBM_SETTOOLTIPS, (LPARAM) NULL, 0);
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_GETTOOLTIPS, 0,0);
+ ok(rTest == NULL, "Expected NULL\n");
+ SendMessage(hWndTrackbar, TBM_SETTOOLTIPS, (LPARAM) hWndTooltip, 5);
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_GETTOOLTIPS, 0,0);
+ ok(rTest == hWndTooltip, "Expected hWndTooltip, got\n");
+ } else
+ skip("tool tip control not present?\n");
+
+ /* test TBM_GETTOOLTIPS */
+ rTest = (HWND) SendMessage(hWndTrackbar, TBM_GETTOOLTIPS, 0,0);
+ ok(rTest == hWndTooltip, "Expected hWndTooltip\n");
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, tool_tips_test_seq, "tool tips test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_empty_test_seq, "parent tool tips test sequence", FALSE);
+}
+
+
+static void test_unicode(HWND hWndTrackbar){
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ /* testing TBM_SETUNICODEFORMAT */
+ r = SendMessage(hWndTrackbar, TBM_SETUNICODEFORMAT, TRUE, 0);
+ ok(r == FALSE, "Expected FALSE, got %d\n",r);
+ r = SendMessage(hWndTrackbar, TBM_SETUNICODEFORMAT, FALSE, 0);
+ ok(r == TRUE, "Expected TRUE, got %d\n",r);
+
+ /* test TBM_GETUNICODEFORMAT */
+ r = SendMessage(hWndTrackbar, TBM_GETUNICODEFORMAT, 0,0);
+ ok(r == FALSE, "Expected FALSE, got %d\n",r);
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, unicode_test_seq, "unicode test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_empty_test_seq, "parent unicode test sequence", FALSE);
+}
+
+static void test_ignore_selection(HWND hWndTrackbar){
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ /* test TBM_SETSEL ensure that it is ignored */
+ SendMessage(hWndTrackbar, TBM_SETSEL, TRUE, MAKELONG(0,10));
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(0, r);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(0, r);
+ SendMessage(hWndTrackbar, TBM_SETSEL, FALSE, MAKELONG(0,10));
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(0, r);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(0, r);
+
+ /* test TBM_SETSELEND, ensure that it is ignored */
+ SendMessage(hWndTrackbar, TBM_SETSELEND, TRUE, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(0, r);
+ SendMessage(hWndTrackbar, TBM_SETSELEND, TRUE, 10);
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(0,r);
+ SendMessage(hWndTrackbar, TBM_SETSELEND, FALSE, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETSELEND, 0,0);
+ expect(0, r);
+
+ /* test TBM_SETSELSTART, ensure that it is ignored */
+ SendMessage(hWndTrackbar, TBM_SETSELSTART, TRUE, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(0, r);
+ SendMessage(hWndTrackbar, TBM_SETSELSTART, TRUE, 10);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(0,r);
+ SendMessage(hWndTrackbar, TBM_SETSELSTART, FALSE, 0);
+ r = SendMessage(hWndTrackbar, TBM_GETSELSTART, 0,0);
+ expect(0, r);
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, ignore_selection_test_seq, "ignore selection setting test sequence", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_empty_test_seq, "parent ignore selection setting test sequence", FALSE);
+}
+
+START_TEST(trackbar)
+{
+ DWORD style = WS_VISIBLE | TBS_TOOLTIPS | TBS_ENABLESELRANGE | TBS_FIXEDLENGTH | TBS_AUTOTICKS;
+ HWND hWndTrackbar;
+ HWND hWndParent;
+
+ init_msg_sequences(sequences, NUM_MSG_SEQUENCE);
+ InitCommonControls();
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+
+ /* create parent window */
+ hWndParent = create_parent_window();
+ ok(hWndParent != NULL, "Failed to create parent Window!\n");
+
+ if(!hWndParent){
+ skip("parent window not present\n");
+ return;
+ }
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create Parent Window", TRUE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+
+ /* create trackbar with set styles */
+ hWndTrackbar = create_trackbar(style, hWndParent);
+
+ ok(hWndTrackbar != NULL, "Expected non NULL value\n");
+
+ if (!hWndTrackbar){
+ skip("trackbar control not present?\n");
+ return;
+ }
+
+ ok_sequence(sequences, TRACKBAR_SEQ_INDEX, create_trackbar_wnd_seq, "create Trackbar Window", FALSE);
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_create_trackbar_wnd_seq, "parent trackbar window", TRUE);
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+
+ /* TEST OF ALL SETTER and GETTER MESSAGES with required styles turned on*/
+ test_trackbar_buddy(hWndTrackbar);
+ test_line_size(hWndTrackbar);
+ test_page_size(hWndTrackbar);
+ test_position(hWndTrackbar);
+ test_range(hWndTrackbar);
+ test_selection(hWndTrackbar);
+ test_thumb_length(hWndTrackbar);
+ test_tic_settings(hWndTrackbar);
+ test_tic_placement(hWndTrackbar);
+ test_tool_tips(hWndTrackbar);
+ test_unicode(hWndTrackbar);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCE);
+ DestroyWindow(hWndTrackbar);
+
+ /* test getters and setters without styles set */
+ hWndTrackbar = create_trackbar(0, hWndParent);
+
+ ok(hWndTrackbar != NULL, "Expected non NULL value\n");
+
+ if (!hWndTrackbar){
+ skip("trackbar control not present?\n");
+ return;
+ }
+
+ ok_sequence(sequences, PARENT_SEQ_INDEX, parent_new_window_test_seq, "new trackbar window test sequence", TRUE);
+
+ test_ignore_selection(hWndTrackbar);
+
+ DestroyWindow(hWndTrackbar);
+
+ DestroyWindow(hWndParent);
+}
/* Unit tests for treeview.
*
* Copyright 2005 Krzysztof Foltman
+ * Copyright 2007 Christopher James Peterson
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include "winuser.h"
#include "winnls.h"
#include "winreg.h"
-#include "commctrl.h"
+#include "commctrl.h"
#include "wine/test.h"
+#include "msg.h"
+
+#define NUM_MSG_SEQUENCES 1
+#define LISTVIEW_SEQ_INDEX 0
+
+static struct msg_sequence *MsgSequences[NUM_MSG_SEQUENCES];
+
+static const struct message FillRootSeq[] = {
+ { TVM_INSERTITEM, sent },
+ { TVM_GETITEM, sent },
+ { TVM_INSERTITEM, sent },
+ { 0 }
+};
+
+static const struct message DoTest1Seq[] = {
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { 0 }
+};
+
+static const struct message DoTest2Seq[] = {
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ { 0 }
+};
+
+static const struct message DoFocusTestSeq[] = {
+ { TVM_INSERTITEM, sent },
+ { TVM_INSERTITEM, sent },
+ { WM_WINDOWPOSCHANGING, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|wparam|defwinproc, 0x00000001 },
+ { WM_WINDOWPOSCHANGED, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { WM_WINDOWPOSCHANGING, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0x00000001 },
+ { WM_WINDOWPOSCHANGED, sent },
+ { WM_SIZE, sent|defwinproc },
+ { WM_WINDOWPOSCHANGING, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|wparam|defwinproc, 0x00000001 },
+ { WM_WINDOWPOSCHANGED, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { TVM_SELECTITEM, sent|wparam, 0x00000009 },
+ /* The following end up out of order in wine */
+ { WM_PAINT, sent|defwinproc },
+ { WM_NCPAINT, sent|wparam|defwinproc, 0x00000001 },
+ { WM_ERASEBKGND, sent|defwinproc },
+ { TVM_EDITLABEL, sent },
+ { WM_COMMAND, sent|wparam|defwinproc, 0x04000000 },
+ { WM_COMMAND, sent|wparam|defwinproc, 0x03000000 },
+ { WM_PARENTNOTIFY, sent|wparam|defwinproc, 0x00000001 },
+ { WM_KILLFOCUS, sent|defwinproc },
+ { WM_PAINT, sent|defwinproc },
+ { WM_IME_SETCONTEXT, sent|defwinproc|optional },
+ { WM_COMMAND, sent|wparam|defwinproc, 0x01000000},
+ { WM_ERASEBKGND, sent|defwinproc },
+ { WM_CTLCOLOREDIT, sent|defwinproc|optional },
+ { WM_CTLCOLOREDIT, sent|defwinproc|optional },
+ { 0 }
+};
+
+static const struct message TestGetSetBkColorSeq[] = {
+ { TVM_GETBKCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETBKCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_GETBKCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETBKCOLOR, sent|wparam|lparam, 0x00000000, 0x00ffffff },
+ { TVM_GETBKCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETBKCOLOR, sent|wparam|lparam, 0x00000000, 0xffffffff },
+ { 0 }
+};
+
+static const struct message TestGetSetImageListSeq[] = {
+ { TVM_SETIMAGELIST, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_GETIMAGELIST, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
+
+static const struct message TestGetSetIndentSeq[] = {
+ { TVM_SETINDENT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_GETINDENT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ /* The actual amount to indent is dependent on the system for this message */
+ { TVM_SETINDENT, sent },
+ { TVM_GETINDENT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
+
+static const struct message TestGetSetInsertMarkColorSeq[] = {
+ { TVM_SETINSERTMARKCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_GETINSERTMARKCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
+
+static const struct message TestGetSetItemSeq[] = {
+ { TVM_GETITEM, sent },
+ { TVM_SETITEM, sent },
+ { TVM_GETITEM, sent },
+ { TVM_SETITEM, sent },
+ { 0 }
+};
+
+static const struct message TestGetSetItemHeightSeq[] = {
+ { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETITEMHEIGHT, sent|wparam|lparam, 0xffffffff, 0x00000000 },
+ { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETITEMHEIGHT, sent|lparam, 0xcccccccc, 0x00000000 },
+ { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETITEMHEIGHT, sent|wparam|lparam, 0x00000009, 0x00000000 },
+ { WM_WINDOWPOSCHANGING, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|wparam|defwinproc, 0x00000001 },
+ { WM_WINDOWPOSCHANGED, sent|defwinproc },
+ { WM_SIZE, sent|defwinproc },
+ { TVM_GETITEMHEIGHT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
+
+static const struct message TestGetSetScrollTimeSeq[] = {
+ { TVM_SETSCROLLTIME, sent|wparam|lparam, 0x00000014, 0x00000000 },
+ { TVM_GETSCROLLTIME, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
+
+static const struct message TestGetSetTextColorSeq[] = {
+ { TVM_GETTEXTCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETTEXTCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_GETTEXTCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETTEXTCOLOR, sent|wparam|lparam, 0x00000000, 0x00ffffff },
+ { TVM_GETTEXTCOLOR, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETTEXTCOLOR, sent|wparam|lparam, 0x00000000, 0xffffffff },
+ { 0 }
+};
+
+static const struct message TestGetSetToolTipsSeq[] = {
+ { WM_COMMAND, sent|wparam, 0x02000000 },
+ { WM_PARENTNOTIFY, sent|wparam|defwinproc, 0x00020002 },
+ { TVM_SETTOOLTIPS, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_GETTOOLTIPS, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
+
+static const struct message TestGetSetUnicodeFormatSeq[] = {
+ { TVM_SETUNICODEFORMAT, sent|wparam|lparam, 0x00000001, 0x00000000 },
+ { TVM_GETUNICODEFORMAT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETUNICODEFORMAT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_GETUNICODEFORMAT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { TVM_SETUNICODEFORMAT, sent|wparam|lparam, 0x00000000, 0x00000000 },
+ { 0 }
+};
static HWND hMainWnd;
-static HWND hTree;
+static HWND hTree, hEdit;
static HTREEITEM hRoot, hChild;
static int pos = 0;
static void FillRoot(void)
{
TVINSERTSTRUCTA ins;
+ TVITEM tvi;
static CHAR root[] = "Root",
child[] = "Child";
hRoot = TreeView_InsertItem(hTree, &ins);
assert(hRoot);
+ /* UMLPad 1.15 depends on this being not -1 (I_IMAGECALLBACK) */
+ tvi.hItem = hRoot;
+ tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ SendMessage( hTree, TVM_GETITEM, 0, (LPARAM)&tvi );
+ ok(tvi.iImage == 0, "tvi.iImage=%d\n", tvi.iImage);
+ ok(tvi.iSelectedImage == 0, "tvi.iSelectedImage=%d\n", tvi.iSelectedImage);
+
AddItem('B');
ins.hParent = hRoot;
ins.hInsertAfter = TVI_FIRST;
ok(!strcmp(sequence, "1(nR)nR23(RC)RC45(CR)CR."), "root-child select test\n");
}
-LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+static void DoFocusTest(void)
+{
+ TVINSERTSTRUCTA ins;
+ static CHAR child1[] = "Edit",
+ child2[] = "A really long string";
+ HTREEITEM hChild1, hChild2;
+
+ /* This test verifies that when a label is being edited, scrolling
+ * the treeview does not cause the label to lose focus. To test
+ * this, first some additional entries are added to generate
+ * scrollbars.
+ */
+ ins.hParent = hRoot;
+ ins.hInsertAfter = hChild;
+ U(ins).item.mask = TVIF_TEXT;
+ U(ins).item.pszText = child1;
+ hChild1 = TreeView_InsertItem(hTree, &ins);
+ assert(hChild1);
+ ins.hInsertAfter = hChild1;
+ U(ins).item.mask = TVIF_TEXT;
+ U(ins).item.pszText = child2;
+ hChild2 = TreeView_InsertItem(hTree, &ins);
+ assert(hChild2);
+
+ ShowWindow(hMainWnd,SW_SHOW);
+ /* Using SendMessageA since Win98 doesn't have default unicode support */
+ SendMessageA(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hChild);
+ hEdit = TreeView_EditLabel(hTree, hChild);
+ ScrollWindowEx(hTree, -10, 0, NULL, NULL, NULL, NULL, SW_SCROLLCHILDREN);
+ ok(GetFocus() == hEdit, "Edit control should have focus\n");
+}
+
+static void TestGetSetBkColor(void)
+{
+ COLORREF crColor = RGB(0,0,0);
+
+ todo_wine{
+ /* If the value is -1, the control is using the system color for the background color. */
+ crColor = (COLORREF)SendMessage( hTree, TVM_GETBKCOLOR, 0, 0 );
+ ok(crColor == -1, "Default background color reported as 0x%.8x\n", crColor);
+ }
+
+ /* Test for black background */
+ SendMessage( hTree, TVM_SETBKCOLOR, 0, (LPARAM)RGB(0,0,0) );
+ crColor = (COLORREF)SendMessage( hTree, TVM_GETBKCOLOR, 0, 0 );
+ ok(crColor == RGB(0,0,0), "Black background color reported as 0x%.8x\n", crColor);
+
+ /* Test for white background */
+ SendMessage( hTree, TVM_SETBKCOLOR, 0, (LPARAM)RGB(255,255,255) );
+ crColor = (COLORREF)SendMessage( hTree, TVM_GETBKCOLOR, 0, 0 );
+ ok(crColor == RGB(255,255,255), "White background color reported as 0x%.8x\n", crColor);
+
+ /* Reset the default background */
+ SendMessage( hTree, TVM_SETBKCOLOR, 0, -1 );
+}
+
+static void TestGetSetImageList(void)
+{
+ HIMAGELIST hImageList = NULL;
+
+ /* Test a NULL HIMAGELIST */
+ SendMessage( hTree, TVM_SETIMAGELIST, TVSIL_NORMAL, (LPARAM)hImageList );
+ hImageList = (HIMAGELIST)SendMessage( hTree, TVM_GETIMAGELIST, TVSIL_NORMAL, 0 );
+ ok(hImageList == NULL, "NULL image list, reported as 0x%p, expected 0.\n", hImageList);
+
+ /* TODO: Test an actual image list */
+}
+
+static void TestGetSetIndent(void)
+{
+ int ulIndent = -1;
+ int ulMinIndent = -1;
+ int ulMoreThanTwiceMin = -1;
+
+ /* Finding the minimum indent */
+ SendMessage( hTree, TVM_SETINDENT, 0, 0 );
+ ulMinIndent = (int)SendMessage( hTree, TVM_GETINDENT, 0, 0 );
+
+ /* Checking an indent that is more than twice the default indent */
+ ulMoreThanTwiceMin = 2*ulMinIndent+1;
+ SendMessage( hTree, TVM_SETINDENT, ulMoreThanTwiceMin, 0 );
+ ulIndent = (DWORD)SendMessage( hTree, TVM_GETINDENT, 0, 0 );
+ ok(ulIndent == ulMoreThanTwiceMin, "Indent reported as %d, expected %d\n", ulIndent, ulMoreThanTwiceMin);
+}
+
+static void TestGetSetInsertMarkColor(void)
+{
+ COLORREF crColor = RGB(0,0,0);
+ SendMessage( hTree, TVM_SETINSERTMARKCOLOR, 0, crColor );
+ crColor = (COLORREF)SendMessage( hTree, TVM_GETINSERTMARKCOLOR, 0, 0 );
+ ok(crColor == RGB(0,0,0), "Insert mark color reported as 0x%.8x, expected 0x00000000\n", crColor);
+}
+
+static void TestGetSetItem(void)
+{
+ TVITEM tviRoot = {0};
+ int nBufferSize = 80;
+ char szBuffer[80] = {0};
+
+ /* Test the root item */
+ tviRoot.hItem = hRoot;
+ tviRoot.mask = TVIF_TEXT;
+ tviRoot.cchTextMax = nBufferSize;
+ tviRoot.pszText = szBuffer;
+ SendMessage( hTree, TVM_GETITEM, 0, (LPARAM)&tviRoot );
+ ok(!strcmp("Root", szBuffer), "GetItem: szBuffer=\"%s\", expected \"Root\"\n", szBuffer);
+
+ /* Change the root text */
+ strncpy(szBuffer, "Testing123", nBufferSize);
+ SendMessage( hTree, TVM_SETITEM, 0, (LPARAM)&tviRoot );
+ memset(szBuffer, 0, nBufferSize);
+ SendMessage( hTree, TVM_GETITEM, 0, (LPARAM)&tviRoot );
+ ok(!strcmp("Testing123", szBuffer), "GetItem: szBuffer=\"%s\", expected \"Testing123\"\n", szBuffer);
+
+ /* Reset the root text */
+ memset(szBuffer, 0, nBufferSize);
+ strncpy(szBuffer, "Root", nBufferSize);
+ SendMessage( hTree, TVM_SETITEM, 0, (LPARAM)&tviRoot );
+}
+
+static void TestGetSetItemHeight(void)
+{
+ int ulOldHeight = 0;
+ int ulNewHeight = 0;
+
+ /* Assuming default height to begin with */
+ ulOldHeight = (int) SendMessage( hTree, TVM_GETITEMHEIGHT, 0, 0 );
+
+ /* Explicitly setting and getting the default height */
+ SendMessage( hTree, TVM_SETITEMHEIGHT, -1, 0 );
+ ulNewHeight = (int) SendMessage( hTree, TVM_GETITEMHEIGHT, 0, 0 );
+ ok(ulNewHeight == ulOldHeight, "Default height not set properly, reported %d, expected %d\n", ulNewHeight, ulOldHeight);
+
+ /* Explicitly setting and getting the height of twice the normal */
+ SendMessage( hTree, TVM_SETITEMHEIGHT, 2*ulOldHeight, 0 );
+ ulNewHeight = (int) SendMessage( hTree, TVM_GETITEMHEIGHT, 0, 0 );
+ ok(ulNewHeight == 2*ulOldHeight, "New height not set properly, reported %d, expected %d\n", ulNewHeight, 2*ulOldHeight);
+
+ /* Assuming tree doesn't have TVS_NONEVENHEIGHT set, so a set of 9 will round down to 8 */
+ SendMessage( hTree, TVM_SETITEMHEIGHT, 9, 0 );
+ ulNewHeight = (int) SendMessage( hTree, TVM_GETITEMHEIGHT, 0, 0 );
+ ok(ulNewHeight == 8, "Uneven height not set properly, reported %d, expected %d\n", ulNewHeight, 8);
+}
+
+static void TestGetSetScrollTime(void)
+{
+ int ulExpectedTime = 20;
+ int ulTime = 0;
+ SendMessage( hTree, TVM_SETSCROLLTIME, ulExpectedTime, 0 );
+ ulTime = (int)SendMessage( hTree, TVM_GETSCROLLTIME, 0, 0 );
+ ok(ulTime == ulExpectedTime, "Scroll time reported as %d, expected %d\n", ulTime, ulExpectedTime);
+}
+
+static void TestGetSetTextColor(void)
{
+ /* If the value is -1, the control is using the system color for the text color. */
+ COLORREF crColor = RGB(0,0,0);
+ crColor = (COLORREF)SendMessage( hTree, TVM_GETTEXTCOLOR, 0, 0 );
+ ok(crColor == -1, "Default text color reported as 0x%.8x\n", crColor);
+
+ /* Test for black text */
+ SendMessage( hTree, TVM_SETTEXTCOLOR, 0, (LPARAM)RGB(0,0,0) );
+ crColor = (COLORREF)SendMessage( hTree, TVM_GETTEXTCOLOR, 0, 0 );
+ ok(crColor == RGB(0,0,0), "Black text color reported as 0x%.8x\n", crColor);
+
+ /* Test for white text */
+ SendMessage( hTree, TVM_SETTEXTCOLOR, 0, (LPARAM)RGB(255,255,255) );
+ crColor = (COLORREF)SendMessage( hTree, TVM_GETTEXTCOLOR, 0, 0 );
+ ok(crColor == RGB(255,255,255), "White text color reported as 0x%.8x\n", crColor);
+
+ /* Reset the default text color */
+ SendMessage( hTree, TVM_SETTEXTCOLOR, 0, -1 );
+}
+
+static void TestGetSetToolTips(void)
+{
+ HWND hwndLastToolTip = NULL;
+ HWND hPopupTreeView;
+
+ /* show even WS_POPUP treeview don't send NM_TOOLTIPSCREATED */
+ hPopupTreeView = CreateWindow(WC_TREEVIEW, NULL, WS_POPUP|WS_VISIBLE, 0, 0, 100, 100, hMainWnd, NULL, NULL, NULL);
+ DestroyWindow(hPopupTreeView);
+
+ /* Testing setting a NULL ToolTip */
+ SendMessage( hTree, TVM_SETTOOLTIPS, 0, 0 );
+ hwndLastToolTip = (HWND)SendMessage( hTree, TVM_GETTOOLTIPS, 0, 0 );
+ ok(hwndLastToolTip == NULL, "NULL tool tip, reported as 0x%p, expected 0.\n", hwndLastToolTip);
+
+ /* TODO: Add a test of an actual tooltip */
+}
+
+static void TestGetSetUnicodeFormat(void)
+{
+ BOOL bPreviousSetting = 0;
+ BOOL bNewSetting = 0;
+
+ /* Set to Unicode */
+ bPreviousSetting = (BOOL)SendMessage( hTree, TVM_SETUNICODEFORMAT, 1, 0 );
+ bNewSetting = (BOOL)SendMessage( hTree, TVM_GETUNICODEFORMAT, 0, 0 );
+ ok(bNewSetting == 1, "Unicode setting did not work.\n");
+
+ /* Set to ANSI */
+ SendMessage( hTree, TVM_SETUNICODEFORMAT, 0, 0 );
+ bNewSetting = (BOOL)SendMessage( hTree, TVM_GETUNICODEFORMAT, 0, 0 );
+ ok(bNewSetting == 0, "ANSI setting did not work.\n");
+
+ /* Revert to original setting */
+ SendMessage( hTree, TVM_SETUNICODEFORMAT, (LPARAM)bPreviousSetting, 0 );
+}
+
+static void TestGetSet(void)
+{
+ /* TVM_GETBKCOLOR and TVM_SETBKCOLOR */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetBkColor();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetBkColorSeq,
+ "TestGetSetBkColor", FALSE);
+
+ /* TVM_GETIMAGELIST and TVM_SETIMAGELIST */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetImageList();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetImageListSeq,
+ "TestGetImageList", FALSE);
+
+ /* TVM_SETINDENT and TVM_GETINDENT */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetIndent();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetIndentSeq,
+ "TestGetSetIndent", FALSE);
+
+ /* TVM_GETINSERTMARKCOLOR and TVM_GETINSERTMARKCOLOR */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetInsertMarkColor();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetInsertMarkColorSeq,
+ "TestGetSetInsertMarkColor", FALSE);
+
+ /* TVM_GETITEM and TVM_SETITEM */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetItem();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetItemSeq,
+ "TestGetSetItem", FALSE);
+
+ /* TVM_GETITEMHEIGHT and TVM_SETITEMHEIGHT */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetItemHeight();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetItemHeightSeq,
+ "TestGetSetItemHeight", FALSE);
+
+ /* TVM_GETSCROLLTIME and TVM_SETSCROLLTIME */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetScrollTime();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetScrollTimeSeq,
+ "TestGetSetScrollTime", FALSE);
+
+ /* TVM_GETTEXTCOLOR and TVM_SETTEXTCOLOR */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetTextColor();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetTextColorSeq,
+ "TestGetSetTextColor", FALSE);
+
+ /* TVM_GETTOOLTIPS and TVM_SETTOOLTIPS */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetToolTips();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetToolTipsSeq,
+ "TestGetSetToolTips", TRUE);
+
+ /* TVM_GETUNICODEFORMAT and TVM_SETUNICODEFORMAT */
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ TestGetSetUnicodeFormat();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, TestGetSetUnicodeFormatSeq,
+ "TestGetSetUnicodeFormat", FALSE);
+}
+
+/* This function hooks in and records all messages to the treeview control */
+static LRESULT WINAPI TreeviewWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+ WNDPROC lpOldProc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(MsgSequences, LISTVIEW_SEQ_INDEX, &msg);
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(lpOldProc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ WNDPROC pOldWndProc;
+
switch(msg) {
case WM_CREATE:
{
hTree = CreateWindowExA(WS_EX_CLIENTEDGE, WC_TREEVIEWA, NULL, WS_CHILD|WS_VISIBLE|
- TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS,
- 0, 0, 300, 50, hWnd, (HMENU)100, GetModuleHandleA(0), 0);
+ TVS_LINESATROOT|TVS_HASLINES|TVS_HASBUTTONS|TVS_EDITLABELS,
+ 0, 0, 120, 100, hWnd, (HMENU)100, GetModuleHandleA(0), 0);
SetFocus(hTree);
+
+ /* Record the old WNDPROC so we can call it after recording the messages */
+ pOldWndProc = (WNDPROC)SetWindowLongPtrA(hTree, GWLP_WNDPROC, (LONG_PTR)TreeviewWndProc);
+ SetWindowLongPtrA(hTree, GWLP_USERDATA, (LONG_PTR)pOldWndProc);
+
return 0;
}
case WM_NOTIFY:
{
NMHDR *pHdr = (NMHDR *)lParam;
-
+
+ ok(pHdr->code != NM_FIRST - 19, "Treeview should not send NM_TOOLTIPSCREATED\n");
if (pHdr->idFrom == 100) {
NMTREEVIEWA *pTreeView = (LPNMTREEVIEWA) lParam;
switch(pHdr->code) {
}
return 0;
}
-
+
case WM_SIZE:
MoveWindow(hTree, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
-
+
case WM_DESTROY:
PostQuitMessage(0);
break;
-
+
default:
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
WNDCLASSA wc;
MSG msg;
INITCOMMONCONTROLSEX icex;
- RECT rc;
-
+
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_TREEVIEW_CLASSES;
InitCommonControlsEx(&icex);
-
+ init_msg_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandleA(NULL);
wc.hIcon = NULL;
- wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_IBEAM));
+ wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyTestWnd";
hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
- GetClientRect(hMainWnd, &rc);
+ CW_USEDEFAULT, CW_USEDEFAULT, 130, 105, NULL, NULL, GetModuleHandleA(NULL), 0);
+
+ if ( !ok(hMainWnd != NULL, "Failed to create parent window. Tests aborted.\n") )
+ return;
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
FillRoot();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, FillRootSeq, "FillRoot", FALSE);
+
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
DoTest1();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, DoTest1Seq, "DoTest1", FALSE);
+
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
DoTest2();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, DoTest2Seq, "DoTest2", FALSE);
+
+ flush_sequences(MsgSequences, NUM_MSG_SEQUENCES);
+ DoFocusTest();
+ ok_sequence(MsgSequences, LISTVIEW_SEQ_INDEX, DoFocusTestSeq, "DoFocusTest", TRUE);
+
+ /* Sequences tested inside due to number */
+ TestGetSet();
PostMessageA(hMainWnd, WM_CLOSE, 0, 0);
while(GetMessageA(&msg,0,0,0)) {
-/* Unit test suite for updown control.
+/* Unit tests for the up-down control
*
* Copyright 2005 C. Scott Ananian
+ * Copyright (C) 2007 James Hawkins
+ * Copyright (C) 2007 Leslie Choong
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+/* TO TEST:
+ * - send click messages to the up-down control, check the current position
+ * - up-down control automatically positions itself next to its buddy window
+ * - up-down control sets the caption of the buddy window
+ * - test CreateUpDownControl API
+ * - check UDS_AUTOBUDDY style, up-down control selects previous window in z-order
+ * - check UDM_SETBUDDY message
+ * - check UDM_GETBUDDY message
+ * - up-down control and buddy control must have the same parent
+ * - up-down control notifies its parent window when its position changes with UDN_DELTAPOS + WM_VSCROLL or WM_HSCROLL
+ * - check UDS_ALIGN[LEFT,RIGHT]...check that width of buddy window is decreased
+ * - check that UDS_SETBUDDYINT sets the caption of the buddy window when it is changed
+ * - check that the thousands operator is set for large numbers
+ * - check that the thousands operator is not set with UDS_NOTHOUSANDS
+ * - check UDS_ARROWKEYS, control subclasses the buddy window so that it processes the keys when it has focus
+ * - check UDS_HORZ
+ * - check changing past min/max values
+ * - check UDS_WRAP wraps values past min/max, incrementing past upper value wraps position to lower value
+ * - can change control's position, min/max pos, radix
+ * - check UDM_GETPOS, for up-down control with a buddy window, position is the caption of the buddy window, so change the
+ * caption of the buddy window then call UDM_GETPOS
+ * - check UDM_SETRANGE, max can be less than min, so clicking the up arrow decreases the current position
+ * - more stuff to test
+ */
+
#include <assert.h>
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "wine/test.h"
+#include "msg.h"
+
+#define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
+
+#define NUM_MSG_SEQUENCES 3
+#define PARENT_SEQ_INDEX 0
+#define EDIT_SEQ_INDEX 1
+#define UPDOWN_SEQ_INDEX 2
+
+static HWND parent_wnd, edit, updown;
+
+static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
+
+static const struct message create_parent_wnd_seq[] = {
+ { WM_GETMINMAXINFO, sent },
+ { WM_NCCREATE, sent },
+ { WM_NCCALCSIZE, sent|wparam, 0 },
+ { WM_CREATE, sent },
+ { WM_SHOWWINDOW, sent|wparam, 1 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
+ { WM_ACTIVATEAPP, sent|wparam, 1 },
+ { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATE, sent|wparam, 1 },
+ { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
+ { WM_IME_NOTIFY, sent|defwinproc|optional },
+ { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+ /* Win9x adds SWP_NOZORDER below */
+ { WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
+ { WM_NCCALCSIZE, sent|wparam|optional, 1 },
+ { WM_SIZE, sent },
+ { WM_MOVE, sent },
+ { 0 }
+};
+
+static const struct message add_edit_to_parent_seq[] = {
+ { WM_PARENTNOTIFY, sent|wparam, WM_CREATE },
+ { 0 }
+};
+
+static const struct message add_updown_with_edit_seq[] = {
+ { WM_WINDOWPOSCHANGING, sent },
+ { WM_NCCALCSIZE, sent|wparam, TRUE },
+ { WM_WINDOWPOSCHANGED, sent },
+ { WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED /*, MAKELONG(91, 75) exact size depends on font */ },
+ { 0 }
+};
+
+static const struct message add_updown_to_parent_seq[] = {
+ { WM_NOTIFYFORMAT, sent|lparam, 0, NF_QUERY },
+ { WM_QUERYUISTATE, sent },
+ { WM_PARENTNOTIFY, sent|wparam, MAKELONG(WM_CREATE, WM_CREATE) },
+ { 0 }
+};
+
+static const struct message get_edit_text_seq[] = {
+ { WM_GETTEXT, sent },
+ { 0 }
+};
+
+static const struct message test_updown_pos_seq[] = {
+ { UDM_SETRANGE, sent|lparam, 0, MAKELONG(100,0) },
+ { UDM_GETRANGE, sent},
+ { UDM_SETPOS, sent|lparam, 0, 5},
+ { UDM_GETPOS, sent},
+ { UDM_SETPOS, sent|lparam, 0, 0},
+ { UDM_GETPOS, sent},
+ { UDM_SETPOS, sent|lparam, 0, MAKELONG(-1,0)},
+ { UDM_GETPOS, sent},
+ { UDM_SETPOS, sent|lparam, 0, 100},
+ { UDM_GETPOS, sent},
+ { UDM_SETPOS, sent|lparam, 0, 101},
+ { UDM_GETPOS, sent},
+ { 0 }
+};
+
+static const struct message test_updown_pos32_seq[] = {
+ { UDM_SETRANGE32, sent|lparam, 0, 1000 },
+ { UDM_GETRANGE32, sent}, /* Cannot check wparam and lparam as they are ptrs */
+ { UDM_SETPOS32, sent|lparam, 0, 500 },
+ { UDM_GETPOS32, sent},
+ { UDM_SETPOS32, sent|lparam, 0, 0 },
+ { UDM_GETPOS32, sent},
+ { UDM_SETPOS32, sent|lparam, 0, -1 },
+ { UDM_GETPOS32, sent},
+ { UDM_SETPOS32, sent|lparam, 0, 1000 },
+ { UDM_GETPOS32, sent},
+ { UDM_SETPOS32, sent|lparam, 0, 1001 },
+ { UDM_GETPOS32, sent},
+ { 0 }
+};
+
+static const struct message test_updown_buddy_seq[] = {
+ { UDM_GETBUDDY, sent },
+ { UDM_SETBUDDY, sent },
+ { WM_STYLECHANGING, sent|defwinproc },
+ { WM_STYLECHANGED, sent|defwinproc },
+ { WM_STYLECHANGING, sent|defwinproc },
+ { WM_STYLECHANGED, sent|defwinproc },
+ { WM_WINDOWPOSCHANGING, sent|defwinproc },
+ { WM_NCCALCSIZE, sent|wparam|optional|defwinproc, 1 },
+ { WM_WINDOWPOSCHANGED, sent|defwinproc },
+ { WM_MOVE, sent|defwinproc },
+ { UDM_GETBUDDY, sent },
+ { 0 }
+};
+
+static const struct message test_updown_base_seq[] = {
+ { UDM_SETBASE, sent|wparam, 10 },
+ { UDM_GETBASE, sent },
+ { UDM_SETBASE, sent|wparam, 80 },
+ { UDM_GETBASE, sent },
+ { UDM_SETBASE, sent|wparam, 16 },
+ { UDM_GETBASE, sent },
+ { UDM_SETBASE, sent|wparam, 80 },
+ { UDM_GETBASE, sent },
+ { UDM_SETBASE, sent|wparam, 10 },
+ { UDM_GETBASE, sent },
+ { 0 }
+};
-static HDC desktopDC;
-static HINSTANCE hinst;
+static const struct message test_updown_unicode_seq[] = {
+ { UDM_SETUNICODEFORMAT, sent|wparam, 0 },
+ { UDM_GETUNICODEFORMAT, sent },
+ { UDM_SETUNICODEFORMAT, sent|wparam, 1 },
+ { UDM_GETUNICODEFORMAT, sent },
+ { UDM_SETUNICODEFORMAT, sent|wparam, 0 },
+ { UDM_GETUNICODEFORMAT, sent },
+ { 0 }
+};
-static HWND create_edit_control (DWORD style, DWORD exstyle)
+static const struct message test_updown_destroy_seq[] = {
+ { WM_SHOWWINDOW, sent|wparam|lparam, 0, 0 },
+ { WM_WINDOWPOSCHANGING, sent},
+ { WM_WINDOWPOSCHANGED, sent},
+ { WM_DESTROY, sent},
+ { WM_NCDESTROY, sent},
+ { 0 }
+};
+
+static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
- HWND handle;
-
- handle = CreateWindowEx(exstyle,
- "EDIT",
- NULL,
- ES_AUTOHSCROLL | ES_AUTOVSCROLL | style,
- 10, 10, 300, 300,
- NULL, NULL, hinst, NULL);
- assert (handle);
- if (winetest_interactive)
- ShowWindow (handle, SW_SHOW);
- return handle;
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ /* do not log painting messages */
+ if (message != WM_PAINT &&
+ message != WM_ERASEBKGND &&
+ message != WM_NCPAINT &&
+ message != WM_NCHITTEST &&
+ message != WM_GETTEXT &&
+ message != WM_GETICON &&
+ message != WM_DEVICECHANGE)
+ {
+ trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, PARENT_SEQ_INDEX, &msg);
+ }
+
+ defwndproc_counter++;
+ ret = DefWindowProcA(hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
}
-static HWND create_updown_control (HWND hWndEdit)
+static BOOL register_parent_wnd_class(void)
{
- HWND hWndUpDown;
-
- /* make the control */
- hWndUpDown = CreateWindowEx
- (0L, UPDOWN_CLASS, NULL,
- /* window styles */
- UDS_SETBUDDYINT | UDS_ALIGNRIGHT |
- UDS_ARROWKEYS | UDS_NOTHOUSANDS,
- /* placement */
- 0, 0, 8, 8,
- /* parent, etc */
- NULL, NULL, hinst, NULL);
- assert (hWndUpDown);
- /* set the buddy. */
- SendMessage (hWndUpDown, UDM_SETBUDDY, (WPARAM)hWndEdit, 0L );
- /* set the range. */
- SendMessage (hWndUpDown, UDM_SETRANGE, 0L, (LPARAM) MAKELONG(32000, 0));
- /* maybe show it. */
- if (winetest_interactive)
- ShowWindow (hWndUpDown, SW_SHOW);
- return hWndUpDown;
+ WNDCLASSA cls;
+
+ cls.style = 0;
+ cls.lpfnWndProc = parent_wnd_proc;
+ cls.cbClsExtra = 0;
+ cls.cbWndExtra = 0;
+ cls.hInstance = GetModuleHandleA(NULL);
+ cls.hIcon = 0;
+ cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
+ cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+ cls.lpszMenuName = NULL;
+ cls.lpszClassName = "Up-Down test parent class";
+ return RegisterClassA(&cls);
}
-static void test_updown_control (void)
+static HWND create_parent_window(void)
{
- HWND hWndUpDown, hWndEdit;
- int num;
-
- hWndEdit = create_edit_control (ES_AUTOHSCROLL | ES_NUMBER, 0);
- hWndUpDown = create_updown_control (hWndEdit);
- /* before we set a value, it should be '0' */
- num = SendMessage(hWndUpDown, UDM_GETPOS, 0, 0L);
- ok(num == 0, "Expected 0 got %d\n", num);
- /* set a value, check it. */
- SendMessage(hWndUpDown, UDM_SETPOS, 0L, MAKELONG( 1, 0));
- num = SendMessage(hWndUpDown, UDM_GETPOS, 0, 0L);
- ok(num == 1, "Expected 1 got %d\n", num);
- /* okay, done (short set of tests!) */
- DestroyWindow(hWndUpDown);
- DestroyWindow(hWndEdit);
+ if (!register_parent_wnd_class())
+ return NULL;
+
+ return CreateWindowEx(0, "Up-Down test parent class",
+ "Up-Down test parent window",
+ WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
+ WS_MAXIMIZEBOX | WS_VISIBLE,
+ 0, 0, 100, 100,
+ GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
}
-START_TEST(updown)
+struct subclass_info
+{
+ WNDPROC oldproc;
+};
+
+static LRESULT WINAPI edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ trace("edit: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, EDIT_SEQ_INDEX, &msg);
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+ return ret;
+}
+
+static HWND create_edit_control(void)
+{
+ struct subclass_info *info;
+ RECT rect;
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ GetClientRect(parent_wnd, &rect);
+ edit = CreateWindowExA(0, "EDIT", NULL, WS_CHILD | WS_BORDER | WS_VISIBLE,
+ 0, 0, rect.right, rect.bottom,
+ parent_wnd, NULL, GetModuleHandleA(NULL), NULL);
+ if (!edit)
+ {
+ HeapFree(GetProcessHeap(), 0, info);
+ return NULL;
+ }
+
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(edit, GWLP_WNDPROC,
+ (LONG_PTR)edit_subclass_proc);
+ SetWindowLongPtrA(edit, GWLP_USERDATA, (LONG_PTR)info);
+
+ return edit;
+}
+
+static LRESULT WINAPI updown_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ static long defwndproc_counter = 0;
+ LRESULT ret;
+ struct message msg;
+
+ trace("updown: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
+
+ msg.message = message;
+ msg.flags = sent|wparam|lparam;
+ if (defwndproc_counter) msg.flags |= defwinproc;
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ add_message(sequences, UPDOWN_SEQ_INDEX, &msg);
+
+ defwndproc_counter++;
+ ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
+ defwndproc_counter--;
+
+ return ret;
+}
+
+static HWND create_updown_control(void)
+{
+ struct subclass_info *info;
+ HWND updown;
+ RECT rect;
+
+ info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
+ if (!info)
+ return NULL;
+
+ GetClientRect(parent_wnd, &rect);
+ updown = CreateUpDownControl(WS_CHILD | WS_BORDER | WS_VISIBLE | UDS_ALIGNRIGHT,
+ 0, 0, rect.right, rect.bottom, parent_wnd, 1, GetModuleHandleA(NULL), edit,
+ 100, 0, 50);
+ if (!updown)
+ {
+ HeapFree(GetProcessHeap(), 0, info);
+ return NULL;
+ }
+
+ info->oldproc = (WNDPROC)SetWindowLongPtrA(updown, GWLP_WNDPROC,
+ (LONG_PTR)updown_subclass_proc);
+ SetWindowLongPtrA(updown, GWLP_USERDATA, (LONG_PTR)info);
+
+ return updown;
+}
+
+static void test_updown_pos(void)
+{
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Set Range from 0 to 100 */
+ SendMessage(updown, UDM_SETRANGE, 0 , MAKELONG(100,0) );
+ r = SendMessage(updown, UDM_GETRANGE, 0,0);
+ expect(100,LOWORD(r));
+ expect(0,HIWORD(r));
+
+ /* Set the position to 5, return is not checked as it was set before func call */
+ SendMessage(updown, UDM_SETPOS, 0 , MAKELONG(5,0) );
+ /* Since UDM_SETBUDDYINT was not set at creation HIWORD(r) will always be 1 as a return from UDM_GETPOS */
+ /* Get the position, which should be 5 */
+ r = SendMessage(updown, UDM_GETPOS, 0 , 0 );
+ expect(5,LOWORD(r));
+ expect(1,HIWORD(r));
+
+ /* Set the position to 0, return should be 5 */
+ r = SendMessage(updown, UDM_SETPOS, 0 , MAKELONG(0,0) );
+ expect(5,r);
+ /* Get the position, which should be 0 */
+ r = SendMessage(updown, UDM_GETPOS, 0 , 0 );
+ expect(0,LOWORD(r));
+ expect(1,HIWORD(r));
+
+ /* Set the position to -1, return should be 0 */
+ r = SendMessage(updown, UDM_SETPOS, 0 , MAKELONG(-1,0) );
+ expect(0,r);
+ /* Get the position, which should be 0 */
+ r = SendMessage(updown, UDM_GETPOS, 0 , 0 );
+ expect(0,LOWORD(r));
+ expect(1,HIWORD(r));
+
+ /* Set the position to 100, return should be 0 */
+ r = SendMessage(updown, UDM_SETPOS, 0 , MAKELONG(100,0) );
+ expect(0,r);
+ /* Get the position, which should be 100 */
+ r = SendMessage(updown, UDM_GETPOS, 0 , 0 );
+ expect(100,LOWORD(r));
+ expect(1,HIWORD(r));
+
+ /* Set the position to 101, return should be 100 */
+ r = SendMessage(updown, UDM_SETPOS, 0 , MAKELONG(101,0) );
+ expect(100,r);
+ /* Get the position, which should be 100 */
+ r = SendMessage(updown, UDM_GETPOS, 0 , 0 );
+ expect(100,LOWORD(r));
+ expect(1,HIWORD(r));
+
+ ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_pos_seq , "test updown pos", FALSE);
+}
+
+static void test_updown_pos32(void)
+{
+ int r;
+ int low, high;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Set the position to 0 to 1000 */
+ SendMessage(updown, UDM_SETRANGE32, 0 , 1000 );
+
+ r = SendMessage(updown, UDM_GETRANGE32, (WPARAM) &low , (LPARAM) &high );
+ expect(0,low);
+ expect(1000,high);
+
+ /* Set position to 500, don't check return since it is unset*/
+ SendMessage(updown, UDM_SETPOS32, 0 , 500 );
+
+ /* Since UDM_SETBUDDYINT was not set at creation bRet will always be true as a return from UDM_GETPOS32 */
+
+ r = SendMessage(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
+ expect(500,r);
+ expect(1,high);
+
+ /* Set position to 0, return should be 500 */
+ r = SendMessage(updown, UDM_SETPOS32, 0 , 0 );
+ expect(500,r);
+ r = SendMessage(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
+ expect(0,r);
+ expect(1,high);
+
+ /* Set position to -1 which should become 0, return should be 0 */
+ r = SendMessage(updown, UDM_SETPOS32, 0 , -1 );
+ expect(0,r);
+ r = SendMessage(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
+ expect(0,r);
+ expect(1,high);
+
+ /* Set position to 1000, return should be 0 */
+ r = SendMessage(updown, UDM_SETPOS32, 0 , 1000 );
+ expect(0,r);
+ r = SendMessage(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
+ expect(1000,r);
+ expect(1,high);
+
+ /* Set position to 1001 which should become 1000, return should be 1000 */
+ r = SendMessage(updown, UDM_SETPOS32, 0 , 1001 );
+ expect(1000,r);
+ r = SendMessage(updown, UDM_GETPOS32, 0 , (LPARAM) &high );
+ expect(1000,r);
+ expect(1,high);
+
+ ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_pos32_seq, "test updown pos32", FALSE);
+}
+
+static void test_updown_buddy(void)
+{
+ HWND buddyReturn;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ buddyReturn = (HWND)SendMessage(updown, UDM_GETBUDDY, 0 , 0 );
+ ok(buddyReturn == edit, "Expected edit handle\n");
+
+ buddyReturn = (HWND)SendMessage(updown, UDM_SETBUDDY, (WPARAM) edit, 0);
+ ok(buddyReturn == edit, "Expected edit handle\n");
+
+ buddyReturn = (HWND)SendMessage(updown, UDM_GETBUDDY, 0 , 0 );
+ ok(buddyReturn == edit, "Expected edit handle\n");
+
+ ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_buddy_seq, "test updown buddy", TRUE);
+ ok_sequence(sequences, EDIT_SEQ_INDEX, add_updown_with_edit_seq, "test updown buddy_edit", FALSE);
+}
+
+static void test_updown_base(void)
+{
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ SendMessage(updown, UDM_SETBASE, 10 , 0);
+ r = SendMessage(updown, UDM_GETBASE, 0 , 0);
+ expect(10,r);
+
+ /* Set base to an invalid value, should return 0 and stay at 10 */
+ r = SendMessage(updown, UDM_SETBASE, 80 , 0);
+ expect(0,r);
+ r = SendMessage(updown, UDM_GETBASE, 0 , 0);
+ expect(10,r);
+
+ /* Set base to 16 now, should get 16 as the return */
+ r = SendMessage(updown, UDM_SETBASE, 16 , 0);
+ expect(10,r);
+ r = SendMessage(updown, UDM_GETBASE, 0 , 0);
+ expect(16,r);
+
+ /* Set base to an invalid value, should return 0 and stay at 16 */
+ r = SendMessage(updown, UDM_SETBASE, 80 , 0);
+ expect(0,r);
+ r = SendMessage(updown, UDM_GETBASE, 0 , 0);
+ expect(16,r);
+
+ /* Set base back to 10, return should be 16 */
+ r = SendMessage(updown, UDM_SETBASE, 10 , 0);
+ expect(16,r);
+ r = SendMessage(updown, UDM_GETBASE, 0 , 0);
+ expect(10,r);
+
+ ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_base_seq, "test updown base", FALSE);
+}
+
+static void test_updown_unicode(void)
{
- desktopDC=GetDC(NULL);
- hinst = GetModuleHandleA(NULL);
+ int r;
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ /* Set it to ANSI, don't check return as we don't know previous state */
+ SendMessage(updown, UDM_SETUNICODEFORMAT, 0 , 0);
+ r = SendMessage(updown, UDM_GETUNICODEFORMAT, 0 , 0);
+ expect(0,r);
+
+ /* Now set it to Unicode format */
+ r = SendMessage(updown, UDM_SETUNICODEFORMAT, 1 , 0);
+ expect(0,r);
+ r = SendMessage(updown, UDM_GETUNICODEFORMAT, 0 , 0);
+ expect(1,r);
+
+ /* And now set it back to ANSI */
+ r = SendMessage(updown, UDM_SETUNICODEFORMAT, 0 , 0);
+ expect(1,r);
+ r = SendMessage(updown, UDM_GETUNICODEFORMAT, 0 , 0);
+ expect(0,r);
+
+ ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_unicode_seq, "test updown unicode", FALSE);
+}
+
+static void test_create_updown_control(void)
+{
+ CHAR text[MAX_PATH];
+
+ parent_wnd = create_parent_window();
+ ok(parent_wnd != NULL, "Failed to create parent window!\n");
+ ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create parent window", TRUE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ edit = create_edit_control();
+ ok(edit != NULL, "Failed to create edit control\n");
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_edit_to_parent_seq, "add edit control to parent", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ updown = create_updown_control();
+ ok(updown != NULL, "Failed to create updown control\n");
+ ok_sequence(sequences, PARENT_SEQ_INDEX, add_updown_to_parent_seq, "add updown control to parent", TRUE);
+ ok_sequence(sequences, EDIT_SEQ_INDEX, add_updown_with_edit_seq, "add updown control with edit", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ GetWindowTextA(edit, text, MAX_PATH);
+ ok(lstrlenA(text) == 0, "Expected empty string\n");
+ ok_sequence(sequences, EDIT_SEQ_INDEX, get_edit_text_seq, "get edit text", FALSE);
+
+ flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+ test_updown_pos();
+ test_updown_pos32();
+ test_updown_buddy();
+ test_updown_base();
+ test_updown_unicode();
+}
+
+START_TEST(updown)
+{
InitCommonControls();
+ init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
- test_updown_control();
+ test_create_updown_control();
}