Autosyncing with Wine HEAD

svn path=/trunk/; revision=30937
This commit is contained in:
The Wine Synchronizer 2007-12-01 18:29:29 +00:00
parent 5be02c6da0
commit 58ffb98f70
29 changed files with 9726 additions and 435 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

View file

@ -82,108 +82,108 @@ static void test_comboboxex(void) {
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 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 (%ld)\n", res);
/* 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;
}
@ -200,14 +200,14 @@ static void init(void) {
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);
@ -218,13 +218,13 @@ static void init(void) {
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));
}

View file

@ -1,29 +1,39 @@
<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>

View file

@ -0,0 +1,24 @@
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"

View file

@ -0,0 +1,571 @@
/* 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();
}

View file

@ -23,7 +23,10 @@
#include <stdarg.h>
#include "windows.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "commctrl.h"
#include "objidl.h"
@ -49,7 +52,7 @@ static PVOID (WINAPI *pDPA_DeleteAllPtrs)(const HDPA);
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);
@ -63,7 +66,7 @@ static BOOL (WINAPI *pDPA_Sort)(const HDPA,PFNDPACOMPARE,LPARAM);
#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)
{
@ -112,7 +115,7 @@ static PVOID CALLBACK CB_MergeInsertSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
{
ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
return p1;
}
}
static PVOID CALLBACK CB_MergeDeleteOddSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
{
@ -123,7 +126,7 @@ static PVOID CALLBACK CB_MergeDeleteOddSrc(UINT op, PVOID p1, PVOID p2, LPARAM l
static INT nEnum;
static INT CALLBACK CB_EnumFirstThree(PVOID pItem, PVOID lp)
{
{
INT i;
i = pDPA_GetPtrIndex(lp, pItem);
@ -136,12 +139,12 @@ static INT CALLBACK CB_EnumFirstThree(PVOID pItem, PVOID lp)
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;
}
@ -149,14 +152,14 @@ static HRESULT CALLBACK CB_Load(LPITEMDATA pInfo, IStream *pStm, LPARAM lp)
{
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;
}
@ -171,23 +174,23 @@ static BOOL CheckDPA(HDPA dpa, DWORD dwIn, PDWORD pdwOut)
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;
}
@ -200,16 +203,17 @@ static void test_dpa(void)
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");
@ -217,8 +221,9 @@ static void test_dpa(void)
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);
@ -228,11 +233,12 @@ static void test_dpa(void)
/* 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++)
{
@ -245,24 +251,29 @@ static void test_dpa(void)
/* 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++)
{
@ -281,11 +292,11 @@ static void test_dpa(void)
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);
@ -295,10 +306,11 @@ static void test_dpa(void)
/* 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 */
@ -313,8 +325,9 @@ static void test_dpa(void)
/* 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++)
@ -330,39 +343,49 @@ static void test_dpa(void)
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)
@ -388,31 +411,34 @@ static void test_dpa(void)
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);
@ -424,12 +450,6 @@ START_TEST(dpa)
hcomctl32 = GetModuleHandleA("comctl32.dll");
if(!hcomctl32)
{
ok(0, "error=%ld\n", GetLastError());
return;
}
if(InitFunctionPtrs(hcomctl32))
test_dpa();
else

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,9 @@
/* 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
@ -18,10 +20,19 @@
* 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"
@ -35,6 +46,24 @@
#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;
@ -264,7 +293,7 @@ static void testHotspot (void)
/* 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);
@ -283,6 +312,8 @@ static void testHotspot (void)
#undef SIZEX2
#undef SIZEY2
#undef HOTSPOTS_MAX
ImageList_Destroy(himl2);
ImageList_Destroy(himl1);
DestroyWindow(hwnd);
}
@ -327,13 +358,20 @@ static BOOL DoTest1(void)
/* 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;
}
@ -366,10 +404,9 @@ static BOOL DoTest2(void)
/* 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;
}
@ -541,10 +578,395 @@ static void testMerge(void)
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);
@ -557,4 +979,5 @@ START_TEST(imagelist)
DoTest2();
DoTest3();
testMerge();
test_imagelist_storage();
}

View file

@ -2,6 +2,7 @@
* 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
@ -23,10 +24,318 @@
#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;
@ -43,7 +352,7 @@ static void test_images(void)
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");
@ -63,6 +372,7 @@ static void test_images(void)
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");
@ -94,14 +404,14 @@ static void test_images(void)
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");
@ -113,7 +423,7 @@ static void test_checkboxes(void)
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;
@ -129,7 +439,7 @@ static void test_checkboxes(void)
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;
@ -147,13 +457,13 @@ static void test_checkboxes(void)
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;
@ -161,14 +471,14 @@ static void test_checkboxes(void)
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;
@ -189,9 +499,19 @@ static void test_checkboxes(void)
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;
@ -201,7 +521,7 @@ static void test_checkboxes(void)
/* 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;
@ -211,7 +531,7 @@ static void test_checkboxes(void)
/* 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;
@ -222,6 +542,502 @@ static void test_checkboxes(void)
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;
@ -230,6 +1046,22 @@ START_TEST(listview)
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();
}

View file

@ -0,0 +1,159 @@
/*
* 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);
}

File diff suppressed because it is too large Load diff

View file

@ -111,7 +111,7 @@ static void check_reg_entries(const char *mrulist, const char**items)
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",
@ -128,7 +128,7 @@ static void check_reg_entries(const char *mrulist, const char**items)
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']),
@ -165,37 +165,39 @@ static void test_MRUListA(void)
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;
@ -204,9 +206,9 @@ static void test_MRUListA(void)
"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)
@ -220,38 +222,39 @@ static void test_MRUListA(void)
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);
@ -261,7 +264,7 @@ static void test_MRUListA(void)
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);
@ -269,7 +272,7 @@ static void test_MRUListA(void)
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);
@ -285,8 +288,6 @@ static void test_MRUListA(void)
START_TEST(mru)
{
hComctl32 = GetModuleHandleA("comctl32.dll");
if (!hComctl32)
return;
delete_reg_entries();
if (!create_reg_entries())

View file

@ -0,0 +1,251 @@
/* 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)
{
}

View file

@ -0,0 +1,73 @@
/* 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);

View file

@ -24,27 +24,42 @@
#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;
}
@ -52,7 +67,7 @@ static WNDPROC progress_wndproc;
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)
{
@ -69,7 +84,7 @@ LRESULT CALLBACK ProgressSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
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");
}
@ -78,29 +93,29 @@ static void init(void)
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);
@ -110,23 +125,24 @@ static void init(void)
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));
}
@ -147,20 +163,20 @@ static void test_redraw(void)
/* 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.
@ -175,7 +191,7 @@ static void test_redraw(void)
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);
@ -187,7 +203,7 @@ static void test_redraw(void)
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);
@ -198,8 +214,8 @@ static void test_redraw(void)
START_TEST(progress)
{
init();
test_redraw();
cleanup();
}

View file

@ -17,9 +17,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include <windows.h>
#include <commctrl.h>
@ -39,7 +36,7 @@ static int CALLBACK sheet_callback(HWND hwnd, UINT msg, LPARAM lparam)
}
return 0;
}
static INT_PTR CALLBACK page_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
LPARAM lparam)
{
@ -81,8 +78,8 @@ static void test_title(void)
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;
@ -94,14 +91,49 @@ static void test_title(void)
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);
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;
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);
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();
}

View file

@ -0,0 +1,831 @@
/* 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);
}

View file

@ -0,0 +1,34 @@
/*
* 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 */

View file

@ -1,6 +1,7 @@
/* 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
@ -19,6 +20,7 @@
#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
@ -27,3 +29,19 @@ FONT 8, "MS Shell Dlg"
{
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

View file

@ -0,0 +1,196 @@
/* 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();
}

View file

@ -156,7 +156,7 @@ static void ok_sequence(const struct message *expected, const char *context)
"%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++;
@ -169,7 +169,7 @@ static void ok_sequence(const struct message *expected, const char *context)
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;
@ -183,7 +183,7 @@ static WNDPROC origProc3;
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;
@ -195,12 +195,12 @@ static LRESULT WINAPI WndProc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lP
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);
@ -275,20 +275,23 @@ static BOOL RegisterWindowClasses(void)
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;

View file

@ -1,6 +1,7 @@
/* 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
@ -20,13 +21,24 @@
#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)
@ -39,19 +51,222 @@
#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)
{
@ -94,6 +309,195 @@ 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;
@ -110,7 +514,7 @@ static void test_tab(INT nMinTabWidth)
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);
@ -223,8 +627,338 @@ static void test_tab(INT nMinTabWidth)
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");
@ -246,4 +980,17 @@ START_TEST(tab)
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);
}

View file

@ -1,3 +1,5 @@
/* Automatically generated file; DO NOT EDIT!! */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -5,36 +7,48 @@
#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 }

File diff suppressed because it is too large Load diff

View file

@ -38,10 +38,10 @@ static void test_create_tooltip(void)
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);
@ -51,9 +51,9 @@ static void test_create_tooltip(void)
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);

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
/* 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
@ -26,13 +27,167 @@
#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;
@ -70,6 +225,7 @@ static void IdentifyItem(HTREEITEM hItem)
static void FillRoot(void)
{
TVINSERTSTRUCTA ins;
TVITEM tvi;
static CHAR root[] = "Root",
child[] = "Child";
@ -82,6 +238,13 @@ static void FillRoot(void)
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;
@ -132,23 +295,326 @@ static void DoTest2(void)
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) {
@ -166,15 +632,15 @@ LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
}
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);
}
@ -186,18 +652,18 @@ START_TEST(treeview)
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";
@ -206,12 +672,29 @@ START_TEST(treeview)
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)) {

View file

@ -1,6 +1,8 @@
/* 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
@ -17,82 +19,574 @@
* 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"
static HDC desktopDC;
static HINSTANCE hinst;
#define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
static HWND create_edit_control (DWORD style, DWORD exstyle)
#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 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 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;
static long defwndproc_counter = 0;
LRESULT ret;
struct message msg;
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;
/* 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;
WNDCLASSA cls;
/* 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;
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;
if (!register_parent_wnd_class())
return NULL;
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);
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);
}
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)
{
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)
{
desktopDC=GetDC(NULL);
hinst = GetModuleHandleA(NULL);
InitCommonControls();
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
test_updown_control();
test_create_updown_control();
}