[COMCTL32_WINETEST]

sync to wine 1.2 RC2

svn path=/trunk/; revision=47448
This commit is contained in:
Christoph von Wittich 2010-05-30 15:19:09 +00:00
parent 769948f75a
commit d6fb44f0d7
29 changed files with 8176 additions and 1893 deletions

View file

@ -22,11 +22,23 @@
#include <commctrl.h>
#include "wine/test.h"
#include "msg.h"
#define EDITBOX_SEQ_INDEX 0
#define NUM_MSG_SEQUENCES 1
#define EDITBOX_ID 0
#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
static HWND hComboExParentWnd;
static HINSTANCE hMainHinst;
static const char ComboExTestClass[] = "ComboExTestClass";
static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
#define MAX_CHARS 100
static char *textBuffer = NULL;
@ -42,7 +54,7 @@ static LONG addItem(HWND cbex, int idx, LPTSTR text) {
cbexItem.iItem = idx;
cbexItem.pszText = text;
cbexItem.cchTextMax = 0;
return (LONG)SendMessage(cbex, CBEM_INSERTITEM, 0,(LPARAM)&cbexItem);
return SendMessage(cbex, CBEM_INSERTITEM, 0, (LPARAM)&cbexItem);
}
static LONG setItem(HWND cbex, int idx, LPTSTR text) {
@ -52,11 +64,11 @@ static LONG setItem(HWND cbex, int idx, LPTSTR text) {
cbexItem.iItem = idx;
cbexItem.pszText = text;
cbexItem.cchTextMax = 0;
return (LONG)SendMessage(cbex, CBEM_SETITEM, 0,(LPARAM)&cbexItem);
return SendMessage(cbex, CBEM_SETITEM, 0, (LPARAM)&cbexItem);
}
static LONG delItem(HWND cbex, int idx) {
return (LONG)SendMessage(cbex, CBEM_DELETEITEM, (LPARAM)idx, 0);
return SendMessage(cbex, CBEM_DELETEITEM, idx, 0);
}
static LONG getItem(HWND cbex, int idx, COMBOBOXEXITEM *cbItem) {
@ -65,7 +77,51 @@ static LONG getItem(HWND cbex, int idx, COMBOBOXEXITEM *cbItem) {
cbItem->pszText = textBuffer;
cbItem->iItem = idx;
cbItem->cchTextMax = 100;
return (LONG)SendMessage(cbex, CBEM_GETITEM, 0, (LPARAM)cbItem);
return SendMessage(cbex, CBEM_GETITEM, 0, (LPARAM)cbItem);
}
static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
static LONG defwndproc_counter = 0;
LRESULT ret;
struct message msg;
msg.message = message;
msg.flags = sent|wparam|lparam;
if (defwndproc_counter) msg.flags |= defwinproc;
msg.wParam = wParam;
msg.lParam = lParam;
msg.id = EDITBOX_ID;
if (message != WM_PAINT &&
message != WM_ERASEBKGND &&
message != WM_NCPAINT &&
message != WM_NCHITTEST &&
message != WM_GETTEXT &&
message != WM_GETICON &&
message != WM_DEVICECHANGE)
{
add_message(sequences, EDITBOX_SEQ_INDEX, &msg);
}
defwndproc_counter++;
ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
defwndproc_counter--;
return ret;
}
static HWND subclass_editbox(HWND hwndComboEx)
{
WNDPROC oldproc;
HWND hwnd;
hwnd = (HWND)SendMessage(hwndComboEx, CBEM_GETEDITCONTROL, 0, 0);
oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
(LONG_PTR)editbox_subclass_proc);
SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
return hwnd;
}
static void test_comboboxex(void) {
@ -288,6 +344,41 @@ static void test_WM_LBUTTONDOWN(void)
DestroyWindow(hComboEx);
}
static void test_CB_GETLBTEXT(void)
{
HWND hCombo;
CHAR buff[1];
COMBOBOXEXITEMA item;
LRESULT ret;
hCombo = createComboEx(WS_BORDER | WS_VISIBLE | WS_CHILD | CBS_DROPDOWN);
/* set text to null */
addItem(hCombo, 0, NULL);
buff[0] = 'a';
item.mask = CBEIF_TEXT;
item.iItem = 0;
item.pszText = buff;
item.cchTextMax = 1;
ret = SendMessage(hCombo, CBEM_GETITEMA, 0, (LPARAM)&item);
ok(ret != 0, "CBEM_GETITEM failed\n");
ok(buff[0] == 0, "\n");
ret = SendMessage(hCombo, CB_GETLBTEXTLEN, 0, 0);
ok(ret == 0, "Expected zero length\n");
ret = SendMessage(hCombo, CB_GETLBTEXTLEN, 0, 0);
ok(ret == 0, "Expected zero length\n");
buff[0] = 'a';
ret = SendMessage(hCombo, CB_GETLBTEXT, 0, (LPARAM)buff);
ok(ret == 0, "Expected zero length\n");
ok(buff[0] == 0, "Expected null terminator as a string, got %s\n", buff);
DestroyWindow(hCombo);
}
static LRESULT CALLBACK ComboExTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg) {
@ -321,6 +412,8 @@ static int init(void)
iccex.dwICC = ICC_USEREX_CLASSES;
pInitCommonControlsEx(&iccex);
pSetWindowSubclass = (void*)GetProcAddress(hComctl32, (LPSTR)410);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
@ -355,13 +448,87 @@ static void cleanup(void)
UnregisterClassA(ComboExTestClass, GetModuleHandleA(NULL));
}
static void test_comboboxex_subclass(void)
{
HWND hComboEx, hCombo, hEdit;
hComboEx = createComboEx(WS_BORDER | WS_VISIBLE | WS_CHILD | CBS_DROPDOWN);
hCombo = (HWND)SendMessage(hComboEx, CBEM_GETCOMBOCONTROL, 0, 0);
ok(hCombo != NULL, "Failed to get internal combo\n");
hEdit = (HWND)SendMessage(hComboEx, CBEM_GETEDITCONTROL, 0, 0);
ok(hEdit != NULL, "Failed to get internal edit\n");
if (pSetWindowSubclass)
{
ok(GetPropA(hCombo, "CC32SubclassInfo") != NULL, "Expected CC32SubclassInfo property\n");
ok(GetPropA(hEdit, "CC32SubclassInfo") != NULL, "Expected CC32SubclassInfo property\n");
}
DestroyWindow(hComboEx);
}
static const struct message test_setitem_edit_seq[] = {
{ WM_SETTEXT, sent|id, 0, 0, EDITBOX_ID },
{ EM_SETSEL, sent|id|wparam|lparam, 0, 0, EDITBOX_ID },
{ EM_SETSEL, sent|id|wparam|lparam, 0, -1, EDITBOX_ID },
{ 0 }
};
static void test_get_set_item(void)
{
char textA[] = "test";
HWND hComboEx;
COMBOBOXEXITEMA item;
BOOL ret;
hComboEx = createComboEx(WS_BORDER | WS_VISIBLE | WS_CHILD | CBS_DROPDOWN);
subclass_editbox(hComboEx);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
memset(&item, 0, sizeof(item));
item.mask = CBEIF_TEXT;
item.pszText = textA;
item.iItem = -1;
ret = SendMessage(hComboEx, CBEM_SETITEMA, 0, (LPARAM)&item);
expect(TRUE, ret);
ok_sequence(sequences, EDITBOX_SEQ_INDEX, test_setitem_edit_seq, "set item data for edit", FALSE);
/* get/set lParam */
item.mask = CBEIF_LPARAM;
item.iItem = -1;
item.lParam = 0xdeadbeef;
ret = SendMessage(hComboEx, CBEM_GETITEMA, 0, (LPARAM)&item);
expect(TRUE, ret);
ok(item.lParam == 0, "Expected zero, got %ld\n", item.lParam);
item.lParam = 0xdeadbeef;
ret = SendMessage(hComboEx, CBEM_SETITEMA, 0, (LPARAM)&item);
expect(TRUE, ret);
item.lParam = 0;
ret = SendMessage(hComboEx, CBEM_GETITEMA, 0, (LPARAM)&item);
expect(TRUE, ret);
ok(item.lParam == 0xdeadbeef, "Expected 0xdeadbeef, got %ld\n", item.lParam);
DestroyWindow(hComboEx);
}
START_TEST(comboex)
{
if (!init())
return;
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
test_comboboxex();
test_WM_LBUTTONDOWN();
test_CB_GETLBTEXT();
test_comboboxex_subclass();
test_get_set_item();
cleanup();
}

View file

@ -4,6 +4,8 @@
<module name="comctl32_winetest" type="win32cui" installbase="bin" installname="comctl32_winetest.exe" allowwarnings="true">
<include base="comctl32_winetest">.</include>
<define name="__ROS_LONG64__" />
<redefine name="_WIN32_WINNT">0x0600</redefine>
<redefine name="_WIN32_IE">0x0500</redefine>
<file>comboex.c</file>
<file>datetime.c</file>
<file>dpa.c</file>
@ -14,7 +16,6 @@
<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>

View file

@ -1,37 +0,0 @@
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"
Index: mru.c
===================================================================
--- mru.c (revision 25766)
+++ mru.c (working copy)
@@ -75,7 +75,7 @@
/* Based on RegDeleteTreeW from dlls/advapi32/registry.c */
-static LSTATUS mru_RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
+static LONG mru_RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
{
LONG ret;
DWORD dwMaxSubkeyLen, dwMaxValueLen;

View file

@ -33,113 +33,97 @@
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 },
{ DTM_SETFORMATA, sent|wparam|lparam, 0, 0 },
{ DTM_SETFORMATA, sent|wparam, 0 },
{ 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 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(255, 255, 255) },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, RGB(100, 180, 220) },
{ DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_BACKGROUND, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(255, 255, 255) },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_MONTHBK, RGB(100, 180, 220) },
{ DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_MONTHBK, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TEXT, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(255, 255, 255) },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TEXT, RGB(100, 180, 220) },
{ DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_TEXT, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(255, 255, 255) },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLEBK, RGB(100, 180, 220) },
{ DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_TITLEBK, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(255, 255, 255) },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, RGB(100, 180, 220) },
{ DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_TITLETEXT, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0 },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(255, 255, 255) },
{ DTM_SETMCCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, RGB(100, 180, 220) },
{ DTM_GETMCCOLOR, sent|wparam|lparam, MCSC_TRAILINGTEXT, 0 },
{ 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 },
{ DTM_SETMCFONT, sent|lparam, 0, 1 },
{ DTM_GETMCFONT, sent|wparam|lparam, 0, 0 },
{ 0 }
};
static const struct message test_dtm_get_monthcal_seq[] = {
{ DTM_GETMONTHCAL, sent|wparam|lparam, 0x00000000, 0x00000000 },
{ DTM_GETMONTHCAL, sent|wparam|lparam, 0, 0 },
{ 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 },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN },
{ DTM_GETRANGE, sent|wparam, 0 },
{ DTM_SETRANGE, sent|wparam, GDTR_MAX },
{ DTM_SETRANGE, sent|wparam, GDTR_MAX },
{ DTM_GETRANGE, sent|wparam, 0 },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
{ DTM_GETRANGE, sent|wparam, 0 },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
{ DTM_GETRANGE, sent|wparam, 0 },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
{ DTM_GETRANGE, sent|wparam, 0 },
{ 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 },
{ DTM_SETSYSTEMTIME, sent|wparam, 0 },
{ DTM_GETSYSTEMTIME, sent|wparam, 0 },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
{ DTM_GETRANGE, sent|wparam, 0 },
{ DTM_SETSYSTEMTIME, sent|wparam, 0 },
{ DTM_GETSYSTEMTIME, sent|wparam, 0 },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
{ DTM_GETRANGE, sent|wparam, 0 },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
{ DTM_GETRANGE, sent|wparam, 0 },
{ DTM_SETRANGE, sent|wparam, GDTR_MIN | GDTR_MAX },
{ DTM_GETRANGE, sent|wparam, 0 },
{ 0 }
};
static const struct message test_dtm_set_and_get_system_time_seq[] = {
{ DTM_SETSYSTEMTIME, sent|wparam, 0x00000001 },
{ 0x0090, sent|optional }, /* Vista */
{ 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 },
{ DTM_SETSYSTEMTIME, sent|wparam, GDT_NONE },
{ DTM_GETSYSTEMTIME, sent|wparam, 0 },
{ DTM_SETSYSTEMTIME, sent|wparam, 0 },
{ DTM_SETSYSTEMTIME, sent|wparam, 0 },
{ DTM_SETSYSTEMTIME, sent|wparam, 0 },
{ DTM_GETSYSTEMTIME, sent|wparam, 0 },
{ DTM_SETSYSTEMTIME, sent|wparam, 0 },
{ 0 }
};
static const struct message destroy_window_seq[] = {
{ 0x0090, sent|optional }, /* Vista */
{ 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);
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
static LONG defwndproc_counter = 0;
LRESULT ret;
struct message msg;
@ -154,21 +138,17 @@ static LRESULT WINAPI datetime_subclass_proc(HWND hwnd, UINT message, WPARAM wPa
add_message(sequences, DATETIME_SEQ_INDEX, &msg);
defwndproc_counter++;
ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
defwndproc_counter--;
return ret;
}
static HWND create_datetime_control(DWORD style, DWORD exstyle)
static HWND create_datetime_control(DWORD style)
{
struct subclass_info *info;
WNDPROC oldproc;
HWND hWndDateTime = NULL;
info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
if (!info)
return NULL;
hWndDateTime = CreateWindowEx(0,
DATETIMEPICK_CLASS,
NULL,
@ -179,44 +159,47 @@ static HWND create_datetime_control(DWORD style, DWORD exstyle)
NULL,
NULL);
if (!hWndDateTime) {
HeapFree(GetProcessHeap(), 0, info);
return NULL;
}
if (!hWndDateTime) return NULL;
info->oldproc = (WNDPROC)SetWindowLongPtrA(hWndDateTime, GWLP_WNDPROC,
(LONG_PTR)datetime_subclass_proc);
SetWindowLongPtrA(hWndDateTime, GWLP_USERDATA, (LONG_PTR)info);
oldproc = (WNDPROC)SetWindowLongPtrA(hWndDateTime, GWLP_WNDPROC,
(LONG_PTR)datetime_subclass_proc);
SetWindowLongPtrA(hWndDateTime, GWLP_USERDATA, (LONG_PTR)oldproc);
return hWndDateTime;
}
static void test_dtm_set_format(HWND hWndDateTime)
static void test_dtm_set_format(void)
{
HWND hWnd;
CHAR txt[256];
SYSTEMTIME systime;
LRESULT r;
r = SendMessage(hWndDateTime, DTM_SETFORMAT, 0, 0);
hWnd = create_datetime_control(DTS_SHOWNONE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessage(hWnd, DTM_SETFORMAT, 0, 0);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_SETFORMAT, 0,
r = SendMessage(hWnd, 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);
r = SendMessage(hWndDateTime, DTM_SETFORMAT, 0,
r = SendMessage(hWnd, DTM_SETFORMAT, 0,
(LPARAM)"'hh' hh");
expect(1, r);
ZeroMemory(&systime, sizeof(systime));
systime.wYear = 2000;
systime.wMonth = systime.wDay = 1;
r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, 0, (LPARAM)&systime);
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, 0, (LPARAM)&systime);
expect(1, r);
GetWindowText(hWndDateTime, txt, 256);
todo_wine ok(strcmp(txt, "hh 12") == 0, "String mismatch (\"%s\" vs \"hh 12\")\n", txt);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
GetWindowText(hWnd, txt, 256);
ok(strcmp(txt, "hh 12") == 0, "String mismatch (\"%s\" vs \"hh 12\")\n", txt);
DestroyWindow(hWnd);
}
static void test_mccolor_types(HWND hWndDateTime, int mccolor_type, const char* mccolor_name)
@ -239,43 +222,60 @@ static void test_mccolor_types(HWND hWndDateTime, int mccolor_type, const char*
ok(r==theColor, "%s: GETMCCOLOR: Expected %d, got %ld\n", mccolor_name, theColor, r);
}
static void test_dtm_set_and_get_mccolor(HWND hWndDateTime)
static void test_dtm_set_and_get_mccolor(void)
{
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");
HWND hWnd;
hWnd = create_datetime_control(DTS_SHOWNONE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
test_mccolor_types(hWnd, MCSC_BACKGROUND, "MCSC_BACKGROUND");
test_mccolor_types(hWnd, MCSC_MONTHBK, "MCSC_MONTHBK");
test_mccolor_types(hWnd, MCSC_TEXT, "MCSC_TEXT");
test_mccolor_types(hWnd, MCSC_TITLEBK, "MCSC_TITLEBK");
test_mccolor_types(hWnd, MCSC_TITLETEXT, "MCSC_TITLETEXT");
test_mccolor_types(hWnd, 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);
DestroyWindow(hWnd);
}
static void test_dtm_set_and_get_mcfont(HWND hWndDateTime)
static void test_dtm_set_and_get_mcfont(void)
{
HFONT hFontOrig, hFontNew;
HWND hWnd;
hWnd = create_datetime_control(DTS_SHOWNONE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
hFontOrig = GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hWndDateTime, DTM_SETMCFONT, (WPARAM)hFontOrig, TRUE);
hFontNew = (HFONT)SendMessage(hWndDateTime, DTM_GETMCFONT, 0, 0);
SendMessage(hWnd, DTM_SETMCFONT, (WPARAM)hFontOrig, TRUE);
hFontNew = (HFONT)SendMessage(hWnd, 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);
DestroyWindow(hWnd);
}
static void test_dtm_get_monthcal(HWND hWndDateTime)
static void test_dtm_get_monthcal(void)
{
LRESULT r;
HWND hWnd;
hWnd = create_datetime_control(DTS_SHOWNONE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
todo_wine {
r = SendMessage(hWndDateTime, DTM_GETMONTHCAL, 0, 0);
r = SendMessage(hWnd, DTM_GETMONTHCAL, 0, 0);
ok(r == 0, "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);
DestroyWindow(hWnd);
}
static void fill_systime_struct(SYSTEMTIME *st, int year, int month, int dayofweek, int day, int hour, int minute, int second, int milliseconds)
@ -318,24 +318,29 @@ static LPARAM compare_systime(SYSTEMTIME *st1, SYSTEMTIME *st2)
#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)
static void test_dtm_set_and_get_range(void)
{
LRESULT r;
SYSTEMTIME st[2];
SYSTEMTIME getSt[2];
HWND hWnd;
hWnd = create_datetime_control(DTS_SHOWNONE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* initialize st[0] to lowest possible value */
fill_systime_struct(&st[0], 1601, 1, 0, 1, 0, 0, 0, 0);
/* initialize 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MIN, (LPARAM)st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
r = SendMessage(hWnd, 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MAX, (LPARAM)st);
expect_unsuccess(0, r);
/* set st[0] to all invalid numbers */
@ -343,25 +348,25 @@ static void test_dtm_set_and_get_range(HWND hWndDateTime)
/* 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MAX, (LPARAM)st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
r = SendMessage(hWnd, 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MIN, (LPARAM)st);
expect_unsuccess(0, r);
r = SendMessage(hWndDateTime, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
r = SendMessage(hWnd, 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
r = SendMessage(hWnd, 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]);
@ -371,9 +376,9 @@ static void test_dtm_set_and_get_range(HWND hWndDateTime)
/* 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
r = SendMessage(hWnd, 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]);
@ -383,32 +388,37 @@ static void test_dtm_set_and_get_range(HWND hWndDateTime)
/* 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
r = SendMessage(hWnd, 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);
DestroyWindow(hWnd);
}
/* 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)
static void test_dtm_set_range_swap_min_max(void)
{
LRESULT r;
SYSTEMTIME st[2];
SYSTEMTIME getSt[2];
SYSTEMTIME origSt;
HWND hWnd;
hWnd = create_datetime_control(DTS_SHOWNONE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
fill_systime_struct(&st[0], 2007, 2, 4, 15, 2, 2, 2, 2);
r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&origSt);
r = SendMessage(hWnd, 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);
@ -418,28 +428,33 @@ static void test_dtm_set_range_swap_min_max(HWND hWndDateTime)
/* 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
r = SendMessage(hWnd, 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]);
ok(compare_systime(&st[0], &getSt[0]) == 1 ||
broken(compare_systime(&st[0], &getSt[1]) == 1), /* comctl32 version <= 5.80 */
"ST1 != ST2\n");
ok(compare_systime(&st[1], &getSt[1]) == 1 ||
broken(compare_systime(&st[1], &getSt[0]) == 1), /* comctl32 version <= 5.80 */
"ST1 != ST2\n");
}
fill_systime_struct(&st[0], 1980, 1, 3, 23, 14, 34, 37, 465);
r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st[0]);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt[0]);
r = SendMessage(hWnd, 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]);
ok(compare_systime_time(&origSt, &getSt[0]) == 1 ||
broken(compare_systime_time(&st[0], &getSt[0]) == 1), /* comctl32 version <= 5.80 */
"ST1.time != ST2.time\n");
}
/* set st[0] to value higher than minimum */
@ -447,18 +462,21 @@ static void test_dtm_set_range_swap_min_max(HWND hWndDateTime)
/* 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);
r = SendMessage(hWnd, 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);
r = SendMessage(hWnd, 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]);
ok(compare_systime(&st[0], &getSt[1]) == 1 ||
broken(compare_systime(&st[0], &getSt[0]) == 1), /* comctl32 version <= 5.80 */
"ST1 != ST2\n");
ok(compare_systime(&st[1], &getSt[0]) == 1 ||
broken(compare_systime(&st[1], &getSt[1]) == 1), /* comctl32 version <= 5.80 */
"ST1 != ST2\n");
}
/* set st[0] to value higher than st[1] */
@ -467,9 +485,9 @@ static void test_dtm_set_range_swap_min_max(HWND hWndDateTime)
/* 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
r = SendMessage(hWnd, 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]);
@ -479,25 +497,25 @@ static void test_dtm_set_range_swap_min_max(HWND hWndDateTime)
/* 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);
r = SendMessage(hWnd, DTM_SETRANGE, GDTR_MIN | GDTR_MAX, (LPARAM)st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETRANGE, 0, (LPARAM)getSt);
r = SendMessage(hWnd, 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);
DestroyWindow(hWnd);
}
static void test_dtm_set_and_get_system_time(HWND hWndDateTime)
static void test_dtm_set_and_get_system_time(void)
{
LRESULT r;
SYSTEMTIME st;
SYSTEMTIME getSt;
HWND hWndDateTime_test_gdt_none;
SYSTEMTIME st, getSt, ref;
HWND hWnd, hWndDateTime_test_gdt_none;
hWndDateTime_test_gdt_none = create_datetime_control(0, 0);
hWndDateTime_test_gdt_none = create_datetime_control(0);
ok(hWndDateTime_test_gdt_none!=NULL, "Expected non NULL, got %p\n", hWndDateTime_test_gdt_none);
if(hWndDateTime_test_gdt_none) {
@ -513,64 +531,175 @@ static void test_dtm_set_and_get_system_time(HWND hWndDateTime)
DestroyWindow(hWndDateTime_test_gdt_none);
r = SendMessage(hWndDateTime, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
hWnd = create_datetime_control(DTS_SHOWNONE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_NONE, (LPARAM)&st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
r = SendMessage(hWnd, 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);
r = SendMessage(hWnd, 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);
r = SendMessage(hWnd, 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);
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
expect(1, r);
r = SendMessage(hWndDateTime, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
r = SendMessage(hWnd, 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);
r = SendMessage(hWnd, 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);
/* set to some valid value */
GetSystemTime(&ref);
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&ref);
expect(1, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
expect_systime(&ref, &getSt);
/* year invalid */
st = ref;
st.wYear = 0;
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
todo_wine expect(1, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
expect_systime(&ref, &getSt);
/* month invalid */
st = ref;
st.wMonth = 13;
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
expect(0, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
expect_systime(&ref, &getSt);
/* day invalid */
st = ref;
st.wDay = 32;
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
expect(0, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
expect_systime(&ref, &getSt);
/* day of week isn't validated */
st = ref;
st.wDayOfWeek = 10;
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
expect(1, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
expect_systime(&ref, &getSt);
/* hour invalid */
st = ref;
st.wHour = 25;
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
expect(0, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
expect_systime(&ref, &getSt);
/* minute invalid */
st = ref;
st.wMinute = 60;
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
expect(0, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
expect_systime(&ref, &getSt);
/* sec invalid */
st = ref;
st.wSecond = 60;
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
expect(0, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
expect_systime(&ref, &getSt);
/* msec invalid */
st = ref;
st.wMilliseconds = 1000;
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
expect(0, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
expect_systime(&ref, &getSt);
/* day of week should be calculated automatically,
actual day of week for this date is 4 */
fill_systime_struct(&st, 2009, 10, 1, 1, 0, 0, 10, 200);
r = SendMessage(hWnd, DTM_SETSYSTEMTIME, GDT_VALID, (LPARAM)&st);
expect(1, r);
r = SendMessage(hWnd, DTM_GETSYSTEMTIME, 0, (LPARAM)&getSt);
expect(GDT_VALID, r);
/* 01.10.2009 is Thursday */
expect(4, (LRESULT)getSt.wDayOfWeek);
st.wDayOfWeek = 4;
expect_systime(&st, &getSt);
DestroyWindow(hWnd);
}
static void test_datetime_control(void)
static void test_wm_set_get_text(void)
{
HWND hWndDateTime;
static const CHAR a_str[] = "a";
char buff[16], time[16];
HWND hWnd;
LRESULT ret;
hWndDateTime = create_datetime_control(DTS_SHOWNONE, 0);
hWnd = create_datetime_control(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");
}
ret = SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)a_str);
ok(CB_ERR == ret ||
broken(0 == ret) || /* comctl32 <= 4.72 */
broken(1 == ret), /* comctl32 <= 4.70 */
"Expected CB_ERR, got %ld\n", ret);
DestroyWindow(hWndDateTime);
ok_sequence(sequences, DATETIME_SEQ_INDEX, destroy_window_seq, "test_dtm_set_and_get_system_time", TRUE);
buff[0] = 0;
ret = SendMessage(hWnd, WM_GETTEXT, sizeof(buff), (LPARAM)buff);
ok(strcmp(buff, a_str) != 0, "Expected text not to change, got %s\n", buff);
GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL, NULL, time, sizeof(time));
ok(!strcmp(buff, time), "Expected %s, got %s\n", time, buff);
DestroyWindow(hWnd);
}
static void test_dts_shownone(void)
{
HWND hwnd;
DWORD style;
/* it isn't allowed to change DTS_SHOWNONE after creation */
hwnd = create_datetime_control(0);
style = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, style | DTS_SHOWNONE);
style = GetWindowLong(hwnd, GWL_STYLE);
ok(!(style & DTS_SHOWNONE), "Expected DTS_SHOWNONE not to be set\n");
DestroyWindow(hwnd);
hwnd = create_datetime_control(DTS_SHOWNONE);
style = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, style & ~DTS_SHOWNONE);
style = GetWindowLong(hwnd, GWL_STYLE);
ok(style & DTS_SHOWNONE, "Expected DTS_SHOWNONE to be set\n");
DestroyWindow(hwnd);
}
START_TEST(datetime)
@ -592,5 +721,13 @@ START_TEST(datetime)
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
test_datetime_control();
test_dtm_set_format();
test_dtm_set_and_get_mccolor();
test_dtm_set_and_get_mcfont();
test_dtm_get_monthcal();
test_dtm_set_and_get_range();
test_dtm_set_range_swap_min_max();
test_dtm_set_and_get_system_time();
test_wm_set_get_text();
test_dts_shownone();
}

View file

@ -31,17 +31,14 @@
#include "wine/test.h"
#define DPAM_NOSORT 0x1
#define DPAM_INSERT 0x4
#define DPAM_DELETE 0x8
#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
typedef struct _ITEMDATA
typedef struct _STREAMDATA
{
INT iPos;
PVOID pvData;
} ITEMDATA, *LPITEMDATA;
typedef HRESULT (CALLBACK *PFNDPASTM)(LPITEMDATA,IStream*,LPARAM);
DWORD dwSize;
DWORD dwData2;
DWORD dwItems;
} STREAMDATA, *PSTREAMDATA;
static HDPA (WINAPI *pDPA_Clone)(const HDPA,const HDPA);
static HDPA (WINAPI *pDPA_Create)(INT);
@ -55,9 +52,9 @@ static INT (WINAPI *pDPA_GetPtr)(const HDPA,INT);
static INT (WINAPI *pDPA_GetPtrIndex)(const HDPA,PVOID);
static BOOL (WINAPI *pDPA_Grow)(HDPA,INT);
static INT (WINAPI *pDPA_InsertPtr)(const HDPA,INT,PVOID);
static HRESULT (WINAPI *pDPA_LoadStream)(HDPA*,PFNDPASTM,IStream*,LPARAM);
static HRESULT (WINAPI *pDPA_LoadStream)(HDPA*,PFNDPASTREAM,IStream*,LPVOID);
static BOOL (WINAPI *pDPA_Merge)(const HDPA,const HDPA,DWORD,PFNDPACOMPARE,PFNDPAMERGE,LPARAM);
static HRESULT (WINAPI *pDPA_SaveStream)(HDPA,PFNDPASTM,IStream*,LPARAM);
static HRESULT (WINAPI *pDPA_SaveStream)(HDPA,PFNDPASTREAM,IStream*,LPVOID);
static INT (WINAPI *pDPA_Search)(HDPA,PVOID,INT,PFNDPACOMPARE,LPARAM,UINT);
static BOOL (WINAPI *pDPA_SetPtr)(const HDPA,INT,PVOID);
static BOOL (WINAPI *pDPA_Sort)(const HDPA,PFNDPACOMPARE,LPARAM);
@ -109,14 +106,22 @@ static INT CALLBACK CB_CmpGT(PVOID p1, PVOID p2, LPARAM lp)
return p1 > p2 ? -1 : p1 < p2 ? 1 : 0;
}
/* merge callback messages counter
DPAMM_MERGE 1
DPAMM_DELETE 2
DPAMM_INSERT 3 */
static INT nMessages[4];
static PVOID CALLBACK CB_MergeInsertSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
{
nMessages[op]++;
ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
return p1;
}
static PVOID CALLBACK CB_MergeDeleteOddSrc(UINT op, PVOID p1, PVOID p2, LPARAM lp)
{
nMessages[op]++;
ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
return ((PCHAR)p2)+1;
}
@ -134,30 +139,30 @@ static INT CALLBACK CB_EnumFirstThree(PVOID pItem, PVOID lp)
return pItem != (PVOID)3;
}
static HRESULT CALLBACK CB_Save(LPITEMDATA pInfo, IStream *pStm, LPARAM lp)
static HRESULT CALLBACK CB_Save(DPASTREAMINFO *pInfo, IStream *pStm, LPVOID lp)
{
HRESULT hRes;
ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
ok(lp == (LPVOID)0xdeadbeef, "lp=%p\n", lp);
hRes = IStream_Write(pStm, &pInfo->iPos, sizeof(INT), NULL);
ok(hRes == S_OK, "hRes=0x%x\n", hRes);
hRes = IStream_Write(pStm, &pInfo->pvData, sizeof(PVOID), NULL);
ok(hRes == S_OK, "hRes=0x%x\n", hRes);
expect(S_OK, hRes);
hRes = IStream_Write(pStm, &pInfo->pvItem, sizeof(PVOID), NULL);
expect(S_OK, hRes);
return S_OK;
}
static HRESULT CALLBACK CB_Load(LPITEMDATA pInfo, IStream *pStm, LPARAM lp)
static HRESULT CALLBACK CB_Load(DPASTREAMINFO *pInfo, IStream *pStm, LPVOID lp)
{
HRESULT hRes;
INT iOldPos;
iOldPos = pInfo->iPos;
ok(lp == 0xdeadbeef, "lp=%ld\n", lp);
ok(lp == (LPVOID)0xdeadbeef, "lp=%p\n", lp);
hRes = IStream_Read(pStm, &pInfo->iPos, sizeof(INT), NULL);
ok(hRes == S_OK, "hRes=0x%x\n", hRes);
expect(S_OK, 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%x\n", hRes);
hRes = IStream_Read(pStm, &pInfo->pvItem, sizeof(PVOID), NULL);
expect(S_OK, hRes);
return S_OK;
}
@ -200,7 +205,6 @@ static void test_dpa(void)
INT ret, i;
PVOID p;
DWORD dw, dw2, dw3;
HRESULT hRes;
BOOL rc;
GetSystemInfo(&si);
@ -209,9 +213,9 @@ static void test_dpa(void)
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,
ok(!ret && GetLastError() == ERROR_NOT_ENOUGH_MEMORY,
"ret=%d error=%d\n", ret, GetLastError());
dpa = pDPA_Create(0);
ok(dpa != NULL, "\n");
@ -288,9 +292,9 @@ static void test_dpa(void)
ok(j == DPA_ERR, "j=%d\n", j);
/* ... but for a binary search it's ignored */
j = pDPA_Search(dpa, (PVOID)(INT_PTR)i, i+1, CB_CmpLT, 0xdeadbeef, DPAS_SORTED);
todo_wine ok(j+1 == i, "j=%d i=%d\n", j, i);
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);
@ -335,49 +339,6 @@ static void test_dpa(void)
ok(j != i, "i=%d\n", i);
}
if(pDPA_Merge)
{
/* Delete all even entries from dpa */
p = pDPA_DeletePtr(dpa, 1);
p = pDPA_DeletePtr(dpa, 2);
p = pDPA_DeletePtr(dpa, 3);
rc=CheckDPA(dpa, 0x135, &dw);
ok(rc, "dw=0x%x\n", dw);
/* Delete all odd entries from dpa2 */
pDPA_Merge(dpa2, dpa, DPAM_DELETE,
CB_CmpLT, CB_MergeDeleteOddSrc, 0xdeadbeef);
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,
CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
pDPA_Merge(dpa2, dpa3, DPAM_INSERT|DPAM_NOSORT,
CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
rc=CheckDPA(dpa, 0x123456, &dw);
ok(rc, "dw=0x%x\n", dw);
rc=CheckDPA(dpa2, 0x123456, &dw2);
ok(rc ||
broken(!rc), /* win98 */
"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, dpa2);
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);
@ -386,62 +347,397 @@ static void test_dpa(void)
pDPA_DeleteAllPtrs(dpa2);
rc=CheckDPA(dpa2, 0, &dw2);
ok(rc, "dw2=0x%x\n", dw2);
pDPA_Destroy(dpa);
pDPA_Destroy(dpa2);
pDPA_Destroy(dpa3);
}
if(pDPA_DestroyCallback)
static void test_DPA_Merge(void)
{
HDPA dpa, dpa2, dpa3;
INT ret, i;
DWORD dw;
BOOL rc;
if(!pDPA_Merge)
{
nEnum = 0;
pDPA_DestroyCallback(dpa3, CB_EnumFirstThree, dpa3);
ok(nEnum == 3, "nEnum=%d\n", nEnum);
win_skip("DPA_Merge() not available\n");
return;
}
else pDPA_Destroy(dpa3);
if(!pDPA_SaveStream)
goto skip_stream_tests;
dpa = pDPA_Create(0);
dpa2 = pDPA_Create(0);
dpa3 = pDPA_Create(0);
ret = pDPA_InsertPtr(dpa, 0, (PVOID)1);
ok(ret == 0, "ret=%d\n", ret);
ret = pDPA_InsertPtr(dpa, 1, (PVOID)3);
ok(ret == 1, "ret=%d\n", ret);
ret = pDPA_InsertPtr(dpa, 2, (PVOID)5);
ok(ret == 2, "ret=%d\n", ret);
rc = CheckDPA(dpa, 0x135, &dw);
ok(rc, "dw=0x%x\n", dw);
for (i = 0; i < 6; i++)
{
ret = pDPA_InsertPtr(dpa2, i, (PVOID)(INT_PTR)(6-i));
ok(ret == i, "ret=%d\n", ret);
ret = pDPA_InsertPtr(dpa3, i, (PVOID)(INT_PTR)(i+1));
ok(ret == i, "ret=%d\n", ret);
}
rc = CheckDPA(dpa2, 0x654321, &dw);
ok(rc, "dw=0x%x\n", dw);
rc = CheckDPA(dpa3, 0x123456, &dw);
ok(rc, "dw=0x%x\n", dw);
/* Delete all odd entries from dpa2 */
memset(nMessages, 0, sizeof(nMessages));
pDPA_Merge(dpa2, dpa, DPAM_INTERSECT,
CB_CmpLT, CB_MergeDeleteOddSrc, 0xdeadbeef);
rc = CheckDPA(dpa2, 0x246, &dw);
ok(rc, "dw=0x%x\n", dw);
expect(3, nMessages[DPAMM_MERGE]);
expect(3, nMessages[DPAMM_DELETE]);
expect(0, nMessages[DPAMM_INSERT]);
for (i = 0; i < 6; i++)
{
ret = pDPA_InsertPtr(dpa2, i, (PVOID)(INT_PTR)(6-i));
ok(ret == i, "ret=%d\n", ret);
}
/* DPAM_INTERSECT - returning source while merging */
memset(nMessages, 0, sizeof(nMessages));
pDPA_Merge(dpa2, dpa, DPAM_INTERSECT,
CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
rc = CheckDPA(dpa2, 0x135, &dw);
ok(rc, "dw=0x%x\n", dw);
expect(3, nMessages[DPAMM_MERGE]);
expect(6, nMessages[DPAMM_DELETE]);
expect(0, nMessages[DPAMM_INSERT]);
/* DPAM_UNION */
pDPA_DeleteAllPtrs(dpa);
pDPA_InsertPtr(dpa, 0, (PVOID)1);
pDPA_InsertPtr(dpa, 1, (PVOID)3);
pDPA_InsertPtr(dpa, 2, (PVOID)5);
pDPA_DeleteAllPtrs(dpa2);
pDPA_InsertPtr(dpa2, 0, (PVOID)2);
pDPA_InsertPtr(dpa2, 1, (PVOID)4);
pDPA_InsertPtr(dpa2, 2, (PVOID)6);
memset(nMessages, 0, sizeof(nMessages));
pDPA_Merge(dpa2, dpa, DPAM_UNION,
CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
rc = CheckDPA(dpa2, 0x123456, &dw);
ok(rc ||
broken(!rc && dw == 0x23456), /* 4.7x */
"dw=0x%x\n", dw);
expect(0, nMessages[DPAMM_MERGE]);
expect(0, nMessages[DPAMM_DELETE]);
ok(nMessages[DPAMM_INSERT] == 3 ||
broken(nMessages[DPAMM_INSERT] == 2), /* 4.7x */
"Expected 3, got %d\n", nMessages[DPAMM_INSERT]);
/* Merge dpa3 into dpa2 and dpa */
memset(nMessages, 0, sizeof(nMessages));
pDPA_Merge(dpa, dpa3, DPAM_UNION|DPAM_SORTED,
CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
expect(3, nMessages[DPAMM_MERGE]);
expect(0, nMessages[DPAMM_DELETE]);
expect(3, nMessages[DPAMM_INSERT]);
pDPA_DeleteAllPtrs(dpa2);
pDPA_InsertPtr(dpa2, 0, (PVOID)2);
pDPA_InsertPtr(dpa2, 1, (PVOID)4);
pDPA_InsertPtr(dpa2, 2, (PVOID)6);
memset(nMessages, 0, sizeof(nMessages));
pDPA_Merge(dpa2, dpa3, DPAM_UNION|DPAM_SORTED,
CB_CmpLT, CB_MergeInsertSrc, 0xdeadbeef);
expect(3, nMessages[DPAMM_MERGE]);
expect(0, nMessages[DPAMM_DELETE]);
ok(nMessages[DPAMM_INSERT] == 3 ||
broken(nMessages[DPAMM_INSERT] == 2), /* 4.7x */
"Expected 3, got %d\n", nMessages[DPAMM_INSERT]);
rc = CheckDPA(dpa, 0x123456, &dw);
ok(rc, "dw=0x%x\n", dw);
rc = CheckDPA(dpa2, 0x123456, &dw);
ok(rc ||
broken(!rc), /* win98 */
"dw=0x%x\n", dw);
rc = CheckDPA(dpa3, 0x123456, &dw);
ok(rc, "dw=0x%x\n", dw);
pDPA_Destroy(dpa);
pDPA_Destroy(dpa2);
pDPA_Destroy(dpa3);
}
static void test_DPA_EnumCallback(void)
{
HDPA dpa;
BOOL rc;
DWORD dw;
INT i, ret;
if(!pDPA_EnumCallback)
{
win_skip("DPA_EnumCallback() not available\n");
return;
}
dpa = pDPA_Create(0);
for (i = 0; i < 6; i++)
{
ret = pDPA_InsertPtr(dpa, i, (PVOID)(INT_PTR)(i+1));
ok(ret == i, "ret=%d\n", ret);
}
rc = CheckDPA(dpa, 0x123456, &dw);
ok(rc, "dw=0x%x\n", dw);
nEnum = 0;
/* test callback sets first 3 items to 7 */
pDPA_EnumCallback(dpa, CB_EnumFirstThree, dpa);
rc = CheckDPA(dpa, 0x777456, &dw);
ok(rc, "dw=0x%x\n", dw);
ok(nEnum == 3, "nEnum=%d\n", nEnum);
pDPA_Destroy(dpa);
}
static void test_DPA_DestroyCallback(void)
{
HDPA dpa;
INT i, ret;
if(!pDPA_DestroyCallback)
{
win_skip("DPA_DestroyCallback() not available\n");
return;
}
dpa = pDPA_Create(0);
for (i = 0; i < 3; i++)
{
ret = pDPA_InsertPtr(dpa, i, (PVOID)(INT_PTR)(i+1));
ok(ret == i, "ret=%d\n", ret);
}
nEnum = 0;
pDPA_DestroyCallback(dpa, CB_EnumFirstThree, dpa);
ok(nEnum == 3, "nEnum=%d\n", nEnum);
}
static void test_DPA_LoadStream(void)
{
static const WCHAR szStg[] = { 'S','t','g',0 };
IStorage* pStg = NULL;
IStream* pStm = NULL;
LARGE_INTEGER li;
ULARGE_INTEGER uli;
DWORD dwMode;
HRESULT hRes;
STREAMDATA header;
ULONG written, ret;
HDPA dpa;
if(!pDPA_LoadStream)
{
win_skip("DPA_LoadStream() not available. Skipping stream tests.\n");
return;
}
hRes = CoInitialize(NULL);
if(hRes == S_OK)
if (hRes != S_OK)
{
static const WCHAR szStg[] = { 'S','t','g',0 };
IStorage* pStg = NULL;
IStream* pStm = NULL;
LARGE_INTEGER liZero;
DWORD dwMode;
liZero.QuadPart = 0;
dwMode = STGM_DIRECT|STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
ok(hRes == S_OK, "hRes=0x%x\n", hRes);
hRes = IStorage_CreateStream(pStg, szStg, dwMode, 0, 0, &pStm);
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%x\n", hRes);
pDPA_Destroy(dpa);
hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
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%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();
ok(0, "hResult: %d\n", hRes);
return;
}
else ok(0, "hResult: %d\n", hRes);
skip_stream_tests:
dwMode = STGM_DIRECT|STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
expect(S_OK, hRes);
hRes = IStorage_CreateStream(pStg, szStg, dwMode, 0, 0, &pStm);
expect(S_OK, hRes);
/* write less than header size */
li.QuadPart = 0;
hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
expect(S_OK, hRes);
memset(&header, 0, sizeof(header));
written = 0;
uli.QuadPart = sizeof(header)-1;
hRes = IStream_SetSize(pStm, uli);
expect(S_OK, hRes);
hRes = IStream_Write(pStm, &header, sizeof(header)-1, &written);
expect(S_OK, hRes);
written -= sizeof(header)-1;
expect(0, written);
li.QuadPart = 0;
hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
expect(S_OK, hRes);
hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, NULL);
expect(E_FAIL, hRes);
/* check stream position after header read failed */
li.QuadPart = 0;
uli.QuadPart = 1;
hRes = IStream_Seek(pStm, li, STREAM_SEEK_CUR, &uli);
expect(S_OK, hRes);
ok(uli.QuadPart == 0, "Expected to position reset\n");
/* write valid header for empty DPA */
header.dwSize = sizeof(header);
header.dwData2 = 1;
header.dwItems = 0;
written = 0;
li.QuadPart = 0;
hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
expect(S_OK, hRes);
uli.QuadPart = sizeof(header);
hRes = IStream_SetSize(pStm, uli);
expect(S_OK, hRes);
hRes = IStream_Write(pStm, &header, sizeof(header), &written);
expect(S_OK, hRes);
written -= sizeof(header);
expect(0, written);
li.QuadPart = 0;
hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
expect(S_OK, hRes);
dpa = NULL;
hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, NULL);
expect(S_OK, hRes);
DPA_Destroy(dpa);
/* try with altered dwData2 field */
header.dwSize = sizeof(header);
header.dwData2 = 2;
header.dwItems = 0;
li.QuadPart = 0;
hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
expect(S_OK, hRes);
hRes = IStream_Write(pStm, &header, sizeof(header), &written);
expect(S_OK, hRes);
written -= sizeof(header);
expect(0, written);
li.QuadPart = 0;
hRes = IStream_Seek(pStm, li, STREAM_SEEK_SET, NULL);
expect(S_OK, hRes);
hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, (void*)0xdeadbeef);
expect(E_FAIL, hRes);
ret = IStream_Release(pStm);
ok(!ret, "ret=%d\n", ret);
ret = IStorage_Release(pStg);
ok(!ret, "ret=%d\n", ret);
CoUninitialize();
}
static void test_DPA_SaveStream(void)
{
HDPA dpa;
static const WCHAR szStg[] = { 'S','t','g',0 };
IStorage* pStg = NULL;
IStream* pStm = NULL;
DWORD dwMode, dw;
HRESULT hRes;
ULONG ret;
INT i;
BOOL rc;
LARGE_INTEGER liZero;
if(!pDPA_SaveStream)
{
win_skip("DPA_SaveStream() not available. Skipping stream tests.\n");
return;
}
hRes = CoInitialize(NULL);
if (hRes != S_OK)
{
ok(0, "hResult: %d\n", hRes);
return;
}
dwMode = STGM_DIRECT|STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE;
hRes = StgCreateDocfile(NULL, dwMode|STGM_DELETEONRELEASE, 0, &pStg);
expect(S_OK, hRes);
hRes = IStorage_CreateStream(pStg, szStg, dwMode, 0, 0, &pStm);
expect(S_OK, hRes);
dpa = pDPA_Create(0);
/* simple parameter check */
hRes = pDPA_SaveStream(dpa, NULL, pStm, NULL);
ok(hRes == E_INVALIDARG ||
broken(hRes == S_OK) /* XP and below */, "Wrong result, %d\n", hRes);
if (0) {
/* crashes on XP */
hRes = pDPA_SaveStream(NULL, CB_Save, pStm, NULL);
expect(E_INVALIDARG, hRes);
hRes = pDPA_SaveStream(dpa, CB_Save, NULL, NULL);
expect(E_INVALIDARG, hRes);
}
/* saving/loading */
for (i = 0; i < 6; i++)
{
ret = pDPA_InsertPtr(dpa, i, (PVOID)(INT_PTR)(i+1));
ok(ret == i, "ret=%d\n", ret);
}
liZero.QuadPart = 0;
hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
expect(S_OK, hRes);
hRes = pDPA_SaveStream(dpa, CB_Save, pStm, (void*)0xdeadbeef);
expect(S_OK, hRes);
pDPA_Destroy(dpa);
liZero.QuadPart = 0;
hRes = IStream_Seek(pStm, liZero, STREAM_SEEK_SET, NULL);
expect(S_OK, hRes);
hRes = pDPA_LoadStream(&dpa, CB_Load, pStm, (void*)0xdeadbeef);
expect(S_OK, hRes);
rc = CheckDPA(dpa, 0x123456, &dw);
ok(rc, "dw=0x%x\n", dw);
pDPA_Destroy(dpa);
ret = IStream_Release(pStm);
ok(!ret, "ret=%d\n", ret);
ret = IStorage_Release(pStg);
ok(!ret, "ret=%d\n", ret);
CoUninitialize();
}
START_TEST(dpa)
@ -450,8 +746,16 @@ START_TEST(dpa)
hcomctl32 = GetModuleHandleA("comctl32.dll");
if(InitFunctionPtrs(hcomctl32))
test_dpa();
else
if(!InitFunctionPtrs(hcomctl32))
{
win_skip("Needed functions are not available\n");
return;
}
test_dpa();
test_DPA_Merge();
test_DPA_EnumCallback();
test_DPA_DestroyCallback();
test_DPA_LoadStream();
test_DPA_SaveStream();
}

View file

@ -24,6 +24,7 @@
#include <assert.h>
#include "wine/test.h"
#include "v6util.h"
#include "msg.h"
typedef struct tagEXPECTEDNOTIFY
@ -121,7 +122,6 @@ static const struct message deleteItem_getItemCount_seq[] = {
};
static const struct message orderArray_seq[] = {
{ HDM_GETITEMCOUNT, sent },
{ HDM_SETORDERARRAY, sent|wparam, 2 },
{ HDM_GETORDERARRAY, sent|wparam, 2 },
{ 0 }
@ -244,7 +244,7 @@ static LONG addItem(HWND hdex, int idx, LPSTR text)
hdItem.cxy = 100;
hdItem.pszText = text;
hdItem.cchTextMax = 0;
return (LONG)SendMessage(hdex, HDM_INSERTITEMA, (WPARAM)idx, (LPARAM)&hdItem);
return SendMessage(hdex, HDM_INSERTITEMA, idx, (LPARAM)&hdItem);
}
static LONG setItem(HWND hdex, int idx, LPSTR text, BOOL fCheckNotifies)
@ -259,7 +259,7 @@ static LONG setItem(HWND hdex, int idx, LPSTR text, BOOL fCheckNotifies)
expect_notify(HDN_ITEMCHANGINGA, FALSE, &hdexItem);
expect_notify(HDN_ITEMCHANGEDA, FALSE, &hdexItem);
}
ret = (LONG)SendMessage(hdex, HDM_SETITEMA, (WPARAM)idx, (LPARAM)&hdexItem);
ret = SendMessage(hdex, HDM_SETITEMA, idx, (LPARAM)&hdexItem);
if (fCheckNotifies)
ok(notifies_received(), "setItem(): not all expected notifies were received\n");
return ret;
@ -279,19 +279,19 @@ static LONG setItemUnicodeNotify(HWND hdex, int idx, LPSTR text, LPWSTR wText)
expect_notify(HDN_ITEMCHANGINGW, TRUE, (HDITEMA*)&hdexNotify);
expect_notify(HDN_ITEMCHANGEDW, TRUE, (HDITEMA*)&hdexNotify);
ret = (LONG)SendMessage(hdex, HDM_SETITEMA, (WPARAM)idx, (LPARAM)&hdexItem);
ret = SendMessage(hdex, HDM_SETITEMA, idx, (LPARAM)&hdexItem);
ok(notifies_received(), "setItemUnicodeNotify(): not all expected notifies were received\n");
return ret;
}
static LONG delItem(HWND hdex, int idx)
{
return (LONG)SendMessage(hdex, HDM_DELETEITEM, (WPARAM)idx, 0);
return SendMessage(hdex, HDM_DELETEITEM, idx, 0);
}
static LONG getItemCount(HWND hdex)
{
return (LONG)SendMessage(hdex, HDM_GETITEMCOUNT, 0, 0);
return SendMessage(hdex, HDM_GETITEMCOUNT, 0, 0);
}
static LONG getItem(HWND hdex, int idx, LPSTR textBuffer)
@ -300,7 +300,7 @@ static LONG getItem(HWND hdex, int idx, LPSTR textBuffer)
hdItem.mask = HDI_TEXT;
hdItem.pszText = textBuffer;
hdItem.cchTextMax = MAX_CHARS;
return (LONG)SendMessage(hdex, HDM_GETITEMA, (WPARAM)idx, (LPARAM)&hdItem);
return SendMessage(hdex, HDM_GETITEMA, idx, (LPARAM)&hdItem);
}
static void addReadDelItem(HWND hdex, HDITEMA *phdiCreate, int maskRead, HDITEMA *phdiRead)
@ -396,14 +396,9 @@ static WCHAR pszUniTestW[] = {'T','S','T',0};
ok(res == i, "Got Item Count as %d\n", res);\
}
struct subclass_info
{
WNDPROC oldproc;
};
static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
static LONG defwndproc_counter = 0;
LRESULT ret;
struct message msg;
@ -417,7 +412,7 @@ static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wPara
add_message(sequences, HEADER_SEQ_INDEX, &msg);
defwndproc_counter++;
ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
defwndproc_counter--;
return ret;
@ -487,7 +482,7 @@ static HWND create_custom_parent_window(void)
static HWND create_custom_header_control(HWND hParent, BOOL preloadHeaderItems)
{
struct subclass_info *info;
WNDPROC oldproc;
HWND childHandle;
HDLAYOUT hlayout;
RECT rectwin;
@ -505,9 +500,6 @@ static HWND create_custom_header_control(HWND hParent, BOOL preloadHeaderItems)
flush_sequences(sequences, NUM_MSG_SEQUENCES);
info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
if (!info)
return NULL;
childHandle = CreateWindowEx(0, WC_HEADER, NULL,
WS_CHILD|WS_BORDER|WS_VISIBLE|HDS_BUTTONS|HDS_HORZ,
@ -534,9 +526,9 @@ static HWND create_custom_header_control(HWND hParent, BOOL preloadHeaderItems)
SetWindowPos(childHandle, winpos.hwndInsertAfter, winpos.x, winpos.y,
winpos.cx, winpos.cy, 0);
info->oldproc = (WNDPROC)SetWindowLongPtrA(childHandle, GWLP_WNDPROC,
(LONG_PTR)header_subclass_proc);
SetWindowLongPtrA(childHandle, GWLP_USERDATA, (LONG_PTR)info);
oldproc = (WNDPROC)SetWindowLongPtrA(childHandle, GWLP_WNDPROC,
(LONG_PTR)header_subclass_proc);
SetWindowLongPtrA(childHandle, GWLP_USERDATA, (LONG_PTR)oldproc);
return childHandle;
}
@ -756,10 +748,10 @@ static void test_header_control (void)
TEST_GET_ITEM(i, 4);
TEST_GET_ITEMCOUNT(6);
}
SendMessageA(hWndHeader, HDM_SETUNICODEFORMAT, (WPARAM)TRUE, 0);
SendMessageA(hWndHeader, HDM_SETUNICODEFORMAT, TRUE, 0);
setItemUnicodeNotify(hWndHeader, 3, pszUniTestA, pszUniTestW);
SendMessageA(hWndHeader, WM_NOTIFYFORMAT, (WPARAM)hHeaderParentWnd, (LPARAM)NF_REQUERY);
SendMessageA(hWndHeader, WM_NOTIFYFORMAT, (WPARAM)hHeaderParentWnd, NF_REQUERY);
setItem(hWndHeader, 3, str_items[4], TRUE);
dont_expect_notify(HDN_GETDISPINFOA);
@ -820,10 +812,8 @@ static void test_hdm_getitemrect(HWND hParent)
expect(80, rect.left);
expect(0, rect.top);
expect(160, rect.right);
todo_wine
{
expect(g_customheight, rect.bottom);
}
expect(g_customheight, rect.bottom);
retVal = SendMessage(hChild, HDM_GETITEMRECT, 0, (LPARAM) &rect);
ok(retVal == TRUE, "Getting item rect should TRUE, got %d\n", retVal);
@ -832,10 +822,8 @@ static void test_hdm_getitemrect(HWND hParent)
expect(0, rect.top);
expect(80, rect.right);
todo_wine
{
expect(g_customheight, rect.bottom);
}
expect(g_customheight, rect.bottom);
retVal = SendMessage(hChild, HDM_GETITEMRECT, 10, (LPARAM) &rect);
ok(retVal == 0, "Getting rect of nonexistent item should return 0, got %d\n", retVal);
@ -907,30 +895,25 @@ static void test_hdm_hittest(HWND hParent)
flush_sequences(sequences, NUM_MSG_SEQUENCES);
retVal = SendMessage(hChild, HDM_HITTEST, 0, (LPARAM) &hdHitTestInfo);
todo_wine
{
expect(0, retVal);
expect(0, hdHitTestInfo.iItem);
}
expect(0, retVal);
expect(0, hdHitTestInfo.iItem);
expect(HHT_ONDIVIDER, hdHitTestInfo.flags);
pt.x = secondItemRightBoundary - 1;
pt.y = bottomBoundary - 1;
hdHitTestInfo.pt = pt;
retVal = SendMessage(hChild, HDM_HITTEST, 1, (LPARAM) &hdHitTestInfo);
todo_wine
{
expect(1, retVal);
}
expect(1, retVal);
expect(1, hdHitTestInfo.iItem);
expect(HHT_ONDIVIDER, hdHitTestInfo.flags);
pt.x = secondItemRightBoundary;
pt.y = bottomBoundary + 1;
hdHitTestInfo.pt = pt;
todo_wine
{
retVal = SendMessage(hChild, HDM_HITTEST, 0, (LPARAM) &hdHitTestInfo);
expect(-1, retVal);
}
retVal = SendMessage(hChild, HDM_HITTEST, 0, (LPARAM) &hdHitTestInfo);
expect(-1, retVal);
expect(-1, hdHitTestInfo.iItem);
expect(HHT_BELOW, hdHitTestInfo.flags);
ok_sequence(sequences, HEADER_SEQ_INDEX, hittest_seq, "hittest sequence testing", FALSE);
@ -951,11 +934,9 @@ static void test_hdm_sethotdivider(HWND hParent)
"adder header control to parent", FALSE);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
todo_wine
{
retVal = SendMessage(hChild, HDM_SETHOTDIVIDER, TRUE, 0X00050005);
expect(0, retVal);
}
retVal = SendMessage(hChild, HDM_SETHOTDIVIDER, TRUE, MAKELPARAM(5, 5));
expect(0, retVal);
retVal = SendMessage(hChild, HDM_SETHOTDIVIDER, FALSE, 100);
expect(100, retVal);
retVal = SendMessage(hChild, HDM_SETHOTDIVIDER, FALSE, 1);
@ -973,7 +954,7 @@ static void test_hdm_sethotdivider(HWND hParent)
static void test_hdm_imageMessages(HWND hParent)
{
HIMAGELIST hImageList = ImageList_Create (4, 4, 0, 1, 0);
HIMAGELIST hImageListRetVal;
HIMAGELIST hIml;
HWND hChild;
flush_sequences(sequences, NUM_MSG_SEQUENCES);
@ -983,14 +964,15 @@ static void test_hdm_imageMessages(HWND hParent)
flush_sequences(sequences, NUM_MSG_SEQUENCES);
hImageListRetVal = (HIMAGELIST) SendMessage(hChild, HDM_SETIMAGELIST, 0, (LPARAM) hImageList);
ok(hImageListRetVal == NULL, "Expected NULL, got %p\n", hImageListRetVal);
hIml = (HIMAGELIST) SendMessage(hChild, HDM_SETIMAGELIST, 0, (LPARAM) hImageList);
ok(hIml == NULL, "Expected NULL, got %p\n", hIml);
hImageListRetVal = (HIMAGELIST) SendMessage(hChild, HDM_GETIMAGELIST, 0, 0);
ok(hImageListRetVal != NULL, "Expected non-NULL handle, got %p\n", hImageListRetVal);
hIml = (HIMAGELIST) SendMessage(hChild, HDM_GETIMAGELIST, 0, 0);
ok(hIml != NULL, "Expected non-NULL handle, got %p\n", hIml);
hImageListRetVal = (HIMAGELIST) SendMessage(hChild, HDM_CREATEDRAGIMAGE, 0, 0);
ok(hImageListRetVal != NULL, "Expected non-NULL handle, got %p\n", hImageListRetVal);
hIml = (HIMAGELIST) SendMessage(hChild, HDM_CREATEDRAGIMAGE, 0, 0);
ok(hIml != NULL, "Expected non-NULL handle, got %p\n", hIml);
ImageList_Destroy(hIml);
ok_sequence(sequences, HEADER_SEQ_INDEX, imageMessages_seq, "imageMessages sequence testing", FALSE);
@ -1025,9 +1007,16 @@ static void test_hdm_filterMessages(HWND hParent)
todo_wine
{
retVal = SendMessage(hChild, HDM_CLEARFILTER, 0, 1);
expect(1, retVal);
if (retVal == 0)
win_skip("HDM_CLEARFILTER needs 5.80\n");
else
expect(1, retVal);
retVal = SendMessage(hChild, HDM_EDITFILTER, 1, 0);
expect(1, retVal);
if (retVal == 0)
win_skip("HDM_EDITFILTER needs 5.80\n");
else
expect(1, retVal);
}
if (winetest_interactive)
ok_sequence(sequences, HEADER_SEQ_INDEX, filterMessages_seq_interactive,
@ -1076,7 +1065,10 @@ static void test_hdm_bitmapmarginMessages(HWND hParent)
flush_sequences(sequences, NUM_MSG_SEQUENCES);
retVal = SendMessage(hChild, HDM_GETBITMAPMARGIN, 0, 0);
expect(6, retVal);
if (retVal == 0)
win_skip("HDM_GETBITMAPMARGIN needs 5.80\n");
else
expect(6, retVal);
ok_sequence(sequences, HEADER_SEQ_INDEX, bitmapmarginMessages_seq,
"bitmapmarginMessages sequence testing", FALSE);
@ -1085,7 +1077,6 @@ static void test_hdm_bitmapmarginMessages(HWND hParent)
static void test_hdm_index_messages(HWND hParent)
{
HWND hChild;
int retVal;
int loopcnt;
@ -1098,6 +1089,7 @@ static void test_hdm_index_messages(HWND hParent)
static char thirdHeaderItem[] = "Type";
static char fourthHeaderItem[] = "Date Modified";
static char *items[] = {firstHeaderItem, secondHeaderItem, thirdHeaderItem, fourthHeaderItem};
RECT rect;
HDITEM hdItem;
hdItem.mask = HDI_TEXT | HDI_WIDTH | HDI_FORMAT;
hdItem.fmt = HDF_LEFT;
@ -1125,17 +1117,17 @@ static void test_hdm_index_messages(HWND hParent)
retVal = SendMessage(hChild, HDM_DELETEITEM, 3, (LPARAM) &hdItem);
ok(retVal == TRUE, "Deleting item 3 should return TRUE, got %d\n", retVal);
retVal = SendMessage(hChild, HDM_GETITEMCOUNT, 0, (LPARAM) &hdItem);
retVal = SendMessage(hChild, HDM_GETITEMCOUNT, 0, 0);
ok(retVal == 3, "Getting item count should return 3, got %d\n", retVal);
retVal = SendMessage(hChild, HDM_DELETEITEM, 3, (LPARAM) &hdItem);
ok(retVal == FALSE, "Deleting already-deleted item should return FALSE, got %d\n", retVal);
retVal = SendMessage(hChild, HDM_GETITEMCOUNT, 0, (LPARAM) &hdItem);
retVal = SendMessage(hChild, HDM_GETITEMCOUNT, 0, 0);
ok(retVal == 3, "Getting item count should return 3, got %d\n", retVal);
retVal = SendMessage(hChild, HDM_DELETEITEM, 2, (LPARAM) &hdItem);
ok(retVal == TRUE, "Deleting item 2 should return TRUE, got %d\n", retVal);
retVal = SendMessage(hChild, HDM_GETITEMCOUNT, 0, (LPARAM) &hdItem);
retVal = SendMessage(hChild, HDM_GETITEMCOUNT, 0, 0);
ok(retVal == 2, "Getting item count should return 2, got %d\n", retVal);
ok_sequence(sequences, HEADER_SEQ_INDEX, deleteItem_getItemCount_seq,
@ -1156,9 +1148,19 @@ static void test_hdm_index_messages(HWND hParent)
expect(0, strcmpResult);
expect(80, hdItem.cxy);
iSize = SendMessage(hChild, HDM_GETITEMCOUNT, 0, 0);
/* item should be updated just after accepting new array */
ShowWindow(hChild, SW_HIDE);
retVal = SendMessage(hChild, HDM_SETORDERARRAY, iSize, (LPARAM) lpiarray);
expect(TRUE, retVal);
rect.left = 0;
retVal = SendMessage(hChild, HDM_GETITEMRECT, 0, (LPARAM) &rect);
expect(TRUE, retVal);
ok(rect.left != 0, "Expected updated rectangle\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
iSize = SendMessage(hChild, HDM_GETITEMCOUNT, 0, (LPARAM) &hdItem);
retVal = SendMessage(hChild, HDM_SETORDERARRAY, iSize, (LPARAM) lpiarray);
ok(retVal == TRUE, "Setting header items order should return TRUE, got %d\n", retVal);
@ -1187,12 +1189,156 @@ static void test_hdm_index_messages(HWND hParent)
DestroyWindow(hChild);
}
static void test_hdf_fixedwidth(HWND hParent)
{
HWND hChild;
HDITEM hdItem;
DWORD ret;
RECT rect;
HDHITTESTINFO ht;
hChild = create_custom_header_control(hParent, FALSE);
hdItem.mask = HDI_WIDTH | HDI_FORMAT;
hdItem.fmt = HDF_FIXEDWIDTH;
hdItem.cxy = 80;
ret = SendMessage(hChild, HDM_INSERTITEM, 0, (LPARAM)&hdItem);
expect(0, ret);
/* try to change width */
rect.right = rect.bottom = 0;
SendMessage(hChild, HDM_GETITEMRECT, 0, (LPARAM)&rect);
ok(rect.right != 0, "Expected not zero width\n");
ok(rect.bottom != 0, "Expected not zero height\n");
SendMessage(hChild, WM_LBUTTONDOWN, 0, MAKELPARAM(rect.right, rect.bottom / 2));
SendMessage(hChild, WM_MOUSEMOVE, 0, MAKELPARAM(rect.right + 20, rect.bottom / 2));
SendMessage(hChild, WM_LBUTTONUP, 0, MAKELPARAM(rect.right + 20, rect.bottom / 2));
SendMessage(hChild, HDM_GETITEMRECT, 0, (LPARAM)&rect);
if (hdItem.cxy != rect.right)
{
win_skip("HDF_FIXEDWIDTH format not supported\n");
DestroyWindow(hChild);
return;
}
/* try to adjust with message */
hdItem.mask = HDI_WIDTH;
hdItem.cxy = 90;
ret = SendMessage(hChild, HDM_SETITEM, 0, (LPARAM)&hdItem);
expect(TRUE, ret);
rect.right = 0;
SendMessage(hChild, HDM_GETITEMRECT, 0, (LPARAM)&rect);
expect(90, rect.right);
/* hittesting doesn't report ondivider flag for HDF_FIXEDWIDTH */
ht.pt.x = rect.right - 1;
ht.pt.y = rect.bottom / 2;
SendMessage(hChild, HDM_HITTEST, 0, (LPARAM)&ht);
expect(HHT_ONHEADER, ht.flags);
/* try to adjust with message */
hdItem.mask = HDI_FORMAT;
hdItem.fmt = 0;
ret = SendMessage(hChild, HDM_SETITEM, 0, (LPARAM)&hdItem);
expect(TRUE, ret);
ht.pt.x = 90;
ht.pt.y = rect.bottom / 2;
SendMessage(hChild, HDM_HITTEST, 0, (LPARAM)&ht);
expect(HHT_ONDIVIDER, ht.flags);
DestroyWindow(hChild);
}
static void test_hds_nosizing(HWND hParent)
{
HWND hChild;
HDITEM hdItem;
DWORD ret;
RECT rect;
HDHITTESTINFO ht;
hChild = create_custom_header_control(hParent, FALSE);
memset(&hdItem, 0, sizeof(hdItem));
hdItem.mask = HDI_WIDTH;
hdItem.cxy = 80;
ret = SendMessage(hChild, HDM_INSERTITEM, 0, (LPARAM)&hdItem);
expect(0, ret);
/* HDS_NOSIZING only blocks hittesting */
ret = GetWindowLong(hChild, GWL_STYLE);
SetWindowLong(hChild, GWL_STYLE, ret | HDS_NOSIZING);
/* try to change width with mouse gestures */
rect.right = rect.bottom = 0;
SendMessage(hChild, HDM_GETITEMRECT, 0, (LPARAM)&rect);
ok(rect.right != 0, "Expected not zero width\n");
ok(rect.bottom != 0, "Expected not zero height\n");
SendMessage(hChild, WM_LBUTTONDOWN, 0, MAKELPARAM(rect.right, rect.bottom / 2));
SendMessage(hChild, WM_MOUSEMOVE, 0, MAKELPARAM(rect.right + 20, rect.bottom / 2));
SendMessage(hChild, WM_LBUTTONUP, 0, MAKELPARAM(rect.right + 20, rect.bottom / 2));
SendMessage(hChild, HDM_GETITEMRECT, 0, (LPARAM)&rect);
if (hdItem.cxy != rect.right)
{
win_skip("HDS_NOSIZING style not supported\n");
DestroyWindow(hChild);
return;
}
/* this style doesn't set HDF_FIXEDWIDTH for items */
hdItem.mask = HDI_FORMAT;
ret = SendMessage(hChild, HDM_GETITEM, 0, (LPARAM)&hdItem);
expect(TRUE, ret);
ok(!(hdItem.fmt & HDF_FIXEDWIDTH), "Unexpected HDF_FIXEDWIDTH\n");
/* try to adjust with message */
hdItem.mask = HDI_WIDTH;
hdItem.cxy = 90;
ret = SendMessage(hChild, HDM_SETITEM, 0, (LPARAM)&hdItem);
expect(TRUE, ret);
rect.right = 0;
SendMessage(hChild, HDM_GETITEMRECT, 0, (LPARAM)&rect);
expect(90, rect.right);
/* hittesting doesn't report ondivider flags for HDS_NOSIZING */
ht.pt.x = rect.right - 1;
ht.pt.y = rect.bottom / 2;
SendMessage(hChild, HDM_HITTEST, 0, (LPARAM)&ht);
expect(HHT_ONHEADER, ht.flags);
/* try to adjust with message */
ret = GetWindowLong(hChild, GWL_STYLE);
SetWindowLong(hChild, GWL_STYLE, ret & ~HDS_NOSIZING);
ht.pt.x = 90;
ht.pt.y = rect.bottom / 2;
SendMessage(hChild, HDM_HITTEST, 0, (LPARAM)&ht);
expect(HHT_ONDIVIDER, ht.flags);
DestroyWindow(hChild);
}
#define TEST_NMCUSTOMDRAW(draw_stage, item_spec, lparam, _left, _top, _right, _bottom) \
ok(nm->dwDrawStage == draw_stage, "Invalid dwDrawStage %d vs %d\n", draw_stage, nm->dwDrawStage); \
if (item_spec != -1) \
ok(nm->dwItemSpec == item_spec, "Invalid dwItemSpec %d vs %ld\n", item_spec, nm->dwItemSpec); \
ok(nm->lItemlParam == lparam, "Invalid lItemlParam %d vs %ld\n", lparam, nm->lItemlParam); \
ok(nm->rc.top == _top && nm->rc.bottom == _bottom && nm->rc.left == _left && nm->rc.right == _right, \
ok((nm->rc.top == _top && nm->rc.bottom == _bottom && nm->rc.left == _left && nm->rc.right == _right) || \
broken(draw_stage != CDDS_ITEMPREPAINT), /* comctl32 < 5.80 */ \
"Invalid rect (%d,%d) (%d,%d) vs (%d,%d) (%d,%d)\n", _left, _top, _right, _bottom, \
nm->rc.left, nm->rc.top, nm->rc.right, nm->rc.bottom);
@ -1545,15 +1691,139 @@ static int init(void)
return 1;
}
/* maximum 8 items allowed */
static void check_orderarray(HWND hwnd, DWORD start, DWORD set, DWORD expected,
int todo, int line)
{
int count, i;
INT order[8];
DWORD ret, array = 0;
count = SendMessage(hwnd, HDM_GETITEMCOUNT, 0, 0);
/* initial order */
for(i = 1; i<=count; i++)
order[i-1] = start>>(4*(count-i)) & 0xf;
ret = SendMessage(hwnd, HDM_SETORDERARRAY, count, (LPARAM)order);
ok_(__FILE__, line)(ret, "Expected HDM_SETORDERARAY to succeed, got %d\n", ret);
/* new order */
for(i = 1; i<=count; i++)
order[i-1] = set>>(4*(count-i)) & 0xf;
ret = SendMessage(hwnd, HDM_SETORDERARRAY, count, (LPARAM)order);
ok_(__FILE__, line)(ret, "Expected HDM_SETORDERARAY to succeed, got %d\n", ret);
/* check actual order */
ret = SendMessage(hwnd, HDM_GETORDERARRAY, count, (LPARAM)order);
ok_(__FILE__, line)(ret, "Expected HDM_GETORDERARAY to succeed, got %d\n", ret);
for(i = 1; i<=count; i++)
array |= order[i-1]<<(4*(count-i));
if (todo) {
todo_wine
ok_(__FILE__, line)(array == expected, "Expected %x, got %x\n", expected, array);
}
else
ok_(__FILE__, line)(array == expected, "Expected %x, got %x\n", expected, array);
}
static void test_hdm_orderarray(void)
{
HWND hwnd;
INT order[5];
DWORD ret;
hwnd = create_header_control();
/* three items */
addItem(hwnd, 0, NULL);
addItem(hwnd, 1, NULL);
addItem(hwnd, 2, NULL);
ret = SendMessage(hwnd, HDM_GETORDERARRAY, 3, (LPARAM)order);
if (!ret)
{
win_skip("HDM_GETORDERARRAY not implemented.\n");
DestroyWindow(hwnd);
return;
}
expect(0, order[0]);
expect(1, order[1]);
expect(2, order[2]);
if (0)
{
/* null pointer, crashes native */
ret = SendMessage(hwnd, HDM_SETORDERARRAY, 3, 0);
expect(FALSE, ret);
}
/* count out of limits */
ret = SendMessage(hwnd, HDM_SETORDERARRAY, 5, (LPARAM)order);
expect(FALSE, ret);
/* count out of limits */
ret = SendMessage(hwnd, HDM_SETORDERARRAY, 2, (LPARAM)order);
expect(FALSE, ret);
/* try with out of range item index */
/* (0,1,2)->(1,0,3) => (1,0,2) */
check_orderarray(hwnd, 0x120, 0x103, 0x102, FALSE, __LINE__);
/* (1,0,2)->(3,0,1) => (0,2,1) */
check_orderarray(hwnd, 0x102, 0x301, 0x021, TRUE, __LINE__);
/* (0,2,1)->(2,3,1) => (2,0,1) */
check_orderarray(hwnd, 0x021, 0x231, 0x201, FALSE, __LINE__);
/* (0,1,2)->(0,2,2) => (0,1,2) */
check_orderarray(hwnd, 0x012, 0x022, 0x012, FALSE, __LINE__);
addItem(hwnd, 3, NULL);
/* (0,1,2,3)->(0,1,2,2) => (0,1,3,2) */
check_orderarray(hwnd, 0x0123, 0x0122, 0x0132, FALSE, __LINE__);
/* (0,1,2,3)->(0,1,3,3) => (0,1,2,3) */
check_orderarray(hwnd, 0x0123, 0x0133, 0x0123, FALSE, __LINE__);
/* (0,1,2,3)->(0,4,2,3) => (0,1,2,3) */
check_orderarray(hwnd, 0x0123, 0x0423, 0x0123, FALSE, __LINE__);
/* (0,1,2,3)->(4,0,1,2) => (0,1,3,2) */
check_orderarray(hwnd, 0x0123, 0x4012, 0x0132, TRUE, __LINE__);
/* (0,1,3,2)->(4,0,1,4) => (0,3,1,2) */
check_orderarray(hwnd, 0x0132, 0x4014, 0x0312, TRUE, __LINE__);
/* (0,1,2,3)->(4,1,0,2) => (1,0,3,2) */
check_orderarray(hwnd, 0x0123, 0x4102, 0x1032, TRUE, __LINE__);
/* (0,1,2,3)->(0,1,4,2) => (0,1,2,3) */
check_orderarray(hwnd, 0x0123, 0x0142, 0x0132, FALSE, __LINE__);
/* (0,1,2,3)->(4,4,4,4) => (0,1,2,3) */
check_orderarray(hwnd, 0x0123, 0x4444, 0x0123, FALSE, __LINE__);
/* (0,1,2,3)->(4,4,1,2) => (0,1,3,2) */
check_orderarray(hwnd, 0x0123, 0x4412, 0x0132, TRUE, __LINE__);
/* (0,1,2,3)->(4,4,4,1) => (0,2,3,1) */
check_orderarray(hwnd, 0x0123, 0x4441, 0x0231, TRUE, __LINE__);
/* (0,1,2,3)->(1,4,4,4) => (1,0,2,3) */
check_orderarray(hwnd, 0x0123, 0x1444, 0x1023, FALSE, __LINE__);
/* (0,1,2,3)->(4,2,4,1) => (0,2,3,1) */
check_orderarray(hwnd, 0x0123, 0x4241, 0x0231, FALSE, __LINE__);
/* (0,1,2,3)->(4,2,0,1) => (2,0,3,1) */
check_orderarray(hwnd, 0x0123, 0x4201, 0x2031, TRUE, __LINE__);
/* (3,2,1,0)->(4,2,0,1) => (3,2,0,1) */
check_orderarray(hwnd, 0x3210, 0x4201, 0x3201, FALSE, __LINE__);
DestroyWindow(hwnd);
}
START_TEST(header)
{
HWND parent_hwnd;
ULONG_PTR ctx_cookie;
HANDLE hCtx;
HWND hwnd;
if (!init())
return;
test_header_control();
test_header_order();
test_hdm_orderarray();
test_customdraw();
DestroyWindow(hHeaderParentWnd);
@ -1573,6 +1843,33 @@ START_TEST(header)
test_hdm_unicodeformatMessages(parent_hwnd);
test_hdm_bitmapmarginMessages(parent_hwnd);
DestroyWindow(parent_hwnd);
if (!load_v6_module(&ctx_cookie, &hCtx))
{
DestroyWindow(parent_hwnd);
return;
}
/* this is a XP SP3 failure workaround */
hwnd = CreateWindowExA(0, WC_HEADER, NULL,
WS_CHILD|WS_BORDER|WS_VISIBLE|HDS_BUTTONS|HDS_HORZ,
0, 0, 100, 100,
parent_hwnd, NULL, GetModuleHandleA(NULL), NULL);
if (!IsWindow(hwnd))
{
win_skip("FIXME: failed to create Header window.\n");
unload_v6_module(ctx_cookie, hCtx);
DestroyWindow(parent_hwnd);
return;
}
else
DestroyWindow(hwnd);
/* comctl32 version 6 tests start here */
test_hdf_fixedwidth(parent_hwnd);
test_hds_nosizing(parent_hwnd);
unload_v6_module(ctx_cookie, hCtx);
DestroyWindow(parent_hwnd);
}

View file

@ -4,6 +4,7 @@
* Copyright 2004 Michael Stefaniuc
* Copyright 2002 Mike McCormack for CodeWeavers
* Copyright 2007 Dmitry Timoshkov
* Copyright 2009 Owen Rudge for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -33,8 +34,12 @@
#include "winuser.h"
#include "objbase.h"
#include "commctrl.h" /* must be included after objbase.h to get ImageList_Write */
#include "initguid.h"
#include "commoncontrols.h"
#include "shellapi.h"
#include "wine/test.h"
#include "v6util.h"
#undef VISIBLE
@ -65,10 +70,14 @@ typedef struct _ILHEAD
} ILHEAD;
#include "poppack.h"
static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
static HRESULT (WINAPI *pImageList_CoCreateInstance)(REFCLSID,const IUnknown *,
REFIID,void **);
static HRESULT (WINAPI *pHIMAGELIST_QueryInterface)(HIMAGELIST,REFIID,void **);
static HDC desktopDC;
static HINSTANCE hinst;
/* These macros build cursor/bitmap data in 4x4 pixel blocks */
@ -327,7 +336,7 @@ static BOOL DoTest1(void)
HICON hicon3 ;
/* create an imagelist to play with */
himl = ImageList_Create(84,84,0x10,0,3);
himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
ok(himl!=0,"failed to create imagelist\n");
/* load the icons to add to the image list */
@ -393,7 +402,7 @@ static BOOL DoTest2(void)
HICON hicon3 ;
/* create an imagelist to play with */
himl = ImageList_Create(84,84,0x10,0,3);
himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
ok(himl!=0,"failed to create imagelist\n");
/* load the icons to add to the image list */
@ -442,7 +451,7 @@ static BOOL DoTest3(void)
ok(hdc!=NULL, "couldn't get DC\n");
/* create an imagelist to play with */
himl = ImageList_Create(48,48,0x10,0,3);
himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
ok(himl!=0,"failed to create imagelist\n");
/* load the icons to add to the image list */
@ -824,7 +833,7 @@ static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max)
{
ILHEAD *ilh = (ILHEAD *)ilh_data;
const ILHEAD *ilh = (const 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);
@ -981,13 +990,639 @@ static void test_imagelist_storage(void)
iml_clear_stream_data();
}
static void test_shell_imagelist(void)
{
BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
IImageList *iml = NULL;
HMODULE hShell32;
HRESULT hr;
int out = 0;
RECT rect;
int cx, cy;
/* Try to load function from shell32 */
hShell32 = LoadLibrary("shell32.dll");
pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
if (!pSHGetImageList)
{
win_skip("SHGetImageList not available, skipping test\n");
return;
}
/* Get system image list */
hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
if (hr != S_OK)
return;
IImageList_GetImageCount(iml, &out);
ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
/* Fetch the small icon size */
cx = GetSystemMetrics(SM_CXSMICON);
cy = GetSystemMetrics(SM_CYSMICON);
/* Check icon size matches */
IImageList_GetImageRect(iml, 0, &rect);
ok(((rect.right == cx) && (rect.bottom == cy)),
"IImageList_GetImageRect returned r:%d,b:%d\n",
rect.right, rect.bottom);
IImageList_Release(iml);
FreeLibrary(hShell32);
}
static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
{
HBITMAP hBitmap;
UINT32 *buffer = NULL;
BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
0, 0, 0, 0, 0}};
hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
if(!hBitmap || !buffer)
{
DeleteObject(hBitmap);
return NULL;
}
buffer[0] = pixel1;
buffer[1] = pixel2;
return hBitmap;
}
static BOOL colour_match(UINT32 x, UINT32 y)
{
const INT32 tolerance = 8;
const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
return (dr <= tolerance && dg <= tolerance && db <= tolerance);
}
static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
UINT32 expected, int line)
{
bits[0] = 0x00FFFFFF;
pImageList_DrawIndirect(ildp);
ok(colour_match(bits[0], expected),
"ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
bits[0] & 0x00FFFFFF, expected, line);
}
static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
UINT fStyle, UINT32 expected, int line)
{
IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
check_ImageList_DrawIndirect(&ildp, bits, expected, line);
}
static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
DWORD dwRop, UINT32 expected, int line)
{
IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
check_ImageList_DrawIndirect(&ildp, bits, expected, line);
}
static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
UINT fState, DWORD Frame, UINT32 expected, int line)
{
IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
check_ImageList_DrawIndirect(&ildp, bits, expected, line);
}
static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
UINT32 broken_expected, int line)
{
IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
bits[0] = 0x00FFFFFF;
pImageList_DrawIndirect(&ildp);
ok(colour_match(bits[0], expected) ||
broken(colour_match(bits[0], broken_expected)),
"ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
bits[0] & 0x00FFFFFF, expected, line);
}
static void test_ImageList_DrawIndirect(void)
{
HIMAGELIST himl = NULL;
int ret;
HDC hdcDst = NULL;
HBITMAP hbmOld = NULL, hbmDst = NULL;
HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
UINT32 *bits = 0;
UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
0, 0, 0, 0, 0}};
hdcDst = CreateCompatibleDC(0);
ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
if (!hdcDst)
return;
hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
ok(hbmMask != 0, "CreateBitmap failed\n");
if(!hbmMask) goto cleanup;
hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
ok(hbmInverseMask != 0, "CreateBitmap failed\n");
if(!hbmInverseMask) goto cleanup;
himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
ok(himl != 0, "ImageList_Create failed\n");
if(!himl) goto cleanup;
/* Add a no-alpha image */
hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
if(!hbmImage) goto cleanup;
iImage = pImageList_Add(himl, hbmImage, hbmMask);
ok(iImage != -1, "ImageList_Add failed\n");
if(iImage == -1) goto cleanup;
/* Add an alpha image */
hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
if(!hbmAlphaImage) goto cleanup;
iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
ok(iAlphaImage != -1, "ImageList_Add failed\n");
if(iAlphaImage == -1) goto cleanup;
/* Add a transparent alpha image */
hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
if(!hbmTransparentImage) goto cleanup;
iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
ok(iTransparentImage != -1, "ImageList_Add failed\n");
if(iTransparentImage == -1) goto cleanup;
/* 32-bit Tests */
bitmapInfo.bmiHeader.biBitCount = 32;
hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
if (!hbmDst || !bits)
goto cleanup;
hbmOld = SelectObject(hdcDst, hbmDst);
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, 0x00B4BDC4, __LINE__);
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
todo_wine
{
check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x009DA8B1, __LINE__);
check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, 0x008C99A3, __LINE__);
}
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
/* ILD_ROP is ignored when the image has an alpha channel */
check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
cleanup:
if(hbmOld)
SelectObject(hdcDst, hbmOld);
if(hbmDst)
DeleteObject(hbmDst);
if(hdcDst)
DeleteDC(hdcDst);
if(hbmMask)
DeleteObject(hbmMask);
if(hbmInverseMask)
DeleteObject(hbmInverseMask);
if(hbmImage)
DeleteObject(hbmImage);
if(hbmAlphaImage)
DeleteObject(hbmAlphaImage);
if(hbmTransparentImage)
DeleteObject(hbmTransparentImage);
if(himl)
{
ret = ImageList_Destroy(himl);
ok(ret, "ImageList_Destroy failed\n");
}
}
static void test_iimagelist(void)
{
IImageList *imgl;
HIMAGELIST himl;
HRESULT hr;
ULONG ret;
if (!pHIMAGELIST_QueryInterface)
{
win_skip("XP imagelist functions not available\n");
return;
}
/* test reference counting on destruction */
imgl = (IImageList*)createImageList(32, 32);
ret = IUnknown_AddRef(imgl);
ok(ret == 2, "Expected 2, got %d\n", ret);
ret = ImageList_Destroy((HIMAGELIST)imgl);
ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
ret = ImageList_Destroy((HIMAGELIST)imgl);
ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
ret = ImageList_Destroy((HIMAGELIST)imgl);
ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
imgl = (IImageList*)createImageList(32, 32);
ret = IUnknown_AddRef(imgl);
ok(ret == 2, "Expected 2, got %d\n", ret);
ret = ImageList_Destroy((HIMAGELIST)imgl);
ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
ret = IImageList_Release(imgl);
ok(ret == 0, "Expected 0, got %d\n", ret);
ret = ImageList_Destroy((HIMAGELIST)imgl);
ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
if (!pImageList_CoCreateInstance)
{
win_skip("Vista imagelist functions not available\n");
return;
}
hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
if (hr == S_OK)
IImageList_Release(imgl);
himl = createImageList(32, 32);
if (!himl)
return;
hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
if (hr == S_OK)
IImageList_Release(imgl);
ImageList_Destroy(himl);
}
static void testHotspot_v6(void)
{
struct hotspot {
int dx;
int dy;
};
#define SIZEX1 47
#define SIZEY1 31
#define SIZEX2 11
#define SIZEY2 17
#define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
static const struct hotspot hotspots[HOTSPOTS_MAX] = {
{ 10, 7 },
{ SIZEX1, SIZEY1 },
{ -9, -8 },
{ -7, 35 }
};
int i, j;
HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
IImageList *imgl1, *imgl2;
HRESULT hr;
/* cast to IImageList */
imgl1 = (IImageList *) himl1;
imgl2 = (IImageList *) himl2;
for (i = 0; i < HOTSPOTS_MAX; i++) {
for (j = 0; j < HOTSPOTS_MAX; j++) {
int dx1 = hotspots[i].dx;
int dy1 = hotspots[i].dy;
int dx2 = hotspots[j].dx;
int dy2 = hotspots[j].dy;
int correctx, correcty, newx, newy;
char loc[256];
IImageList *imglNew;
POINT ppt;
hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
/* check merging the dragged image with a second image */
hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
dx1, dy1, dx2, dy2);
sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
/* check new hotspot, it should be the same like the old one */
hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
ok(SUCCEEDED(hr), "GetDragImage failed\n");
ok(ppt.x == dx1 && ppt.y == dy1,
"Expected drag hotspot [%d,%d] got [%d,%d]\n",
dx1, dy1, ppt.x, ppt.y);
/* check size of new dragged image */
IImageList_GetIconSize(imglNew, &newx, &newy);
correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
ok(newx == correctx && newy == correcty,
"Expected drag image size [%d,%d] got [%d,%d]\n",
correctx, correcty, newx, newy);
sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
IImageList_EndDrag(imgl2);
}
}
#undef SIZEX1
#undef SIZEY1
#undef SIZEX2
#undef SIZEY2
#undef HOTSPOTS_MAX
IImageList_Release(imgl2);
IImageList_Release(imgl1);
}
static void DoTest1_v6(void)
{
IImageList *imgl;
HIMAGELIST himl;
HRESULT hr;
HICON hicon1;
HICON hicon2;
HICON hicon3;
int ret = 0;
/* create an imagelist to play with */
himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
ok(himl != 0,"failed to create imagelist\n");
imgl = (IImageList *) himl;
/* load the icons to add to the image list */
hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
ok(hicon1 != 0, "no hicon1\n");
hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
ok(hicon2 != 0, "no hicon2\n");
hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
ok(hicon3 != 0, "no hicon3\n");
/* remove when nothing exists */
hr = IImageList_Remove(imgl, 0);
ok(!(SUCCEEDED(hr)), "removed nonexistent icon\n");
/* removing everything from an empty imagelist should succeed */
hr = IImageList_Remove(imgl, -1);
ok(SUCCEEDED(hr), "removed nonexistent icon\n");
/* add three */
ok(SUCCEEDED(IImageList_ReplaceIcon(imgl, -1, hicon1, &ret)) && (ret == 0),"failed to add icon1\n");
ok(SUCCEEDED(IImageList_ReplaceIcon(imgl, -1, hicon2, &ret)) && (ret == 1),"failed to add icon2\n");
ok(SUCCEEDED(IImageList_ReplaceIcon(imgl, -1, hicon3, &ret)) && (ret == 2),"failed to add icon3\n");
/* remove an index out of range */
ok(FAILED(IImageList_Remove(imgl, 4711)),"removed nonexistent icon\n");
/* remove three */
ok(SUCCEEDED(IImageList_Remove(imgl,0)),"can't remove 0\n");
ok(SUCCEEDED(IImageList_Remove(imgl,0)),"can't remove 0\n");
ok(SUCCEEDED(IImageList_Remove(imgl,0)),"can't remove 0\n");
/* remove one extra */
ok(FAILED(IImageList_Remove(imgl, 0)),"removed nonexistent icon\n");
/* check SetImageCount/GetImageCount */
ok(SUCCEEDED(IImageList_SetImageCount(imgl, 3)), "couldn't increase image count\n");
ok(SUCCEEDED(IImageList_GetImageCount(imgl, &ret)) && (ret == 3), "invalid image count after increase\n");
ok(SUCCEEDED(IImageList_SetImageCount(imgl, 1)), "couldn't decrease image count\n");
ok(SUCCEEDED(IImageList_GetImageCount(imgl, &ret)) && (ret == 1), "invalid image count after decrease to 1\n");
ok(SUCCEEDED(IImageList_SetImageCount(imgl, 0)), "couldn't decrease image count\n");
ok(SUCCEEDED(IImageList_GetImageCount(imgl, &ret)) && (ret == 0), "invalid image count after decrease to 0\n");
/* destroy it */
ok(SUCCEEDED(IImageList_Release(imgl)),"release imagelist failed\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");
}
static void DoTest3_v6(void)
{
IImageList *imgl;
HIMAGELIST himl;
HBITMAP hbm1;
HBITMAP hbm2;
HBITMAP hbm3;
IMAGELISTDRAWPARAMS imldp;
HWND hwndfortest;
HDC hdc;
int ret;
hwndfortest = create_a_window();
hdc = GetDC(hwndfortest);
ok(hdc!=NULL, "couldn't get DC\n");
/* create an imagelist to play with */
himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
ok(himl!=0,"failed to create imagelist\n");
imgl = (IImageList *) himl;
/* load the icons to add to the image list */
hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
ok(hbm1 != 0, "no bitmap 1\n");
hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
ok(hbm2 != 0, "no bitmap 2\n");
hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
ok(hbm3 != 0, "no bitmap 3\n");
/* add three */
ok(SUCCEEDED(IImageList_Add(imgl, hbm1, 0, &ret)) && (ret == 0), "failed to add bitmap 1\n");
ok(SUCCEEDED(IImageList_Add(imgl, hbm2, 0, &ret)) && (ret == 1), "failed to add bitmap 2\n");
ok(SUCCEEDED(IImageList_SetImageCount(imgl, 3)), "Setimage count failed\n");
ok(SUCCEEDED(IImageList_Replace(imgl, 2, hbm3, 0)), "failed to replace bitmap 3\n");
memset(&imldp, 0, sizeof (imldp));
ok(FAILED(IImageList_Draw(imgl, &imldp)), "zero data succeeded!\n");
imldp.cbSize = sizeof (imldp);
imldp.hdcDst = hdc;
imldp.himl = himl;
if (FAILED(IImageList_Draw(imgl, &imldp)))
{
/* Earlier versions of native comctl32 use a smaller structure */
imldp.cbSize -= 3 * sizeof(DWORD);
ok(SUCCEEDED(IImageList_Draw(imgl, &imldp)), "should succeed\n");
}
REDRAW(hwndfortest);
WAIT;
imldp.fStyle = SRCCOPY;
imldp.rgbBk = CLR_DEFAULT;
imldp.rgbFg = CLR_DEFAULT;
imldp.y = 100;
imldp.x = 100;
ok(SUCCEEDED(IImageList_Draw(imgl, &imldp)), "should succeed\n");
imldp.i ++;
ok(SUCCEEDED(IImageList_Draw(imgl, &imldp)), "should succeed\n");
imldp.i ++;
ok(SUCCEEDED(IImageList_Draw(imgl, &imldp)), "should succeed\n");
imldp.i ++;
ok(FAILED(IImageList_Draw(imgl, &imldp)), "should fail\n");
/* remove three */
ok(SUCCEEDED(IImageList_Remove(imgl, 0)), "removing 1st bitmap\n");
ok(SUCCEEDED(IImageList_Remove(imgl, 0)), "removing 2nd bitmap\n");
ok(SUCCEEDED(IImageList_Remove(imgl, 0)), "removing 3rd bitmap\n");
/* destroy it */
ok(SUCCEEDED(IImageList_Release(imgl)), "release imagelist failed\n");
/* bitmaps should not be deleted by the imagelist */
ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
ReleaseDC(hwndfortest, hdc);
DestroyWindow(hwndfortest);
}
static void testMerge_v6(void)
{
HIMAGELIST himl1, himl2;
IImageList *imgl1, *imgl2, *merge;
HICON hicon1;
HWND hwnd = create_a_window();
HRESULT hr;
int ret;
himl1 = ImageList_Create(32,32,0,0,3);
ok(himl1 != NULL,"failed to create himl1\n");
himl2 = ImageList_Create(32,32,0,0,3);
ok(himl2 != NULL,"failed to create himl2\n");
hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
ok(hicon1 != NULL, "failed to create hicon1\n");
if (!himl1 || !himl2 || !hicon1)
return;
/* cast to IImageList */
imgl1 = (IImageList *) himl1;
imgl2 = (IImageList *) himl2;
ok(SUCCEEDED(IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret)) && (ret == 0),"add icon1 to himl2 failed\n");
/* If himl1 has no images, merge still succeeds */
hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
ok(SUCCEEDED(hr), "merge himl1,-1 failed\n");
if (SUCCEEDED(hr)) IImageList_Release(merge);
hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
ok(SUCCEEDED(hr), "merge himl1,0 failed\n");
if (SUCCEEDED(hr)) IImageList_Release(merge);
/* Same happens if himl2 is empty */
IImageList_Release(imgl2);
himl2 = ImageList_Create(32,32,0,0,3);
ok(himl2 != NULL,"failed to recreate himl2\n");
imgl2 = (IImageList *) himl2;
hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
ok(SUCCEEDED(hr), "merge himl2,-1 failed\n");
if (SUCCEEDED(hr)) IImageList_Release(merge);
hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
ok(SUCCEEDED(hr), "merge himl2,0 failed\n");
if (SUCCEEDED(hr)) IImageList_Release(merge);
/* Now try merging an image with itself */
ok(SUCCEEDED(IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret)) && (ret == 0),"re-add icon1 to himl2 failed\n");
hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
ok(SUCCEEDED(hr), "merge himl2 with itself failed\n");
if (SUCCEEDED(hr)) IImageList_Release(merge);
/* Try merging 2 different image lists */
ok(SUCCEEDED(IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret)) && (ret == 0),"add icon1 to himl1 failed\n");
hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
ok(SUCCEEDED(hr), "merge himl1 with himl2 failed\n");
if (SUCCEEDED(hr)) IImageList_Release(merge);
hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
ok(SUCCEEDED(hr), "merge himl1 with himl2 8,16 failed\n");
if (SUCCEEDED(hr)) IImageList_Release(merge);
IImageList_Release(imgl1);
IImageList_Release(imgl2);
DestroyIcon(hicon1);
DestroyWindow(hwnd);
}
START_TEST(imagelist)
{
ULONG_PTR ctx_cookie;
HANDLE hCtx;
HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
pImageList_Add = NULL;
pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
desktopDC=GetDC(NULL);
hinst = GetModuleHandleA(NULL);
InitCommonControls();
@ -998,4 +1633,36 @@ START_TEST(imagelist)
DoTest3();
testMerge();
test_imagelist_storage();
FreeLibrary(hComCtl32);
/* Now perform v6 tests */
if (!load_v6_module(&ctx_cookie, &hCtx))
return;
/* Reload comctl32 */
hComCtl32 = LoadLibraryA("comctl32.dll");
pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
/* Do v6.0 tests */
test_ImageList_DrawIndirect();
test_shell_imagelist();
test_iimagelist();
testHotspot_v6();
DoTest1_v6();
DoTest3_v6();
testMerge_v6();
CoUninitialize();
unload_v6_module(ctx_cookie, hCtx);
}

View file

@ -33,8 +33,6 @@ static HWND create_ipaddress_control (void)
handle = CreateWindowEx(0, WC_IPADDRESS, NULL,
WS_BORDER|WS_VISIBLE, 0, 0, 0, 0,
NULL, NULL, NULL, NULL);
assert(handle);
return handle;
}
@ -45,6 +43,11 @@ static void test_get_set_text(void)
INT r;
hwnd = create_ipaddress_control();
if (!hwnd)
{
win_skip("IPAddress control not implemented\n");
return;
}
/* check text just after creation */
r = GetWindowText(hwnd, ip, sizeof(ip)/sizeof(CHAR));

File diff suppressed because it is too large Load diff

View file

@ -104,7 +104,9 @@ static void test_GetPtrAW(void)
ok (count == sourcelen ||
broken(count == 0), /* win9x */
"Expected count to be %d, it was %d\n", sourcelen, count);
ok (!lstrcmp(dest, desttest), "Expected destination to not have changed\n");
ok (!lstrcmp(dest, desttest) ||
broken(!lstrcmp(dest, "")), /* Win7 */
"Expected destination to not have changed\n");
count = 0;
count = pStr_GetPtrA(source, NULL, destsize);

File diff suppressed because it is too large Load diff

View file

@ -69,11 +69,27 @@ static HANDLE (WINAPI *pCreateMRUListA)(LPCREATEMRULISTA);
static void (WINAPI *pFreeMRUList)(HANDLE);
static INT (WINAPI *pAddMRUStringA)(HANDLE,LPCSTR);
static INT (WINAPI *pEnumMRUList)(HANDLE,INT,LPVOID,DWORD);
static INT (WINAPI *pEnumMRUListW)(HANDLE,INT,LPVOID,DWORD);
static HANDLE (WINAPI *pCreateMRUListLazyA)(LPCREATEMRULISTA, DWORD, DWORD, DWORD);
static INT (WINAPI *pFindMRUData)(HANDLE, LPCVOID, DWORD, LPINT);
static INT (WINAPI *pAddMRUData)(HANDLE, LPCVOID, DWORD);
/*
static INT (WINAPI *pFindMRUStringA)(HANDLE,LPCSTR,LPINT);
*/
static void InitPointers(void)
{
pCreateMRUListA = (void*)GetProcAddress(hComctl32,(LPCSTR)151);
pFreeMRUList = (void*)GetProcAddress(hComctl32,(LPCSTR)152);
pAddMRUStringA = (void*)GetProcAddress(hComctl32,(LPCSTR)153);
pEnumMRUList = (void*)GetProcAddress(hComctl32,(LPCSTR)154);
pCreateMRUListLazyA = (void*)GetProcAddress(hComctl32,(LPCSTR)157);
pAddMRUData = (void*)GetProcAddress(hComctl32,(LPCSTR)167);
pFindMRUData = (void*)GetProcAddress(hComctl32,(LPCSTR)169);
pEnumMRUListW = (void*)GetProcAddress(hComctl32,(LPCSTR)403);
}
/* Based on RegDeleteTreeW from dlls/advapi32/registry.c */
static LSTATUS mru_RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
{
@ -227,11 +243,6 @@ static void test_MRUListA(void)
HKEY hKey;
INT iRet;
pCreateMRUListA = (void*)GetProcAddress(hComctl32,(LPCSTR)151);
pFreeMRUList = (void*)GetProcAddress(hComctl32,(LPCSTR)152);
pAddMRUStringA = (void*)GetProcAddress(hComctl32,(LPCSTR)153);
pEnumMRUList = (void*)GetProcAddress(hComctl32,(LPCSTR)154);
if (!pCreateMRUListA || !pFreeMRUList || !pAddMRUStringA || !pEnumMRUList)
{
skip("MRU entry points not found\n");
@ -374,7 +385,7 @@ static void test_MRUListA(void)
/* check entry 0 */
buffer[0] = 0;
iRet = pEnumMRUList(hMRU, 0, buffer, 255);
todo_wine ok(iRet == lstrlen(checks[3]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[3]), iRet);
ok(iRet == lstrlen(checks[3]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[3]), iRet);
ok(strcmp(buffer, checks[3]) == 0, "EnumMRUList expected %s, got %s\n", checks[3], buffer);
/* check entry 0 with a too small buffer */
@ -383,21 +394,21 @@ static void test_MRUListA(void)
buffer[2] = 'A'; /* unchanged */
buffer[3] = 0; /* unchanged */
iRet = pEnumMRUList(hMRU, 0, buffer, 2);
todo_wine ok(iRet == lstrlen(checks[3]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[3]), iRet);
todo_wine ok(strcmp(buffer, "T") == 0, "EnumMRUList expected %s, got %s\n", "T", buffer);
ok(iRet == lstrlen(checks[3]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[3]), iRet);
ok(strcmp(buffer, "T") == 0, "EnumMRUList expected %s, got %s\n", "T", buffer);
/* make sure space after buffer has old values */
ok(buffer[2] == 'A', "EnumMRUList expected %02x, got %02x\n", 'A', buffer[2]);
/* check entry 1 */
buffer[0] = 0;
iRet = pEnumMRUList(hMRU, 1, buffer, 255);
todo_wine ok(iRet == lstrlen(checks[1]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[1]), iRet);
ok(iRet == lstrlen(checks[1]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[1]), iRet);
ok(strcmp(buffer, checks[1]) == 0, "EnumMRUList expected %s, got %s\n", checks[1], buffer);
/* check entry 2 */
buffer[0] = 0;
iRet = pEnumMRUList(hMRU, 2, buffer, 255);
todo_wine ok(iRet == lstrlen(checks[2]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[2]), iRet);
ok(iRet == lstrlen(checks[2]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[2]), iRet);
ok(strcmp(buffer, checks[2]) == 0, "EnumMRUList expected %s, got %s\n", checks[2], buffer);
/* check out of bounds entry 3 */
@ -413,6 +424,89 @@ static void test_MRUListA(void)
/* FreeMRUList(NULL) crashes on Win98 OSR0 */
}
static void test_CreateMRUListLazyA(void)
{
HANDLE hMRU;
HKEY hKey;
CREATEMRULISTA listA = { 0 };
if (!pCreateMRUListLazyA || !pFreeMRUList)
{
win_skip("CreateMRUListLazyA or FreeMRUList entry points not found\n");
return;
}
/* wrong size */
listA.cbSize = sizeof(listA) + 1;
hMRU = pCreateMRUListLazyA(&listA, 0, 0, 0);
ok(hMRU == NULL, "Expected NULL handle, got %p\n", hMRU);
listA.cbSize = 4;
hMRU = pCreateMRUListLazyA(&listA, 0, 0, 0);
ok(hMRU == NULL, "Expected NULL handle, got %p\n", hMRU);
/* NULL hKey */
listA.cbSize = sizeof(listA);
listA.hKey = NULL;
hMRU = pCreateMRUListLazyA(&listA, 0, 0, 0);
ok(hMRU == NULL, "Expected NULL handle, got %p\n", hMRU);
/* NULL subkey */
ok(!RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEYA, &hKey),
"Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
listA.cbSize = sizeof(listA);
listA.hKey = hKey;
listA.lpszSubKey = NULL;
hMRU = pCreateMRUListLazyA(&listA, 0, 0, 0);
ok(hMRU == NULL || broken(hMRU != NULL), /* Win9x */
"Expected NULL handle, got %p\n", hMRU);
if (hMRU) pFreeMRUList(hMRU);
}
static void test_EnumMRUList(void)
{
if (!pEnumMRUList || !pEnumMRUListW)
{
win_skip("EnumMRUListA/EnumMRUListW entry point not found\n");
return;
}
/* NULL handle */
if (0)
{
/* crashes on NT4, passed on Win2k, XP, 2k3, Vista, 2k8 */
pEnumMRUList(NULL, 0, NULL, 0);
pEnumMRUListW(NULL, 0, NULL, 0);
}
}
static void test_FindMRUData(void)
{
INT iRet;
if (!pFindMRUData)
{
win_skip("FindMRUData entry point not found\n");
return;
}
/* NULL handle */
iRet = pFindMRUData(NULL, NULL, 0, NULL);
ok(iRet == -1, "FindMRUData expected -1, got %d\n", iRet);
}
static void test_AddMRUData(void)
{
INT iRet;
if (!pAddMRUData)
{
win_skip("AddMRUData entry point not found\n");
return;
}
/* NULL handle */
iRet = pFindMRUData(NULL, NULL, 0, NULL);
ok(iRet == -1, "AddMRUData expected -1, got %d\n", iRet);
}
START_TEST(mru)
{
hComctl32 = GetModuleHandleA("comctl32.dll");
@ -421,7 +515,13 @@ START_TEST(mru)
if (!create_reg_entries())
return;
InitPointers();
test_MRUListA();
test_CreateMRUListLazyA();
test_EnumMRUList();
test_FindMRUData();
test_AddMRUData();
delete_reg_entries();
}

View file

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

@ -47,7 +47,8 @@ struct message
msg_flags_t flags; /* message props */
WPARAM wParam; /* expected value of wParam */
LPARAM lParam; /* expected value of lParam */
UINT id; /* id of the window */
UINT id; /* extra message data: id of the window,
notify code etc. */
};
struct msg_sequence
@ -57,17 +58,237 @@ struct msg_sequence
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);
static 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++;
}
static 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;
}
static void flush_sequences(struct msg_sequence **seq, int n)
{
int i;
for (i = 0; i < n; i++)
flush_sequence(seq, i);
}
static 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 && expected->flags & optional)
{
expected++;
continue;
}
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);
}
#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);
static void init_msg_sequences(struct msg_sequence **seq, int n)
{
int i;
void init_msg_sequences(struct msg_sequence **seq, int n);
for (i = 0; i < n; i++)
seq[i] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct msg_sequence));
}

View file

@ -163,6 +163,7 @@ static void cleanup(void)
static void test_redraw(void)
{
RECT client_rect;
LRESULT ret;
SendMessageA(hProgressWnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
SendMessageA(hProgressWnd, PBM_SETPOS, 10, 0);
@ -184,7 +185,11 @@ static void test_redraw(void)
/* 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");
ret = SendMessageA(hProgressWnd, PBM_GETPOS, 0, 0);
if (ret == 0)
win_skip("PBM_GETPOS needs comctl32 > 4.70\n");
else
ok(ret == 100, "PBM_GETPOS returned a wrong position : %d\n", (UINT)ret);
/* PBM_SETRANGE and PBM_SETRANGE32:
Usually the progress bar doesn't repaint itself immediately. If the

View file

@ -1,6 +1,7 @@
/* Unit test suite for property sheet control.
*
* Copyright 2006 Huw Davies
* Copyright 2009 Jan de Mooij
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,9 +21,16 @@
#include <windows.h>
#include <commctrl.h>
#include "resources.h"
#include "wine/test.h"
static HWND parent;
static HWND sheethwnd;
static LONG active_page = -1;
#define IDC_APPLY_BUTTON 12321
static int CALLBACK sheet_callback(HWND hwnd, UINT msg, LPARAM lparam)
{
@ -33,12 +41,13 @@ static int CALLBACK sheet_callback(HWND hwnd, UINT msg, LPARAM lparam)
char caption[256];
GetWindowTextA(hwnd, caption, sizeof(caption));
ok(!strcmp(caption,"test caption"), "caption: %s\n", caption);
sheethwnd = hwnd;
return 0;
}
}
return 0;
}
static INT_PTR CALLBACK page_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
LPARAM lparam)
{
@ -64,6 +73,10 @@ static INT_PTR CALLBACK page_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
return FALSE;
}
}
case WM_NCDESTROY:
ok(!SendMessageA(sheethwnd, PSM_INDEXTOHWND, 400, 0),"Should always be 0\n");
return TRUE;
default:
return FALSE;
}
@ -79,7 +92,7 @@ static void test_title(void)
memset(&psp, 0, sizeof(psp));
psp.dwSize = sizeof(psp);
psp.dwFlags = 0;
psp.hInstance = GetModuleHandleW(NULL);
psp.hInstance = GetModuleHandleA(NULL);
U(psp).pszTemplate = "prop_page1";
U2(psp).pszIcon = NULL;
psp.pfnDlgProc = page_dlg_proc;
@ -97,6 +110,12 @@ static void test_title(void)
psh.pfnCallback = sheet_callback;
hdlg = (HWND)PropertySheetA(&psh);
if (hdlg == INVALID_HANDLE_VALUE)
{
win_skip("comctl32 4.70 needs dwSize adjustment\n");
psh.dwSize = sizeof(psh) - sizeof(HBITMAP) - sizeof(HPALETTE) - sizeof(HBITMAP);
hdlg = (HWND)PropertySheetA(&psh);
}
DestroyWindow(hdlg);
}
@ -110,7 +129,7 @@ static void test_nopage(void)
memset(&psp, 0, sizeof(psp));
psp.dwSize = sizeof(psp);
psp.dwFlags = 0;
psp.hInstance = GetModuleHandleW(NULL);
psp.hInstance = GetModuleHandleA(NULL);
U(psp).pszTemplate = "prop_page1";
U2(psp).pszIcon = NULL;
psp.pfnDlgProc = page_dlg_proc;
@ -128,6 +147,12 @@ static void test_nopage(void)
psh.pfnCallback = sheet_callback;
hdlg = (HWND)PropertySheetA(&psh);
if (hdlg == INVALID_HANDLE_VALUE)
{
win_skip("comctl32 4.70 needs dwSize adjustment\n");
psh.dwSize = sizeof(psh) - sizeof(HBITMAP) - sizeof(HPALETTE) - sizeof(HBITMAP);
hdlg = (HWND)PropertySheetA(&psh);
}
ShowWindow(hdlg,SW_NORMAL);
SendMessage(hdlg, PSM_REMOVEPAGE, 0, 0);
RedrawWindow(hdlg,NULL,NULL,RDW_UPDATENOW|RDW_ERASENOW);
@ -170,6 +195,7 @@ static void test_disableowner(void)
HPROPSHEETPAGE hpsp[1];
PROPSHEETPAGEA psp;
PROPSHEETHEADERA psh;
INT_PTR p;
register_parent_wnd_class();
parent = CreateWindowA("parent class", "", WS_CAPTION | WS_SYSMENU | WS_VISIBLE, 100, 100, 100, 100, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), 0);
@ -177,7 +203,7 @@ static void test_disableowner(void)
memset(&psp, 0, sizeof(psp));
psp.dwSize = sizeof(psp);
psp.dwFlags = 0;
psp.hInstance = GetModuleHandleW(NULL);
psp.hInstance = GetModuleHandleA(NULL);
U(psp).pszTemplate = "prop_page1";
U2(psp).pszIcon = NULL;
psp.pfnDlgProc = NULL;
@ -194,14 +220,227 @@ static void test_disableowner(void)
U3(psh).phpage = hpsp;
psh.pfnCallback = disableowner_callback;
PropertySheetA(&psh);
p = PropertySheetA(&psh);
todo_wine
ok(p == 0, "Expected 0, got %ld\n", p);
ok(IsWindowEnabled(parent) != 0, "parent window should be enabled\n");
DestroyWindow(parent);
}
static INT_PTR CALLBACK nav_page_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg){
case WM_NOTIFY:
{
LPNMHDR hdr = (LPNMHDR)lparam;
switch(hdr->code){
case PSN_SETACTIVE:
active_page = PropSheet_HwndToIndex(hdr->hwndFrom, hwnd);
return TRUE;
case PSN_KILLACTIVE:
/* prevent navigation away from the fourth page */
if(active_page == 3){
SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
return TRUE;
}
}
break;
}
}
return FALSE;
}
static void test_wiznavigation(void)
{
HPROPSHEETPAGE hpsp[4];
PROPSHEETPAGEA psp[4];
PROPSHEETHEADERA psh;
HWND hdlg, control;
LONG_PTR controlID;
LRESULT defidres;
BOOL hwndtoindex_supported = TRUE;
const INT nextID = 12324;
const INT backID = 12323;
/* create the property sheet pages */
memset(psp, 0, sizeof(PROPSHEETPAGEA) * 4);
psp[0].dwSize = sizeof(PROPSHEETPAGEA);
psp[0].hInstance = GetModuleHandleA(NULL);
U(psp[0]).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_INTRO);
psp[0].pfnDlgProc = nav_page_proc;
hpsp[0] = CreatePropertySheetPageA(&psp[0]);
psp[1].dwSize = sizeof(PROPSHEETPAGEA);
psp[1].hInstance = GetModuleHandleA(NULL);
U(psp[1]).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_EDIT);
psp[1].pfnDlgProc = nav_page_proc;
hpsp[1] = CreatePropertySheetPageA(&psp[1]);
psp[2].dwSize = sizeof(PROPSHEETPAGEA);
psp[2].hInstance = GetModuleHandleA(NULL);
U(psp[2]).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_RADIO);
psp[2].pfnDlgProc = nav_page_proc;
hpsp[2] = CreatePropertySheetPageA(&psp[2]);
psp[3].dwSize = sizeof(PROPSHEETPAGEA);
psp[3].hInstance = GetModuleHandleA(NULL);
U(psp[3]).pszTemplate = MAKEINTRESOURCE(IDD_PROP_PAGE_EXIT);
psp[3].pfnDlgProc = nav_page_proc;
hpsp[3] = CreatePropertySheetPageA(&psp[3]);
/* set up the property sheet dialog */
memset(&psh, 0, sizeof(psh));
psh.dwSize = sizeof(psh);
psh.dwFlags = PSH_MODELESS | PSH_WIZARD;
psh.pszCaption = "A Wizard";
psh.nPages = 4;
psh.hwndParent = GetDesktopWindow();
U3(psh).phpage = hpsp;
hdlg = (HWND)PropertySheetA(&psh);
if (hdlg == INVALID_HANDLE_VALUE)
{
win_skip("comctl32 4.70 needs dwSize adjustment\n");
psh.dwSize = sizeof(psh) - sizeof(HBITMAP) - sizeof(HPALETTE) - sizeof(HBITMAP);
hdlg = (HWND)PropertySheetA(&psh);
}
ok(active_page == 0, "Active page should be 0. Is: %d\n", active_page);
control = GetFocus();
controlID = GetWindowLongPtr(control, GWLP_ID);
ok(controlID == nextID, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID, controlID);
/* simulate pressing the Next button */
SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
if (!active_page) hwndtoindex_supported = FALSE;
if (hwndtoindex_supported)
ok(active_page == 1, "Active page should be 1 after pressing Next. Is: %d\n", active_page);
control = GetFocus();
controlID = GetWindowLongPtr(control, GWLP_ID);
ok(controlID == IDC_PS_EDIT1, "Focus should be set to the first item on the second page. Expected: %d, Found: %ld\n", IDC_PS_EDIT1, controlID);
defidres = SendMessage(hdlg, DM_GETDEFID, 0, 0);
ok(defidres == MAKELRESULT(nextID, DC_HASDEFID), "Expected default button ID to be %d, is %d\n", nextID, LOWORD(defidres));
/* set the focus to the second edit box on this page */
SetFocus(GetNextDlgTabItem(hdlg, control, FALSE));
/* press next again */
SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
if (hwndtoindex_supported)
ok(active_page == 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page);
control = GetFocus();
controlID = GetWindowLongPtr(control, GWLP_ID);
ok(controlID == IDC_PS_RADIO1, "Focus should have been set to item on third page. Expected: %d, Found %ld\n", IDC_PS_RADIO1, controlID);
/* back button */
SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_BACK, 0);
if (hwndtoindex_supported)
ok(active_page == 1, "Active page should be 1 after pressing Back. Is: %d\n", active_page);
control = GetFocus();
controlID = GetWindowLongPtr(control, GWLP_ID);
ok(controlID == IDC_PS_EDIT1, "Focus should have been set to the first item on second page. Expected: %d, Found %ld\n", IDC_PS_EDIT1, controlID);
defidres = SendMessage(hdlg, DM_GETDEFID, 0, 0);
ok(defidres == MAKELRESULT(backID, DC_HASDEFID), "Expected default button ID to be %d, is %d\n", backID, LOWORD(defidres));
/* press next twice */
SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
if (hwndtoindex_supported)
ok(active_page == 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page);
SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
if (hwndtoindex_supported)
ok(active_page == 3, "Active page should be 3 after pressing Next. Is: %d\n", active_page);
else
active_page = 3;
control = GetFocus();
controlID = GetWindowLongPtr(control, GWLP_ID);
ok(controlID == nextID, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID, controlID);
/* try to navigate away, but shouldn't be able to */
SendMessage(hdlg, PSM_PRESSBUTTON, PSBTN_BACK, 0);
ok(active_page == 3, "Active page should still be 3 after pressing Back. Is: %d\n", active_page);
defidres = SendMessage(hdlg, DM_GETDEFID, 0, 0);
ok(defidres == MAKELRESULT(nextID, DC_HASDEFID), "Expected default button ID to be %d, is %d\n", nextID, LOWORD(defidres));
DestroyWindow(hdlg);
}
static void test_buttons(void)
{
HPROPSHEETPAGE hpsp[1];
PROPSHEETPAGEA psp;
PROPSHEETHEADERA psh;
HWND hdlg;
HWND button;
RECT rc;
int prevRight, top;
memset(&psp, 0, sizeof(psp));
psp.dwSize = sizeof(psp);
psp.dwFlags = 0;
psp.hInstance = GetModuleHandleA(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);
if (hdlg == INVALID_HANDLE_VALUE)
{
win_skip("comctl32 4.70 needs dwSize adjustment\n");
psh.dwSize = sizeof(psh) - sizeof(HBITMAP) - sizeof(HPALETTE) - sizeof(HBITMAP);
hdlg = (HWND)PropertySheetA(&psh);
}
/* OK button */
button = GetDlgItem(hdlg, IDOK);
GetWindowRect(button, &rc);
prevRight = rc.right;
top = rc.top;
/* Cancel button */
button = GetDlgItem(hdlg, IDCANCEL);
GetWindowRect(button, &rc);
ok(rc.top == top, "Cancel button should have same top as OK button\n");
ok(rc.left > prevRight, "Cancel button should be to the right of OK button\n");
prevRight = rc.right;
button = GetDlgItem(hdlg, IDC_APPLY_BUTTON);
GetWindowRect(button, &rc);
ok(rc.top == top, "Apply button should have same top as OK button\n");
ok(rc.left > prevRight, "Apply button should be to the right of Cancel button\n");
prevRight = rc.right;
button = GetDlgItem(hdlg, IDHELP);
GetWindowRect(button, &rc);
ok(rc.top == top, "Help button should have same top as OK button\n");
ok(rc.left > prevRight, "Help button should be to the right of Apply button\n");
DestroyWindow(hdlg);
}
START_TEST(propsheet)
{
test_title();
test_nopage();
test_disableowner();
test_wiznavigation();
test_buttons();
}

View file

@ -32,7 +32,6 @@
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 && \
@ -66,14 +65,17 @@ static BOOL is_font_installed(const char *name)
return ret;
}
static void rebuild_rebar(HWND *hRebar)
static HWND create_rebar_control(void)
{
if (*hRebar)
DestroyWindow(*hRebar);
HWND hwnd;
*hRebar = CreateWindow(REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
hwnd = 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);
ok(hwnd != NULL, "Failed to create Rebar\n");
SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
return hwnd;
}
static HWND build_toolbar(int nr, HWND hParent)
@ -85,7 +87,7 @@ static HWND build_toolbar(int nr, HWND hParent)
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_BUTTONSTRUCTSIZE, 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");
@ -104,7 +106,7 @@ static HWND build_toolbar(int nr, HWND hParent)
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_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGES failed\n");
ok(SendMessage(hToolbar, TB_ADDBUTTONS, 5+nr, (LPARAM)btns), "TB_ADDBUTTONS failed\n");
return hToolbar;
}
@ -117,7 +119,7 @@ static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
{
NMHDR *lpnm = (NMHDR *)lParam;
if (lpnm->code == RBN_HEIGHTCHANGE)
GetClientRect(hRebar, &height_change_notify_rect);
GetClientRect(lpnm->hwndFrom, &height_change_notify_rect);
}
break;
}
@ -150,7 +152,7 @@ static void dump_sizes(HWND hRebar)
for (i=0; i<count; i++)
{
REBARBANDINFO rbi;
rbi.cbSize = sizeof(REBARBANDINFO);
rbi.cbSize = REBARBANDINFOA_V6_SIZE;
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");
@ -310,10 +312,10 @@ static int rbsize_numtests = 0;
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"); \
ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_GETRECT\n"); \
if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \
check_rect("band", rc, res->bands[i].rc); \
rbi.cbSize = sizeof(REBARBANDINFO); \
rbi.cbSize = REBARBANDINFOA_V6_SIZE; \
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"); \
@ -329,11 +331,11 @@ static int rbsize_numtests = 0;
static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int cxIdeal)
{
CHAR buffer[MAX_PATH];
REBARBANDINFO rbi;
REBARBANDINFOA rbi;
if (lpszText != NULL)
strcpy(buffer, lpszText);
rbi.cbSize = sizeof(rbi);
rbi.cbSize = REBARBANDINFOA_V6_SIZE;
rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_TEXT;
rbi.cx = cx;
rbi.cxMinChild = cxMinChild;
@ -344,16 +346,16 @@ static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int
SendMessage(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
}
static void layout_test(void)
static void test_layout(void)
{
HWND hRebar = NULL;
HWND hRebar;
REBARBANDINFO rbi;
HIMAGELIST himl;
REBARINFO ri;
rebuild_rebar(&hRebar);
hRebar = create_rebar_control();
check_sizes();
rbi.cbSize = sizeof(rbi);
rbi.cbSize = REBARBANDINFOA_V6_SIZE;
rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
rbi.cx = 200;
rbi.cxMinChild = 100;
@ -409,7 +411,9 @@ static void layout_test(void)
SendMessageA(hRebar, RB_DELETEBAND, 1, 0);
check_sizes();
rebuild_rebar(&hRebar);
DestroyWindow(hRebar);
hRebar = create_rebar_control();
add_band_w(hRebar, "ABC", 70, 40, 100);
add_band_w(hRebar, NULL, 40, 70, 100);
add_band_w(hRebar, NULL, 170, 240, 100);
@ -448,8 +452,10 @@ static void layout_test(void)
SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
check_sizes();
DestroyWindow(hRebar);
/* VARHEIGHT resizing test on a horizontal rebar */
rebuild_rebar(&hRebar);
hRebar = create_rebar_control();
SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_AUTOSIZE);
check_sizes();
rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
@ -474,8 +480,10 @@ static void layout_test(void)
SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
check_sizes();
DestroyWindow(hRebar);
/* VARHEIGHT resizing on a vertical rebar */
rebuild_rebar(&hRebar);
hRebar = create_rebar_control();
SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | CCS_VERT | RBS_AUTOSIZE);
check_sizes();
rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
@ -503,6 +511,7 @@ static void layout_test(void)
check_sizes();
DestroyWindow(hRebar);
ImageList_Destroy(himl);
}
#if 0 /* use this to generate more tests */
@ -684,7 +693,7 @@ static int resize_numtests = 0;
#endif
static void resize_test(void)
static void test_resize(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,
@ -696,6 +705,8 @@ static void resize_test(void)
for (i = 0; i < styles_count; i++)
{
HWND hRebar;
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);
@ -735,17 +746,17 @@ static void resize_test(void)
}
}
static void expect_band_content(UINT uBand, INT fStyle, COLORREF clrFore,
static void expect_band_content(HWND hRebar, 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)
INT cxHeader, INT cxHeader_broken)
{
CHAR buf[MAX_PATH] = "abc";
REBARBANDINFO rb;
REBARBANDINFOA rb;
memset(&rb, 0xdd, sizeof(rb));
rb.cbSize = sizeof(rb);
rb.cbSize = REBARBANDINFOA_V6_SIZE;
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;
@ -753,8 +764,8 @@ static void expect_band_content(UINT uBand, INT fStyle, COLORREF clrFore,
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(rb.clrFore, clrFore, COLORREF, "%x");
expect_eq(rb.clrBack, clrBack, COLORREF, "%x");
expect_eq(strcmp(rb.lpText, lpText), 0, int, "%d");
expect_eq(rb.iImage, iImage, int, "%x");
expect_eq(rb.hwndChild, hwndChild, HWND, "%p");
@ -769,20 +780,27 @@ static void expect_band_content(UINT uBand, INT fStyle, COLORREF clrFore,
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");
ok( rb.cxHeader == cxHeader || broken(rb.cxHeader == cxHeader_broken),
"expected %d for %d\n", cxHeader, rb.cxHeader );
}
static void bandinfo_test(void)
static void test_bandinfo(void)
{
REBARBANDINFOA rb;
CHAR szABC[] = "ABC";
CHAR szABCD[] = "ABCD";
HWND hRebar;
rebuild_rebar(&hRebar);
rb.cbSize = sizeof(REBARBANDINFO);
hRebar = create_rebar_control();
rb.cbSize = REBARBANDINFOA_V6_SIZE;
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);
if (!SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb))
{
win_skip( "V6 info not supported\n" );
DestroyWindow(hRebar);
return;
}
expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
rb.fMask = RBBIM_CHILDSIZE;
rb.cxMinChild = 15;
@ -790,62 +808,93 @@ static void bandinfo_test(void)
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);
ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
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);
ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 35, -1);
rb.cbSize = sizeof(REBARBANDINFO);
rb.cbSize = REBARBANDINFOA_V6_SIZE;
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);
expect_band_content(hRebar, 1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9, -1);
expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 40, -1);
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);
ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
expect_band_content(hRebar, 0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 50, -1);
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);
ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
expect_band_content(hRebar, 0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5, -1);
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);
ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
expect_band_content(hRebar, 0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5, -1);
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);
ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
expect_band_content(hRebar, 0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 40, 5);
DestroyWindow(hRebar);
}
START_TEST(rebar)
static void test_colors(void)
{
HMODULE hComctl32;
BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
INITCOMMONCONTROLSEX iccex;
WNDCLASSA wc;
MSG msg;
RECT rc;
COLORSCHEME scheme;
COLORREF clr;
BOOL ret;
HWND hRebar;
REBARBANDINFOA bi;
/* LoadLibrary is needed. This file has no references to functions in comctl32 */
hComctl32 = LoadLibraryA("comctl32.dll");
pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
if (!pInitCommonControlsEx)
hRebar = create_rebar_control();
/* test default colors */
clr = SendMessage(hRebar, RB_GETTEXTCOLOR, 0, 0);
compare(clr, CLR_NONE, "%x");
clr = SendMessage(hRebar, RB_GETBKCOLOR, 0, 0);
compare(clr, CLR_NONE, "%x");
scheme.dwSize = sizeof(scheme);
scheme.clrBtnHighlight = 0;
scheme.clrBtnShadow = 0;
ret = SendMessage(hRebar, RB_GETCOLORSCHEME, 0, (LPARAM)&scheme);
if (ret)
{
skip("InitCommonControlsEx() is missing. Skipping the tests\n");
return;
compare(scheme.clrBtnHighlight, CLR_DEFAULT, "%x");
compare(scheme.clrBtnShadow, CLR_DEFAULT, "%x");
}
iccex.dwSize = sizeof(iccex);
iccex.dwICC = ICC_COOL_CLASSES;
pInitCommonControlsEx(&iccex);
else
skip("RB_GETCOLORSCHEME not supported\n");
/* check default band colors */
add_band_w(hRebar, "", 0, 10, 10);
bi.cbSize = REBARBANDINFOA_V6_SIZE;
bi.fMask = RBBIM_COLORS;
bi.clrFore = bi.clrBack = 0xc0ffe;
ret = SendMessage(hRebar, RB_GETBANDINFO, 0, (LPARAM)&bi);
ok(ret, "RB_GETBANDINFO failed\n");
compare(bi.clrFore, RGB(0, 0, 0), "%x");
compare(bi.clrBack, GetSysColor(COLOR_3DFACE), "%x");
SendMessage(hRebar, RB_SETTEXTCOLOR, 0, RGB(255, 0, 0));
bi.clrFore = bi.clrBack = 0xc0ffe;
ret = SendMessage(hRebar, RB_GETBANDINFO, 0, (LPARAM)&bi);
ok(ret, "RB_GETBANDINFO failed\n");
compare(bi.clrFore, RGB(0, 0, 0), "%x");
DestroyWindow(hRebar);
}
static BOOL register_parent_wnd_class(void)
{
WNDCLASSA wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
@ -857,23 +906,59 @@ START_TEST(rebar)
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyTestWnd";
wc.lpfnWndProc = MyWndProc;
RegisterClassA(&wc);
hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
return RegisterClassA(&wc);
}
static HWND create_parent_window(void)
{
HWND hwnd;
if (!register_parent_wnd_class()) return NULL;
hwnd = 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();
ShowWindow(hwnd, SW_SHOW);
return hwnd;
}
if(is_font_installed("System") && is_font_installed("Tahoma"))
START_TEST(rebar)
{
HMODULE hComctl32;
BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
INITCOMMONCONTROLSEX iccex;
MSG msg;
/* LoadLibrary is needed. This file has no references to functions in comctl32 */
hComctl32 = LoadLibraryA("comctl32.dll");
pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
if (!pInitCommonControlsEx)
{
layout_test();
resize_test();
} else
skip("Missing System or Tahoma font\n");
win_skip("InitCommonControlsEx() is missing. Skipping the tests\n");
return;
}
iccex.dwSize = sizeof(iccex);
iccex.dwICC = ICC_COOL_CLASSES;
pInitCommonControlsEx(&iccex);
hMainWnd = create_parent_window();
test_bandinfo();
test_colors();
if(!is_font_installed("System") || !is_font_installed("Tahoma"))
{
skip("Missing System or Tahoma font\n");
goto out;
}
test_layout();
test_resize();
out:
PostQuitMessage(0);
while(GetMessageA(&msg,0,0,0)) {
TranslateMessage(&msg);

View file

@ -31,4 +31,14 @@
#define IDS_TBADD5 20
#define IDS_TBADD7 22
#define IDD_PROP_PAGE_INTRO 30
#define IDD_PROP_PAGE_EDIT 31
#define IDD_PROP_PAGE_RADIO 32
#define IDD_PROP_PAGE_EXIT 33
#define IDC_PS_EDIT1 1000
#define IDC_PS_EDIT2 1001
#define IDC_PS_RADIO1 1010
#define IDC_PS_RADIO2 1011
#endif /* __WINE_COMCTL32_TEST_RESOURCES_H */

View file

@ -30,6 +30,40 @@ FONT 8, "MS Shell Dlg"
LTEXT "Test", -1, 10, 6, 100, 8
}
IDD_PROP_PAGE_INTRO DIALOG LOADONCALL MOVEABLE DISCARDABLE 5, 43, 227, 215
STYLE WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS | WS_VISIBLE
CAPTION "Edit Control Page"
FONT 8, "MS Shell Dlg"
{
LTEXT "This is a test property sheet!", -1, 10, 6, 100, 8
}
IDD_PROP_PAGE_EDIT DIALOG LOADONCALL MOVEABLE DISCARDABLE 5, 43, 227, 215
STYLE WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS | WS_VISIBLE
CAPTION "Edit Control Page"
FONT 8, "MS Shell Dlg"
{
EDITTEXT IDC_PS_EDIT1, 5, 5, 150, 140, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_MULTILINE
EDITTEXT IDC_PS_EDIT2, 5, 160, 150, 28, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_MULTILINE
}
IDD_PROP_PAGE_RADIO DIALOG LOADONCALL MOVEABLE DISCARDABLE 5, 43, 227, 215
STYLE WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS | WS_VISIBLE
CAPTION "Edit Control Page"
FONT 8, "MS Shell Dlg"
{
CONTROL "Radio1", IDC_PS_RADIO1, "Button", BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 20, 20, 39, 10
CONTROL "Radio2", IDC_PS_RADIO2, "Button", BS_AUTORADIOBUTTON, 20, 40, 39, 10
}
IDD_PROP_PAGE_EXIT DIALOG LOADONCALL MOVEABLE DISCARDABLE 5, 43, 227, 215
STYLE WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS | WS_VISIBLE
CAPTION "Edit Control Page"
FONT 8, "MS Shell Dlg"
{
LTEXT "This has been a test property sheet!", -1, 10, 6, 170, 8
}
STRINGTABLE
{
IDS_TBADD1 "abc"

View file

@ -466,6 +466,112 @@ static void test_status_ownerdraw(void)
SetWindowLongPtr( g_hMainWnd, GWLP_WNDPROC, (LONG_PTR)g_wndproc_saved );
}
static void test_gettext(void)
{
HWND hwndStatus = CreateWindow(SUBCLASS_NAME, NULL, WS_CHILD|WS_VISIBLE,
0, 0, 300, 20, g_hMainWnd, NULL, NULL, NULL);
char buf[5];
int r;
r = SendMessage(hwndStatus, SB_SETTEXT, 0, (LPARAM)"Text");
expect(TRUE, r);
r = SendMessage(hwndStatus, WM_GETTEXTLENGTH, 0, 0);
expect(4, r);
/* A size of 0 returns the length of the text */
r = SendMessage(hwndStatus, WM_GETTEXT, 0, 0);
expect(4, r);
/* A size of 1 only stores the NULL terminator */
buf[0] = 0xa;
r = SendMessage(hwndStatus, WM_GETTEXT, 1, (LPARAM)buf);
ok( r == 0 || broken(r == 4), "Expected 0 got %d\n", r );
if (!r) ok(!buf[0], "expected empty buffer\n");
/* A size of 2 returns a length 1 */
r = SendMessage(hwndStatus, WM_GETTEXT, 2, (LPARAM)buf);
ok( r == 1 || broken(r == 4), "Expected 1 got %d\n", r );
r = SendMessage(hwndStatus, WM_GETTEXT, sizeof(buf), (LPARAM)buf);
expect(4, r);
ok(!strcmp(buf, "Text"), "expected Text, got %s\n", buf);
DestroyWindow(hwndStatus);
}
/* Notify events to parent */
static BOOL g_got_dblclk;
static BOOL g_got_click;
static BOOL g_got_rdblclk;
static BOOL g_got_rclick;
/* Messages to parent */
static BOOL g_got_contextmenu;
static LRESULT WINAPI test_notify_parent_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_NOTIFY:
{
NMHDR *hdr = ((LPNMHDR)lParam);
switch(hdr->code)
{
case NM_DBLCLK: g_got_dblclk = TRUE; break;
case NM_CLICK: g_got_click = TRUE; break;
case NM_RDBLCLK: g_got_rdblclk = TRUE; break;
case NM_RCLICK: g_got_rclick = TRUE; break;
}
/* Return zero to indicate default processing */
return 0;
}
case WM_CONTEXTMENU: g_got_contextmenu = TRUE; return 0;
default:
return( DefWindowProcA(hwnd, msg, wParam, lParam));
}
return 0;
}
/* Test that WM_NOTIFY messages from the status control works correctly */
static void test_notify(void)
{
HWND hwndParent;
HWND hwndStatus;
ATOM atom;
WNDCLASSA wclass = {0};
wclass.lpszClassName = "TestNotifyParentClass";
wclass.lpfnWndProc = test_notify_parent_proc;
atom = RegisterClassA(&wclass);
ok(atom, "RegisterClass failed\n");
/* create parent */
hwndParent = CreateWindow(wclass.lpszClassName, "parent", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 300, 20, NULL, NULL, NULL, NULL);
ok(hwndParent != NULL, "Parent creation failed!\n");
/* create status bar */
hwndStatus = CreateWindow(STATUSCLASSNAME, NULL, WS_VISIBLE | WS_CHILD,
0, 0, 300, 20, hwndParent, NULL, NULL, NULL);
ok(hwndStatus != NULL, "Status creation failed!\n");
/* Send various mouse event, and check that we get them */
g_got_dblclk = FALSE;
SendMessage(hwndStatus, WM_LBUTTONDBLCLK, 0, 0);
ok(g_got_dblclk, "WM_LBUTTONDBLCLK was not processed correctly!\n");
g_got_rdblclk = FALSE;
SendMessage(hwndStatus, WM_RBUTTONDBLCLK, 0, 0);
ok(g_got_rdblclk, "WM_RBUTTONDBLCLK was not processed correctly!\n");
g_got_click = FALSE;
SendMessage(hwndStatus, WM_LBUTTONUP, 0, 0);
ok(g_got_click, "WM_LBUTTONUP was not processed correctly!\n");
/* For R-UP, check that we also get the context menu from the default processing */
g_got_contextmenu = FALSE;
g_got_rclick = FALSE;
SendMessage(hwndStatus, WM_RBUTTONUP, 0, 0);
ok(g_got_rclick, "WM_RBUTTONUP was not processed correctly!\n");
ok(g_got_contextmenu, "WM_RBUTTONUP did not activate the context menu!\n");
}
START_TEST(status)
{
hinst = GetModuleHandleA(NULL);
@ -483,4 +589,6 @@ START_TEST(status)
test_create();
test_height();
test_status_ownerdraw();
test_gettext();
test_notify();
}

View file

@ -279,21 +279,49 @@ static BOOL RegisterWindowClasses(void)
return TRUE;
}
START_TEST(subclass)
static int init_function_pointers(void)
{
HMODULE hdll;
hdll = GetModuleHandleA("comctl32.dll");
assert(hdll);
HMODULE hmod;
void *ptr;
hmod = GetModuleHandleA("comctl32.dll");
assert(hmod);
/* 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);
#define MAKEFUNC_ORD(f, ord) (p##f = (void*)GetProcAddress(hmod, (LPSTR)(ord)))
MAKEFUNC_ORD(SetWindowSubclass, 410);
MAKEFUNC_ORD(RemoveWindowSubclass, 412);
MAKEFUNC_ORD(DefSubclassProc, 413);
#undef MAKEFUNC_ORD
if(!pSetWindowSubclass || !pRemoveWindowSubclass || !pDefSubclassProc)
return;
{
win_skip("SetWindowSubclass and friends are not available\n");
return 0;
}
/* test named exports */
ptr = GetProcAddress(hmod, "SetWindowSubclass");
ok(broken(ptr == 0) || ptr != 0, "expected named export for SetWindowSubclass\n");
if(ptr)
{
#define TESTNAMED(f) \
ptr = (void*)GetProcAddress(hmod, #f); \
ok(ptr != 0, "expected named export for " #f "\n");
TESTNAMED(RemoveWindowSubclass);
TESTNAMED(DefSubclassProc);
/* GetWindowSubclass exported for V6 only */
#undef TESTNAMED
}
return 1;
}
START_TEST(subclass)
{
if(!init_function_pointers()) return;
if(!RegisterWindowClasses()) assert(0);

View file

@ -89,13 +89,14 @@ static const struct message create_parent_wnd_seq[] = {
static const struct message add_tab_to_parent[] = {
{ TCM_INSERTITEMA, sent },
{ TCM_INSERTITEMA, sent },
{ TCM_INSERTITEMA, sent|optional },
{ WM_NOTIFYFORMAT, sent|defwinproc },
{ WM_QUERYUISTATE, sent|wparam|lparam|defwinproc|optional, 0, 0 },
{ WM_PARENTNOTIFY, sent|defwinproc },
{ TCM_INSERTITEMA, sent },
{ TCM_INSERTITEMA, sent },
{ TCM_INSERTITEMA, sent },
{ TCM_INSERTITEMA, sent|optional },
{ 0 }
};
@ -236,12 +237,15 @@ 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 },
{ WM_NOTIFYFORMAT, sent|defwinproc|optional },
{ WM_QUERYUISTATE, sent|defwinproc|optional },
{ WM_PARENTNOTIFY, sent|defwinproc|optional },
{ TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
{ TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
{ TCM_INSERTITEM, sent|wparam, 2 },
{ WM_NOTIFYFORMAT, sent|defwinproc, },
{ WM_NOTIFYFORMAT, sent|defwinproc|optional },
{ WM_QUERYUISTATE, sent|defwinproc|optional, },
{ WM_PARENTNOTIFY, sent|defwinproc, },
{ WM_PARENTNOTIFY, sent|defwinproc|optional },
{ TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
{ TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
{ TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
@ -370,14 +374,9 @@ static HWND createParentWindow(void)
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);
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
static LONG defwndproc_counter = 0;
LRESULT ret;
struct message msg;
@ -402,7 +401,7 @@ static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam,
}
defwndproc_counter++;
ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
defwndproc_counter--;
return ret;
@ -412,14 +411,10 @@ static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT
{
HWND tabHandle;
TCITEM tcNewTab;
struct subclass_info *info;
WNDPROC oldproc;
RECT rect;
INT i;
info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
if (!info)
return NULL;
GetClientRect(parent_wnd, &rect);
tabHandle = CreateWindow (
@ -431,8 +426,8 @@ static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT
assert(tabHandle);
info->oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tabSubclassProcess);
SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)info);
oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tabSubclassProcess);
SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)oldproc);
tcNewTab.mask = mask;
@ -505,7 +500,7 @@ static void test_tab(INT nMinTabWidth)
SIZE size;
HDC hdc;
HFONT hOldFont;
INT i, dpi;
INT i, dpi, exp;
hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
@ -585,8 +580,11 @@ static void test_tab(INT nMinTabWidth)
SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
trace (" non fixed width, with text...\n");
CheckSize(hwTab, max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth), -1,
"no icon, default width");
exp = max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth);
SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == DEFAULT_MIN_TAB_WIDTH),
"no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
for (i=0; i<8; i++)
{
INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
@ -610,7 +608,11 @@ static void test_tab(INT nMinTabWidth)
SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
trace (" non fixed width, no text...\n");
CheckSize(hwTab, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth, -1, "no icon, default width");
exp = (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth;
SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == DEFAULT_MIN_TAB_WIDTH),
"no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
for (i=0; i<8; i++)
{
INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
@ -636,7 +638,290 @@ static void test_tab(INT nMinTabWidth)
DeleteObject(hFont);
}
static void test_getters_setters(HWND parent_wnd, INT nTabs)
static void test_curfocus(HWND parent_wnd, INT nTabs)
{
INT focusIndex;
HWND hTab;
hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
ok(hTab != NULL, "Failed to create tab control\n");
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);
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);
DestroyWindow(hTab);
}
static void test_cursel(HWND parent_wnd, INT nTabs)
{
INT selectionIndex;
INT focusIndex;
TCITEM tcItem;
HWND hTab;
hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
ok(hTab != NULL, "Failed to create tab control\n");
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* Testing CurSel with largest appropriate value */
selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs-1, 0);
expect(0, 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);
/* selected item should have TCIS_BUTTONPRESSED state
It doesn't depend on button state */
memset(&tcItem, 0, sizeof(TCITEM));
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_BUTTONPRESSED;
selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
SendMessage(hTab, TCM_GETITEM, selectionIndex, (LPARAM) &tcItem);
ok (tcItem.dwState & TCIS_BUTTONPRESSED || broken(tcItem.dwState == 0), /* older comctl32 */
"Selected item should have TCIS_BUTTONPRESSED\n");
DestroyWindow(hTab);
}
static void test_extendedstyle(HWND parent_wnd, INT nTabs)
{
DWORD prevExtendedStyle;
DWORD extendedStyle;
HWND hTab;
hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
ok(hTab != NULL, "Failed to create tab control\n");
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);
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);
DestroyWindow(hTab);
}
static void test_unicodeformat(HWND parent_wnd, INT nTabs)
{
INT unicodeFormat;
HWND hTab;
hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
ok(hTab != NULL, "Failed to create tab control\n");
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);
DestroyWindow(hTab);
}
static void test_getset_item(HWND parent_wnd, INT nTabs)
{
TCITEM tcItem;
DWORD ret;
char szText[32] = "New Label";
HWND hTab;
hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
ok(hTab != NULL, "Failed to create tab control\n");
/* passing invalid index should result in initialization to zero
for members mentioned in mask requested */
/* valid range here is [0,4] */
memset(&tcItem, 0xcc, sizeof(tcItem));
tcItem.mask = TCIF_PARAM;
ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
expect(FALSE, ret);
ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
memset(&tcItem, 0xcc, sizeof(tcItem));
tcItem.mask = TCIF_IMAGE;
ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
expect(FALSE, ret);
expect(0, tcItem.iImage);
memset(&tcItem, 0xcc, sizeof(tcItem));
tcItem.mask = TCIF_TEXT;
tcItem.pszText = szText;
szText[0] = 'a';
ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
expect(FALSE, ret);
expect('a', szText[0]);
memset(&tcItem, 0xcc, sizeof(tcItem));
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = 0;
tcItem.dwState = TCIS_BUTTONPRESSED;
ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
expect(FALSE, ret);
ok(tcItem.dwState == 0, "Expected zero dwState, got %u\n", tcItem.dwState);
memset(&tcItem, 0xcc, sizeof(tcItem));
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_BUTTONPRESSED;
tcItem.dwState = TCIS_BUTTONPRESSED;
ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
expect(FALSE, ret);
ok(tcItem.dwState == 0, "Expected zero dwState\n");
/* check with negative index to be sure */
memset(&tcItem, 0xcc, sizeof(tcItem));
tcItem.mask = TCIF_PARAM;
ret = SendMessage(hTab, TCM_GETITEM, -1, (LPARAM)&tcItem);
expect(FALSE, ret);
ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
memset(&tcItem, 0xcc, sizeof(tcItem));
tcItem.mask = TCIF_PARAM;
ret = SendMessage(hTab, TCM_GETITEM, -2, (LPARAM)&tcItem);
expect(FALSE, ret);
ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
tcItem.mask = TCIF_TEXT;
tcItem.pszText = &szText[0];
tcItem.cchTextMax = sizeof(szText);
strcpy(szText, "New Label");
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);
/* TCIS_BUTTONPRESSED doesn't depend on tab style */
memset(&tcItem, 0, sizeof(tcItem));
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_BUTTONPRESSED;
tcItem.dwState = TCIS_BUTTONPRESSED;
ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
tcItem.dwState = 0;
ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
if (tcItem.dwState)
{
ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
/* next highlight item, test that dwStateMask actually masks */
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_HIGHLIGHTED;
tcItem.dwState = TCIS_HIGHLIGHTED;
ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
tcItem.dwState = 0;
ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
ok (tcItem.dwState == TCIS_HIGHLIGHTED, "TCIS_HIGHLIGHTED should be set.\n");
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_BUTTONPRESSED;
tcItem.dwState = 0;
ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
}
else win_skip( "Item state mask not supported\n" );
DestroyWindow(hTab);
}
static void test_getset_tooltips(HWND parent_wnd, INT nTabs)
{
HWND hTab, toolTip;
char toolTipText[32] = "ToolTip Text Test";
hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
ok(hTab != NULL, "Failed to create tab control\n");
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, 0, 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_misc(HWND parent_wnd, INT nTabs)
{
HWND hTab;
RECT rTab;
@ -694,196 +979,6 @@ static void test_getters_setters(HWND parent_wnd, INT nTabs)
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;
TCITEM tcItem;
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);
/* selected item should have TCIS_BUTTONPRESSED state
It doesn't depend on button state */
memset(&tcItem, 0, sizeof(TCITEM));
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_BUTTONPRESSED;
selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
SendMessage(hTab, TCM_GETITEM, selectionIndex, (LPARAM) &tcItem);
ok (tcItem.dwState & TCIS_BUTTONPRESSED, "Selected item should have TCIS_BUTTONPRESSED\n");
}
/* 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);
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);
/* TCIS_BUTTONPRESSED doesn't depend on tab style */
memset(&tcItem, 0, sizeof(tcItem));
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_BUTTONPRESSED;
tcItem.dwState = TCIS_BUTTONPRESSED;
ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
tcItem.dwState = 0;
ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
/* next highlight item, test that dwStateMask actually masks */
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_HIGHLIGHTED;
tcItem.dwState = TCIS_HIGHLIGHTED;
ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
tcItem.dwState = 0;
ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
ok (tcItem.dwState == TCIS_HIGHLIGHTED, "TCIS_HIGHLIGHTED should be set.\n");
tcItem.mask = TCIF_STATE;
tcItem.dwStateMask = TCIS_BUTTONPRESSED;
tcItem.dwState = 0;
ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
}
/* 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, 0, 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);
}
@ -903,6 +998,7 @@ static void test_adjustrect(HWND parent_wnd)
r = SendMessage(hTab, TCM_ADJUSTRECT, TRUE, 0);
expect(-1, r);
}
static void test_insert_focus(HWND parent_wnd)
{
HWND hTab;
@ -960,8 +1056,8 @@ static void test_insert_focus(HWND parent_wnd)
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);
ok_sequence(sequences, TAB_SEQ_INDEX, insert_focus_seq, "insert_focus test sequence", FALSE);
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "insert_focus parent test sequence", TRUE);
DestroyWindow(hTab);
}
@ -1010,7 +1106,7 @@ static void test_delete_focus(HWND parent_wnd)
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);
ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "delete_focus parent test sequence", TRUE);
DestroyWindow(hTab);
}
@ -1078,6 +1174,28 @@ static void test_removeimage(HWND parent_wnd)
DestroyIcon(hicon);
}
static void test_delete_selection(HWND parent_wnd)
{
HWND hTab;
DWORD ret;
hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
ok(hTab != NULL, "Failed to create tab control\n");
ret = SendMessage(hTab, TCM_SETCURSEL, 3, 0);
expect(0, ret);
ret = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
expect(3, ret);
/* delete selected item - selection goes to -1 */
ret = SendMessage(hTab, TCM_DELETEITEM, 3, 0);
expect(TRUE, ret);
ret = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
expect(-1, ret);
DestroyWindow(hTab);
}
START_TEST(tab)
{
HWND parent_wnd;
@ -1108,13 +1226,19 @@ START_TEST(tab)
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_curfocus(parent_wnd, 5);
test_cursel(parent_wnd, 5);
test_extendedstyle(parent_wnd, 5);
test_unicodeformat(parent_wnd, 5);
test_getset_item(parent_wnd, 5);
test_getset_tooltips(parent_wnd, 5);
test_misc(parent_wnd, 5);
test_adjustrect(parent_wnd);
test_insert_focus(parent_wnd);
test_delete_focus(parent_wnd);
test_delete_selection(parent_wnd);
test_removeimage(parent_wnd);
DestroyWindow(parent_wnd);

View file

@ -15,7 +15,6 @@ 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);
@ -40,7 +39,6 @@ const struct test winetest_testlist[] =
{ "misc", func_misc },
{ "monthcal", func_monthcal },
{ "mru", func_mru },
{ "msg", func_msg },
{ "progress", func_progress },
{ "propsheet", func_propsheet },
{ "rebar", func_rebar },

View file

@ -33,12 +33,27 @@
#include "wine/test.h"
#include "msg.h"
#define PARENT_SEQ_INDEX 0
#define NUM_MSG_SEQUENCES 1
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
static HWND hMainWnd;
static BOOL g_fBlockHotItemChange;
static BOOL g_fReceivedHotItemChange;
static BOOL g_fExpectedHotItemOld;
static BOOL g_fExpectedHotItemNew;
static DWORD g_dwExpectedDispInfoMask;
static BOOL g_ResetDispTextPtr;
static const struct message ttgetdispinfo_parent_seq[] = {
{ WM_NOTIFY, sent|id, 0, 0, TBN_GETINFOTIPA },
/* next line is todo, currently TTN_GETDISPINFOW is raised here */
{ WM_NOTIFY, sent|id, 0, 0, TTN_GETDISPINFOA },
{ 0 }
};
#define expect(EXPECTED,GOT) ok((GOT)==(EXPECTED), "Expected %d, got %d\n", (EXPECTED), (GOT))
@ -56,7 +71,7 @@ static void MakeButton(TBBUTTON *p, int idCommand, int fsStyle, int nString) {
p->iString = nString;
}
static LRESULT MyWnd_Notify(LPARAM lParam)
static LRESULT parent_wnd_notify(LPARAM lParam)
{
NMHDR *hdr = (NMHDR *)lParam;
NMTBHOTITEM *nmhi;
@ -79,25 +94,65 @@ static LRESULT MyWnd_Notify(LPARAM lParam)
ok(FALSE, "TBN_GETDISPINFOA received\n");
break;
case TBN_GETINFOTIPA:
{
NMTBGETINFOTIPA *tbgit = (NMTBGETINFOTIPA*)lParam;
if (g_ResetDispTextPtr)
{
tbgit->pszText = NULL;
return 0;
}
break;
}
case TBN_GETDISPINFOW:
nmdisp = (NMTBDISPINFOA *)lParam;
compare(nmdisp->dwMask, g_dwExpectedDispInfoMask, "%x");
compare(nmdisp->iImage, -1, "%d");
ok(nmdisp->pszText == NULL, "pszText is not NULL\n");
break;
}
return 0;
}
static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (msg)
static LONG defwndproc_counter = 0;
struct message msg;
LRESULT ret;
msg.message = message;
msg.flags = sent|wparam|lparam;
if (defwndproc_counter) msg.flags |= defwinproc;
msg.wParam = wParam;
msg.lParam = lParam;
if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
/* log system messages, except for painting */
if (message < WM_USER &&
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);
add_message(sequences, PARENT_SEQ_INDEX, &msg);
}
switch (message)
{
case WM_NOTIFY:
return MyWnd_Notify(lParam);
return parent_wnd_notify(lParam);
}
return DefWindowProcA(hWnd, msg, wParam, lParam);
defwndproc_counter++;
ret = DefWindowProcA(hWnd, message, wParam, lParam);
defwndproc_counter--;
return ret;
}
static void basic_test(void)
@ -163,7 +218,7 @@ static void basic_test(void)
static void rebuild_toolbar(HWND *hToolbar)
{
if (*hToolbar != NULL)
if (*hToolbar)
DestroyWindow(*hToolbar);
*hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
hMainWnd, (HMENU)5, GetModuleHandle(NULL), NULL);
@ -374,6 +429,8 @@ static void test_add_bitmap(void)
addbmp.hInst = HINST_COMMCTRL;
addbmp.nID = IDB_STD_SMALL_COLOR;
rebuild_toolbar(&hToolbar);
ImageList_Destroy(himl);
ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
CHECK_IMAGELIST(15, 16, 16);
compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(23, 22), "%x");
@ -415,7 +472,7 @@ static void test_add_bitmap(void)
ok(strcmp(_buf, (tab)[_i]) == 0, "Invalid string #%d - '%s' vs '%s'\n", _i, (tab)[_i], _buf); \
} \
ok(SendMessageA(hToolbar, TB_GETSTRING, MAKEWPARAM(260, (count)), (LPARAM)_buf) == -1, \
"Too many string in table\n"); \
"Too many strings in table\n"); \
}
static void test_add_string(void)
@ -432,10 +489,17 @@ static void test_add_string(void)
HWND hToolbar = NULL;
TBBUTTON button;
int ret;
CHAR buf[260];
rebuild_toolbar(&hToolbar);
ret = SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)test1);
ok(ret == 0, "TB_ADDSTRINGA - unexpected return %d\n", ret);
ret = SendMessageA(hToolbar, TB_GETSTRING, MAKEWPARAM(260, 1), (LPARAM)buf);
if (ret == 0)
{
win_skip("TB_GETSTRING needs 5.80\n");
return;
}
CHECK_STRING_TABLE(2, ret1);
ret = SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)test2);
ok(ret == 2, "TB_ADDSTRINGA - unexpected return %d\n", ret);
@ -734,6 +798,22 @@ static tbsize_result_t tbsize_results[] =
static int tbsize_numtests = 0;
typedef struct
{
int test_num;
int rect_index;
RECT rcButton;
} tbsize_alt_result_t;
static tbsize_alt_result_t tbsize_alt_results[] =
{
{ 5, 2, { 0, 24, 8, 29 } },
{ 20, 1, { 100, 2, 107, 102 } },
{ 20, 2, { 107, 2, 207, 102 } }
};
static int tbsize_alt_numtests = 0;
#define check_sizes_todo(todomask) { \
RECT rc; \
int buttonCount, i, mask=(todomask); \
@ -745,7 +825,11 @@ static int tbsize_numtests = 0;
compare(buttonCount, res->nButtons, "%d"); \
for (i=0; i<min(buttonCount, res->nButtons); i++) { \
ok(SendMessageA(hToolbar, TB_GETITEMRECT, i, (LPARAM)&rc) == 1, "TB_GETITEMRECT\n"); \
if (!(mask&1)) { \
if (broken(tbsize_alt_numtests < sizeof(tbsize_alt_results)/sizeof(tbsize_alt_results[0]) && \
memcmp(&rc, &tbsize_alt_results[tbsize_alt_numtests].rcButton, sizeof(RECT)) == 0)) { \
win_skip("Alternate rect found\n"); \
tbsize_alt_numtests++; \
} else if (!(mask&1)) { \
check_rect("button", rc, res->rcButtons[i]); \
} else {\
todo_wine { check_rect("button", rc, res->rcButtons[i]); } \
@ -954,6 +1038,7 @@ static void test_sizes(void)
rebuild_toolbar(&hToolbar);
ImageList_Destroy(himl);
ImageList_Destroy(himl2);
SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[3]);
ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 39), "Unexpected button size\n");
@ -995,10 +1080,17 @@ static void test_sizes(void)
tbinfo.cx = 672;
tbinfo.cbSize = sizeof(TBBUTTONINFO);
tbinfo.dwMask = TBIF_SIZE | TBIF_BYINDEX;
ok(SendMessageA(hToolbar, TB_SETBUTTONINFO, 0, (LPARAM)&tbinfo) != 0, "TB_SETBUTTONINFO failed\n");
ok(SendMessageA(hToolbar, TB_SETBUTTONINFO, 1, (LPARAM)&tbinfo) != 0, "TB_SETBUTTONINFO failed\n");
SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0);
check_sizes();
if (SendMessageA(hToolbar, TB_SETBUTTONINFO, 0, (LPARAM)&tbinfo))
{
ok(SendMessageA(hToolbar, TB_SETBUTTONINFO, 1, (LPARAM)&tbinfo) != 0, "TB_SETBUTTONINFO failed\n");
SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0);
check_sizes();
}
else /* TBIF_BYINDEX probably not supported, confirm that this was the reason for the failure */
{
tbinfo.dwMask = TBIF_SIZE;
ok(SendMessageA(hToolbar, TB_SETBUTTONINFO, 33, (LPARAM)&tbinfo) != 0, "TB_SETBUTTONINFO failed\n");
}
DestroyWindow(hToolbar);
}
@ -1049,21 +1141,24 @@ static void restore_recalc_state(HWND hToolbar)
static void test_recalc(void)
{
HWND hToolbar;
HWND hToolbar = NULL;
TBBUTTONINFO bi;
CHAR test[] = "Test";
const int EX_STYLES_COUNT = 5;
int i;
BOOL recalc;
/* Like TB_ADDBUTTONS tested in test_sized, inserting a button without text
* results in a relayout, while adding one with text forces a recalc */
prepare_recalc_test(&hToolbar);
SendMessage(hToolbar, TB_INSERTBUTTON, 1, (LPARAM)&buttons3[0]);
ok(!did_recalc(hToolbar), "Unexpected recalc - adding button without text\n");
recalc = did_recalc(hToolbar);
ok(!recalc, "Unexpected recalc - adding button without text\n");
prepare_recalc_test(&hToolbar);
SendMessage(hToolbar, TB_INSERTBUTTON, 1, (LPARAM)&buttons3[3]);
ok(did_recalc(hToolbar), "Expected a recalc - adding button with text\n");
recalc = did_recalc(hToolbar);
ok(recalc, "Expected a recalc - adding button with text\n");
/* TB_SETBUTTONINFO, even when adding a text, results only in a relayout */
prepare_recalc_test(&hToolbar);
@ -1071,7 +1166,8 @@ static void test_recalc(void)
bi.dwMask = TBIF_TEXT;
bi.pszText = test;
SendMessage(hToolbar, TB_SETBUTTONINFO, 1, (LPARAM)&bi);
ok(!did_recalc(hToolbar), "Unexpected recalc - setting a button text\n");
recalc = did_recalc(hToolbar);
ok(!recalc, "Unexpected recalc - setting a button text\n");
/* most extended styled doesn't force a recalc (testing all the bits gives
* the same results, but prints some ERRs while testing) */
@ -1082,22 +1178,31 @@ static void test_recalc(void)
prepare_recalc_test(&hToolbar);
expect(0, (int)SendMessage(hToolbar, TB_GETEXTENDEDSTYLE, 0, 0));
SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, (1 << i));
ok(!did_recalc(hToolbar), "Unexpected recalc - setting bit %d\n", i);
recalc = did_recalc(hToolbar);
ok(!recalc, "Unexpected recalc - setting bit %d\n", i);
SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, 0);
ok(!did_recalc(hToolbar), "Unexpected recalc - clearing bit %d\n", i);
recalc = did_recalc(hToolbar);
ok(!recalc, "Unexpected recalc - clearing bit %d\n", i);
expect(0, (int)SendMessage(hToolbar, TB_GETEXTENDEDSTYLE, 0, 0));
}
/* TBSTYLE_EX_MIXEDBUTTONS does a recalc on change */
prepare_recalc_test(&hToolbar);
SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
ok(did_recalc(hToolbar), "Expected a recalc - setting TBSTYLE_EX_MIXEDBUTTONS\n");
restore_recalc_state(hToolbar);
SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
ok(!did_recalc(hToolbar), "Unexpected recalc - setting TBSTYLE_EX_MIXEDBUTTONS again\n");
restore_recalc_state(hToolbar);
SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, 0);
ok(did_recalc(hToolbar), "Expected a recalc - clearing TBSTYLE_EX_MIXEDBUTTONS\n");
recalc = did_recalc(hToolbar);
if (recalc)
{
ok(recalc, "Expected a recalc - setting TBSTYLE_EX_MIXEDBUTTONS\n");
restore_recalc_state(hToolbar);
SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS);
recalc = did_recalc(hToolbar);
ok(!recalc, "Unexpected recalc - setting TBSTYLE_EX_MIXEDBUTTONS again\n");
restore_recalc_state(hToolbar);
SendMessage(hToolbar, TB_SETEXTENDEDSTYLE, 0, 0);
recalc = did_recalc(hToolbar);
ok(recalc, "Expected a recalc - clearing TBSTYLE_EX_MIXEDBUTTONS\n");
}
else win_skip( "No recalc on TBSTYLE_EX_MIXEDBUTTONS\n" );
/* undocumented exstyle 0x2 seems to changes the top margin, what
* interferes with these tests */
@ -1117,8 +1222,8 @@ static void test_getbuttoninfo(void)
int ret;
tbi.cbSize = i;
tbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
ret = (int)SendMessage(hToolbar, TB_GETBUTTONINFO, 0, (LPARAM)&tbi);
tbi.dwMask = TBIF_COMMAND;
ret = (int)SendMessage(hToolbar, TB_GETBUTTONINFO, 1, (LPARAM)&tbi);
if (i == sizeof(TBBUTTONINFO)) {
compare(ret, 0, "%d");
} else {
@ -1189,7 +1294,7 @@ static void test_dispinfo(void)
rebuild_toolbar(&hToolbar);
SendMessageA(hToolbar, TB_LOADIMAGES, IDB_HIST_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons_disp);
g_dwExpectedDispInfoMask = 1;
g_dwExpectedDispInfoMask = TBNF_IMAGE;
/* Some TBN_GETDISPINFO tests will be done in MyWnd_Notify function.
* We will receive TBN_GETDISPINFOW even if the control is ANSI */
compare((BOOL)SendMessageA(hToolbar, CCM_GETUNICODEFORMAT, 0, 0), 0, "%d");
@ -1281,6 +1386,12 @@ static void test_getstring(void)
ok(hToolbar != NULL, "Toolbar creation problem\n");
r = SendMessage(hToolbar, TB_GETSTRING, MAKEWPARAM(0, 0), 0);
if (r == 0)
{
win_skip("TB_GETSTRING and TB_GETSTRINGW need 5.80\n");
DestroyWindow(hToolbar);
return;
}
expect(-1, r);
r = SendMessage(hToolbar, TB_GETSTRINGW, MAKEWPARAM(0, 0), 0);
expect(-1, r);
@ -1300,12 +1411,46 @@ static void test_getstring(void)
DestroyWindow(hToolbar);
}
static void test_tooltip(void)
{
HWND hToolbar = NULL;
const TBBUTTON buttons_disp[] = {
{-1, 20, TBSTATE_ENABLED, 0, {0, }, 0, -1},
{0, 21, TBSTATE_ENABLED, 0, {0, }, 0, -1},
};
NMTTDISPINFOW nmtti;
rebuild_toolbar(&hToolbar);
SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons_disp);
/* W used to get through toolbar code that assumes tooltip is always Unicode */
memset(&nmtti, 0, sizeof(nmtti));
nmtti.hdr.code = TTN_GETDISPINFOW;
nmtti.hdr.idFrom = 20;
SendMessageA(hToolbar, CCM_SETUNICODEFORMAT, FALSE, 0);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
SendMessageA(hToolbar, WM_NOTIFY, 0, (LPARAM)&nmtti);
ok_sequence(sequences, PARENT_SEQ_INDEX, ttgetdispinfo_parent_seq,
"dispinfo from tooltip", TRUE);
g_ResetDispTextPtr = TRUE;
SendMessageA(hToolbar, WM_NOTIFY, 0, (LPARAM)&nmtti);
g_ResetDispTextPtr = FALSE;
DestroyWindow(hToolbar);
}
START_TEST(toolbar)
{
WNDCLASSA wc;
MSG msg;
RECT rc;
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
InitCommonControls();
wc.style = CS_HREDRAW | CS_VREDRAW;
@ -1316,11 +1461,11 @@ START_TEST(toolbar)
wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyTestWnd";
wc.lpfnWndProc = MyWndProc;
wc.lpszClassName = "Toolbar test parent";
wc.lpfnWndProc = parent_wnd_proc;
RegisterClassA(&wc);
hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
hMainWnd = CreateWindowExA(0, "Toolbar test parent", "Blah", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
GetClientRect(hMainWnd, &rc);
ShowWindow(hMainWnd, SW_SHOW);
@ -1336,6 +1481,7 @@ START_TEST(toolbar)
test_dispinfo();
test_setrows();
test_getstring();
test_tooltip();
PostQuitMessage(0);
while(GetMessageA(&msg,0,0,0)) {

View file

@ -23,6 +23,8 @@
#include "wine/test.h"
#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
static void test_create_tooltip(void)
{
HWND parent, hwnd;
@ -42,7 +44,8 @@ static void test_create_tooltip(void)
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 %08x/%08x\n", style, exp_style);
ok(style == exp_style || broken(style == (exp_style | WS_BORDER)), /* nt4 */
"wrong style %08x/%08x\n", style, exp_style);
DestroyWindow(hwnd);
@ -142,7 +145,6 @@ static void test_customdraw(void) {
/* Invalid notification responses */
{CDRF_NOTIFYITEMDRAW, TEST_CDDS_PREPAINT},
{CDRF_NOTIFYPOSTERASE, TEST_CDDS_PREPAINT},
{CDRF_NOTIFYSUBITEMDRAW, TEST_CDDS_PREPAINT},
{CDRF_NEWFONT, TEST_CDDS_PREPAINT}
};
@ -168,6 +170,7 @@ static void test_customdraw(void) {
iterationNumber++) {
HWND parent, hwndTip;
RECT rect;
TOOLINFO toolInfo = { 0 };
/* Create a main window */
@ -201,7 +204,7 @@ static void test_customdraw(void) {
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
/* Create a tool */
toolInfo.cbSize = sizeof(TOOLINFO);
toolInfo.cbSize = TTTOOLINFO_V1_SIZE;
toolInfo.hwnd = parent;
toolInfo.hinst = GetModuleHandleA(NULL);
toolInfo.uFlags = TTF_SUBCLASS;
@ -216,13 +219,18 @@ static void test_customdraw(void) {
SendMessage(hwndTip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0));
/* Put cursor inside window, tooltip will appear immediately */
SetCursorPos(100, 100);
GetWindowRect( parent, &rect );
SetCursorPos( (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 );
flush_events(200);
/* Check CustomDraw results */
ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls,
"CustomDraw run %d stages %x, expected %x\n", iterationNumber, CD_Stages,
expectedResults[iterationNumber].ExpectedCalls);
if (CD_Stages)
{
/* Check CustomDraw results */
ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls ||
broken(CD_Stages == (expectedResults[iterationNumber].ExpectedCalls & ~TEST_CDDS_POSTPAINT)), /* nt4 */
"CustomDraw run %d stages %x, expected %x\n", iterationNumber, CD_Stages,
expectedResults[iterationNumber].ExpectedCalls);
}
/* Clean up */
DestroyWindow(hwndTip);
@ -232,14 +240,63 @@ static void test_customdraw(void) {
}
static const CHAR testcallbackA[] = "callback";
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_NOTIFY && lParam)
{
NMTTDISPINFOA *ttnmdi = (NMTTDISPINFOA*)lParam;
if (ttnmdi->hdr.code == TTN_GETDISPINFOA)
lstrcpy(ttnmdi->lpszText, testcallbackA);
}
return DefWindowProcA(hwnd, message, wParam, lParam);
}
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, IDC_ARROW);
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
cls.lpszMenuName = NULL;
cls.lpszClassName = "Tooltips test parent class";
return RegisterClassA(&cls);
}
static HWND create_parent_window(void)
{
if (!register_parent_wnd_class())
return NULL;
return CreateWindowEx(0, "Tooltips test parent class",
"Tooltips test parent window",
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
WS_MAXIMIZEBOX | WS_VISIBLE,
0, 0, 100, 100,
GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
}
static void test_gettext(void)
{
HWND hwnd;
HWND hwnd, notify;
TTTOOLINFOA toolinfoA;
TTTOOLINFOW toolinfoW;
LRESULT r;
char bufA[10] = "";
CHAR bufA[10] = "";
WCHAR bufW[10] = { 0 };
static const CHAR testtipA[] = "testtip";
notify = create_parent_window();
ok(notify != NULL, "Expected notification window to be created\n");
/* For bug 14790 - lpszText is NULL */
hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
@ -247,6 +304,8 @@ static void test_gettext(void)
NULL, NULL, NULL, 0);
assert(hwnd);
/* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
/* otherwise it crashes on the NULL lpszText */
toolinfoA.cbSize = sizeof(TTTOOLINFOA);
toolinfoA.hwnd = NULL;
toolinfoA.hinst = GetModuleHandleA(NULL);
@ -256,7 +315,6 @@ static void test_gettext(void)
toolinfoA.lParam = 0xdeadbeef;
GetClientRect(hwnd, &toolinfoA.rect);
r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
ok(r, "Adding the tool to the tooltip failed\n");
if (r)
{
toolinfoA.hwnd = NULL;
@ -265,8 +323,65 @@ static void test_gettext(void)
SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
ok(strcmp(toolinfoA.lpszText, "") == 0, "lpszText should be an empty string\n");
}
else
{
win_skip( "Old comctl32, not testing NULL text\n" );
DestroyWindow( hwnd );
return;
}
/* add another tool with text */
toolinfoA.cbSize = sizeof(TTTOOLINFOA);
toolinfoA.hwnd = NULL;
toolinfoA.hinst = GetModuleHandleA(NULL);
toolinfoA.uFlags = 0;
toolinfoA.uId = 0x1235ABCD;
strcpy(bufA, testtipA);
toolinfoA.lpszText = bufA;
toolinfoA.lParam = 0xdeadbeef;
GetClientRect(hwnd, &toolinfoA.rect);
r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
ok(r, "Adding the tool to the tooltip failed\n");
if (r)
{
DWORD length;
length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
ok(length == 0, "Expected 0, got %d\n", length);
toolinfoA.hwnd = NULL;
toolinfoA.uId = 0x1235ABCD;
toolinfoA.lpszText = bufA;
SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
ok(strcmp(toolinfoA.lpszText, testtipA) == 0, "lpszText should be an empty string\n");
length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
ok(length == 0, "Expected 0, got %d\n", length);
}
/* add another with callback text */
toolinfoA.cbSize = sizeof(TTTOOLINFOA);
toolinfoA.hwnd = notify;
toolinfoA.hinst = GetModuleHandleA(NULL);
toolinfoA.uFlags = 0;
toolinfoA.uId = 0x1236ABCD;
toolinfoA.lpszText = LPSTR_TEXTCALLBACKA;
toolinfoA.lParam = 0xdeadbeef;
GetClientRect(hwnd, &toolinfoA.rect);
r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
ok(r, "Adding the tool to the tooltip failed\n");
if (r)
{
toolinfoA.hwnd = notify;
toolinfoA.uId = 0x1236ABCD;
toolinfoA.lpszText = bufA;
SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
ok(strcmp(toolinfoA.lpszText, testcallbackA) == 0,
"lpszText should be an (%s) string\n", testcallbackA);
}
DestroyWindow(hwnd);
DestroyWindow(notify);
SetLastError(0xdeadbeef);
hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
@ -303,6 +418,208 @@ static void test_gettext(void)
DestroyWindow(hwnd);
}
static void test_ttm_gettoolinfo(void)
{
TTTOOLINFOA ti;
TTTOOLINFOW tiW;
HWND hwnd;
DWORD r;
hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
10, 10, 300, 100,
NULL, NULL, NULL, 0);
ti.cbSize = TTTOOLINFOA_V2_SIZE;
ti.hwnd = NULL;
ti.hinst = GetModuleHandleA(NULL);
ti.uFlags = 0;
ti.uId = 0x1234ABCD;
ti.lpszText = NULL;
ti.lParam = 0xdeadbeef;
GetClientRect(hwnd, &ti.rect);
r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
ok(r, "Adding the tool to the tooltip failed\n");
ti.cbSize = TTTOOLINFOA_V2_SIZE;
ti.lParam = 0xaaaaaaaa;
r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
ok(r, "Getting tooltip info failed\n");
ok(0xdeadbeef == ti.lParam ||
broken(0xdeadbeef != ti.lParam), /* comctl32 < 5.81 */
"Expected 0xdeadbeef, got %lx\n", ti.lParam);
tiW.cbSize = TTTOOLINFOW_V2_SIZE;
tiW.hwnd = NULL;
tiW.uId = 0x1234ABCD;
tiW.lParam = 0xaaaaaaaa;
r = SendMessageA(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&tiW);
ok(r, "Getting tooltip info failed\n");
ok(0xdeadbeef == tiW.lParam ||
broken(0xdeadbeef != tiW.lParam), /* comctl32 < 5.81 */
"Expected 0xdeadbeef, got %lx\n", tiW.lParam);
ti.cbSize = TTTOOLINFOA_V2_SIZE;
ti.uId = 0x1234ABCD;
ti.lParam = 0xaaaaaaaa;
SendMessageA(hwnd, TTM_SETTOOLINFOA, 0, (LPARAM)&ti);
ti.cbSize = TTTOOLINFOA_V2_SIZE;
ti.lParam = 0xdeadbeef;
r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
ok(r, "Getting tooltip info failed\n");
ok(0xaaaaaaaa == ti.lParam ||
broken(0xaaaaaaaa != ti.lParam), /* comctl32 < 5.81 */
"Expected 0xaaaaaaaa, got %lx\n", ti.lParam);
DestroyWindow(hwnd);
/* 1. test size parameter validation rules (ansi messages) */
hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
10, 10, 300, 100,
NULL, NULL, NULL, 0);
ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
ti.hwnd = NULL;
ti.hinst = GetModuleHandleA(NULL);
ti.uFlags = 0;
ti.uId = 0x1234ABCD;
ti.lpszText = NULL;
ti.lParam = 0xdeadbeef;
GetClientRect(hwnd, &ti.rect);
r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
ok(r, "Adding the tool to the tooltip failed\n");
r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(1, r);
ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
ti.hwnd = NULL;
ti.uId = 0x1234ABCD;
SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(0, r);
ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
ti.hwnd = NULL;
ti.hinst = GetModuleHandleA(NULL);
ti.uFlags = 0;
ti.uId = 0x1234ABCD;
ti.lpszText = NULL;
ti.lParam = 0xdeadbeef;
GetClientRect(hwnd, &ti.rect);
r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
ok(r, "Adding the tool to the tooltip failed\n");
r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(1, r);
ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
ti.hwnd = NULL;
ti.uId = 0x1234ABCD;
SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(0, r);
ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
ti.hwnd = NULL;
ti.hinst = GetModuleHandleA(NULL);
ti.uFlags = 0;
ti.uId = 0x1234ABCD;
ti.lpszText = NULL;
ti.lParam = 0xdeadbeef;
GetClientRect(hwnd, &ti.rect);
r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
ok(r, "Adding the tool to the tooltip failed\n");
r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(1, r);
ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
ti.hwnd = NULL;
ti.uId = 0x1234ABCD;
SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(0, r);
DestroyWindow(hwnd);
/* 2. test size parameter validation rules (w-messages) */
hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
10, 10, 300, 100,
NULL, NULL, NULL, 0);
if(!hwnd)
{
win_skip("CreateWindowExW() not supported. Skipping.\n");
return;
}
tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
tiW.hwnd = NULL;
tiW.hinst = GetModuleHandleA(NULL);
tiW.uFlags = 0;
tiW.uId = 0x1234ABCD;
tiW.lpszText = NULL;
tiW.lParam = 0xdeadbeef;
GetClientRect(hwnd, &tiW.rect);
r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
ok(r, "Adding the tool to the tooltip failed\n");
r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(1, r);
tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
tiW.hwnd = NULL;
tiW.uId = 0x1234ABCD;
SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(0, r);
tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
tiW.hwnd = NULL;
tiW.hinst = GetModuleHandleA(NULL);
tiW.uFlags = 0;
tiW.uId = 0x1234ABCD;
tiW.lpszText = NULL;
tiW.lParam = 0xdeadbeef;
GetClientRect(hwnd, &tiW.rect);
r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
ok(r, "Adding the tool to the tooltip failed\n");
r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(1, r);
tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
tiW.hwnd = NULL;
tiW.uId = 0x1234ABCD;
SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(0, r);
tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
tiW.hwnd = NULL;
tiW.hinst = GetModuleHandleA(NULL);
tiW.uFlags = 0;
tiW.uId = 0x1234ABCD;
tiW.lpszText = NULL;
tiW.lParam = 0xdeadbeef;
GetClientRect(hwnd, &tiW.rect);
r = SendMessageW(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&tiW);
ok(r, "Adding the tool to the tooltip failed\n");
r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(1, r);
/* looks like TTM_DELTOOLW doesn't work with invalid size */
tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
tiW.hwnd = NULL;
tiW.uId = 0x1234ABCD;
SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(1, r);
tiW.cbSize = TTTOOLINFOW_V2_SIZE;
tiW.hwnd = NULL;
tiW.uId = 0x1234ABCD;
SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
expect(0, r);
DestroyWindow(hwnd);
}
START_TEST(tooltips)
{
InitCommonControls();
@ -310,4 +627,5 @@ START_TEST(tooltips)
test_create_tooltip();
test_customdraw();
test_gettext();
test_ttm_gettoolinfo();
}

View file

@ -30,32 +30,10 @@
#define PARENT_SEQ_INDEX 0
#define TRACKBAR_SEQ_INDEX 1
HWND hWndParent;
static struct msg_sequence *sequences[NUM_MSG_SEQUENCE];
static const struct message create_parent_wnd_seq[] = {
{ WM_GETMINMAXINFO, sent },
{ WM_NCCREATE, sent },
{ WM_NCCALCSIZE, sent|wparam, 0 },
{ WM_CREATE, sent },
{ WM_SHOWWINDOW, sent|wparam, 1 },
{ WM_WINDOWPOSCHANGING, sent|wparam, 0 },
{ WM_QUERYNEWPALETTE, sent|optional },
{ WM_WINDOWPOSCHANGING, sent|wparam, 0 },
{ WM_ACTIVATEAPP, sent|wparam, 1 },
{ WM_NCACTIVATE, sent|wparam, 1 },
{ WM_ACTIVATE, sent|wparam, 1 },
{ WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
{ WM_IME_NOTIFY, sent|defwinproc|optional },
{ WM_SETFOCUS, sent|wparam|defwinproc, 0 },
/* Win9x adds SWP_NOZORDER below */
{ WM_WINDOWPOSCHANGED, sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
{ WM_NCCALCSIZE, sent|wparam|optional, 1 },
{ WM_SIZE, sent },
{ WM_MOVE, sent },
{ 0 }
};
static const struct message create_trackbar_wnd_seq[] = {
{0}
};
@ -81,12 +59,12 @@ static const struct message parent_create_trackbar_wnd_seq[] = {
static const struct message parent_new_window_test_seq[] = {
{ WM_QUERYNEWPALETTE, sent|optional },
{ WM_WINDOWPOSCHANGING, sent},
{ WM_NCACTIVATE, sent},
{ PBT_APMRESUMECRITICAL, sent},
{ WM_WINDOWPOSCHANGING, sent|optional},
{ WM_NCACTIVATE, sent|optional},
{ PBT_APMRESUMECRITICAL, sent|optional},
{ WM_IME_SETCONTEXT, sent|defwinproc|optional},
{ WM_IME_NOTIFY, sent|defwinproc|optional},
{ WM_SETFOCUS, sent|defwinproc},
{ WM_SETFOCUS, sent|defwinproc|optional},
{ WM_NOTIFYFORMAT, sent},
{ WM_QUERYUISTATE, sent|optional},
{0}
@ -386,11 +364,6 @@ static const struct message ignore_selection_test_seq[] = {
{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;
@ -452,7 +425,7 @@ static HWND create_parent_window(void){
}
static LRESULT WINAPI trackbar_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
struct subclass_info *info = (struct subclass_info *) GetWindowLongPtrA(hwnd, GWLP_USERDATA);
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
static LONG defwndproc_counter = 0;
LRESULT ret;
struct message msg;
@ -467,36 +440,27 @@ static LRESULT WINAPI trackbar_subclass_proc(HWND hwnd, UINT message, WPARAM wPa
add_message(sequences, TRACKBAR_SEQ_INDEX, &msg);
defwndproc_counter++;
ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
defwndproc_counter--;
return ret;
}
static HWND create_trackbar(DWORD style, HWND parent){
struct subclass_info *info;
HWND hWndTrack;
WNDPROC oldproc;
RECT rect;
info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
if (!info)
return NULL;
GetClientRect(parent, &rect);
hWndTrack = CreateWindowEx(
0, TRACKBAR_CLASS,"Trackbar Control", style,
rect.right,rect.bottom, 100, 50,
parent, NULL,GetModuleHandleA(NULL) ,NULL);
if (!hWndTrack)
{
HeapFree(GetProcessHeap(), 0, info);
return NULL;
}
if (!hWndTrack) return NULL;
info->oldproc = (WNDPROC)SetWindowLongPtrA(hWndTrack, GWLP_WNDPROC, (LONG_PTR)trackbar_subclass_proc);
SetWindowLongPtrA(hWndTrack, GWLP_USERDATA, (LONG_PTR)info);
oldproc = (WNDPROC)SetWindowLongPtrA(hWndTrack, GWLP_WNDPROC, (LONG_PTR)trackbar_subclass_proc);
SetWindowLongPtrA(hWndTrack, GWLP_USERDATA, (LONG_PTR)oldproc);
return hWndTrack;
}
@ -785,40 +749,63 @@ static void test_thumb_length(HWND hWndTrackbar){
static void test_tic_settings(HWND hWndTrackbar){
int r;
flush_sequences(sequences, NUM_MSG_SEQUENCE);
/* testing TBM_SETTIC */
/* Set tics at 5 and 10 */
/* 0 and 20 are out of range and should not be set */
r = SendMessage(hWndTrackbar, TBM_GETRANGEMAX, 0, 0);
expect(10, r);
r = SendMessage(hWndTrackbar, TBM_GETRANGEMIN, 0, 0);
expect(5, r);
flush_sequences(sequences, NUM_MSG_SEQUENCE);
r = SendMessage(hWndTrackbar, TBM_SETTIC, 0, 0);
ok(r == FALSE, "Expected FALSE, got %d\n", r);
r = SendMessage(hWndTrackbar, TBM_SETTIC, 0, 5);
todo_wine{
ok(r == TRUE, "Expected TRUE, got %d\n", r);
r = SendMessage(hWndTrackbar, TBM_SETTIC, 0, 10);
ok(r == TRUE, "Expected TRUE, got %d\n", r);
}
ok(r == TRUE, "Expected TRUE, got %d\n", r);
r = SendMessage(hWndTrackbar, TBM_SETTIC, 0, 10);
ok(r == TRUE, "Expected TRUE, got %d\n", r);
r = SendMessage(hWndTrackbar, TBM_SETTIC, 0, 20);
ok(r == FALSE, "Expected False, got %d\n", r);
/* test TBM_SETTICFREQ */
SendMessage(hWndTrackbar, TBM_SETRANGE, TRUE, MAKELONG(0, 10));
SendMessage(hWndTrackbar, TBM_SETTICFREQ, 2, 0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0,0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0, 0);
expect(6, r);
SendMessage(hWndTrackbar, TBM_SETTICFREQ, 5, 0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0,0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0, 0);
expect(3, r);
SendMessage(hWndTrackbar, TBM_SETTICFREQ, 15, 0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0,0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0, 0);
expect(2, r);
/* test TBM_GETNUMTICS */
/* since TIC FREQ is 15, there should be only 2 tics now */
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0,0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0, 0);
expect(2, r);
ok_sequence(sequences, TRACKBAR_SEQ_INDEX, tic_settings_test_seq, "tic settings test sequence", TRUE);
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_tic_settings_test_seq, "parent tic settings test sequence", TRUE);
/* range [0,0], freq = 1 */
SendMessage(hWndTrackbar, TBM_SETRANGEMAX, TRUE, 0);
SendMessage(hWndTrackbar, TBM_SETRANGEMIN, TRUE, 0);
SendMessage(hWndTrackbar, TBM_SETTICFREQ, 1, 0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0, 0);
expect(2, r);
/* range [0,1], freq = 1 */
SendMessage(hWndTrackbar, TBM_SETRANGEMAX, TRUE, 1);
SendMessage(hWndTrackbar, TBM_SETRANGEMIN, TRUE, 0);
SendMessage(hWndTrackbar, TBM_SETTICFREQ, 1, 0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0, 0);
expect(2, r);
/* range [0,2], freq = 1 */
SendMessage(hWndTrackbar, TBM_SETRANGEMAX, TRUE, 2);
SendMessage(hWndTrackbar, TBM_SETRANGEMIN, TRUE, 0);
SendMessage(hWndTrackbar, TBM_SETTICFREQ, 1, 0);
r = SendMessage(hWndTrackbar, TBM_GETNUMTICS, 0, 0);
expect(3, r);
}
static void test_tic_placement(HWND hWndTrackbar){
@ -846,9 +833,7 @@ static void test_tic_placement(HWND hWndTrackbar){
r = SendMessage(hWndTrackbar, TBM_GETTIC, 2,0);
expect(4, r);
r = SendMessage(hWndTrackbar, TBM_GETTIC, 4,0);
todo_wine{
expect(-1, r);
}
expect(-1, r);
/* test TBM_GETTICPIC */
r = SendMessage(hWndTrackbar, TBM_GETTICPOS, 0, 0);
@ -869,15 +854,13 @@ static void test_tool_tips(HWND hWndTrackbar){
flush_sequences(sequences, NUM_MSG_SEQUENCE);
/* testing TBM_SETTIPSIDE */
r = SendMessage(hWndTrackbar, TBM_SETTIPSIDE, TBTS_TOP, 0);
todo_wine{
expect(0, r);
}
expect(TBTS_TOP, r);
r = SendMessage(hWndTrackbar, TBM_SETTIPSIDE, TBTS_LEFT, 0);
expect(0, r);
expect(TBTS_TOP, r);
r = SendMessage(hWndTrackbar, TBM_SETTIPSIDE, TBTS_BOTTOM, 0);
expect(1, r);
expect(TBTS_LEFT, r);
r = SendMessage(hWndTrackbar, TBM_SETTIPSIDE, TBTS_RIGHT, 0);
expect(2, r);
expect(TBTS_BOTTOM, r);
/* testing TBM_SETTOOLTIPS */
hWndTooltip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, 0,
@ -967,17 +950,31 @@ static void test_ignore_selection(HWND hWndTrackbar){
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_empty_test_seq, "parent ignore selection setting test sequence", FALSE);
}
static void test_initial_state(void)
{
HWND hWnd;
DWORD ret;
hWnd = create_trackbar(0, hWndParent);
ret = SendMessage(hWnd, TBM_GETNUMTICS, 0, 0);
expect(2, ret);
ret = SendMessage(hWnd, TBM_GETTIC, 0, 0);
expect(-1, ret);
ret = SendMessage(hWnd, TBM_GETTICPOS, 0, 0);
expect(-1, ret);
DestroyWindow(hWnd);
}
START_TEST(trackbar)
{
DWORD style = WS_VISIBLE | TBS_TOOLTIPS | TBS_ENABLESELRANGE | TBS_FIXEDLENGTH | TBS_AUTOTICKS;
HWND hWndTrackbar;
HWND hWndParent;
init_msg_sequences(sequences, NUM_MSG_SEQUENCE);
InitCommonControls();
flush_sequences(sequences, NUM_MSG_SEQUENCE);
/* create parent window */
hWndParent = create_parent_window();
ok(hWndParent != NULL, "Failed to create parent Window!\n");
@ -987,7 +984,6 @@ START_TEST(trackbar)
return;
}
ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create Parent Window", TRUE);
flush_sequences(sequences, NUM_MSG_SEQUENCE);
/* create trackbar with set styles */
@ -1036,5 +1032,7 @@ START_TEST(trackbar)
DestroyWindow(hWndTrackbar);
test_initial_state();
DestroyWindow(hWndParent);
}

File diff suppressed because it is too large Load diff

View file

@ -59,38 +59,15 @@
#define EDIT_SEQ_INDEX 1
#define UPDOWN_SEQ_INDEX 2
static HWND parent_wnd, edit, updown;
#define UPDOWN_ID 0
#define BUDDY_ID 1
static HWND parent_wnd, g_edit;
static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
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_QUERYNEWPALETTE, sent|optional },
{ 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 },
@ -182,12 +159,8 @@ static const struct message test_updown_unicode_seq[] = {
{ 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},
static const struct message test_updown_pos_nochange_seq[] = {
{ WM_GETTEXT, sent|id, 0, 0, BUDDY_ID },
{ 0 }
};
@ -254,14 +227,9 @@ static HWND create_parent_window(void)
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);
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
static LONG defwndproc_counter = 0;
LRESULT ret;
struct message msg;
@ -273,43 +241,37 @@ static LRESULT WINAPI edit_subclass_proc(HWND hwnd, UINT message, WPARAM wParam,
if (defwndproc_counter) msg.flags |= defwinproc;
msg.wParam = wParam;
msg.lParam = lParam;
msg.id = BUDDY_ID;
add_message(sequences, EDIT_SEQ_INDEX, &msg);
defwndproc_counter++;
ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
defwndproc_counter--;
return ret;
}
static HWND create_edit_control(void)
{
struct subclass_info *info;
WNDPROC oldproc;
HWND hwnd;
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,
hwnd = CreateWindowExA(0, WC_EDITA, 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;
}
if (!hwnd) return NULL;
info->oldproc = (WNDPROC)SetWindowLongPtrA(edit, GWLP_WNDPROC,
(LONG_PTR)edit_subclass_proc);
SetWindowLongPtrA(edit, GWLP_USERDATA, (LONG_PTR)info);
oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
(LONG_PTR)edit_subclass_proc);
SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
return edit;
return hwnd;
}
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);
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
static LONG defwndproc_counter = 0;
LRESULT ret;
struct message msg;
@ -321,46 +283,42 @@ static LRESULT WINAPI updown_subclass_proc(HWND hwnd, UINT message, WPARAM wPara
if (defwndproc_counter) msg.flags |= defwinproc;
msg.wParam = wParam;
msg.lParam = lParam;
msg.id = UPDOWN_ID;
add_message(sequences, UPDOWN_SEQ_INDEX, &msg);
defwndproc_counter++;
ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
defwndproc_counter--;
return ret;
}
static HWND create_updown_control(void)
static HWND create_updown_control(DWORD style, HWND buddy)
{
struct subclass_info *info;
WNDPROC oldproc;
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,
updown = CreateUpDownControl(WS_CHILD | WS_BORDER | WS_VISIBLE | style,
0, 0, rect.right, rect.bottom, parent_wnd, 1, GetModuleHandleA(NULL), buddy,
100, 0, 50);
if (!updown)
{
HeapFree(GetProcessHeap(), 0, info);
return NULL;
}
if (!updown) return NULL;
info->oldproc = (WNDPROC)SetWindowLongPtrA(updown, GWLP_WNDPROC,
(LONG_PTR)updown_subclass_proc);
SetWindowLongPtrA(updown, GWLP_USERDATA, (LONG_PTR)info);
oldproc = (WNDPROC)SetWindowLongPtrA(updown, GWLP_WNDPROC,
(LONG_PTR)updown_subclass_proc);
SetWindowLongPtrA(updown, GWLP_USERDATA, (LONG_PTR)oldproc);
return updown;
}
static void test_updown_pos(void)
{
HWND updown;
int r;
updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* Set Range from 0 to 100 */
@ -410,24 +368,63 @@ static void test_updown_pos(void)
expect(1,HIWORD(r));
ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_pos_seq , "test updown pos", FALSE);
DestroyWindow(updown);
/* there's no attempt to update buddy Edit if text didn't change */
SetWindowTextA(g_edit, "50");
updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT, g_edit);
/* test sequence only on 5.8x versions */
r = SendMessage(updown, UDM_GETPOS32, 0, 0);
if (r)
{
flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessage(updown, UDM_SETPOS, 0, 50);
expect(50,r);
ok_sequence(sequences, EDIT_SEQ_INDEX, test_updown_pos_nochange_seq,
"test updown pos, no change", FALSE);
}
DestroyWindow(updown);
}
static void test_updown_pos32(void)
{
HWND updown;
int r;
int low, high;
updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* Set the position to 0 to 1000 */
SendMessage(updown, UDM_SETRANGE32, 0 , 1000 );
low = high = -1;
r = SendMessage(updown, UDM_GETRANGE32, (WPARAM) &low , (LPARAM) &high );
if (low == -1)
{
win_skip("UDM_SETRANGE32/UDM_GETRANGE32 not available\n");
DestroyWindow(updown);
return;
}
expect(0,low);
expect(1000,high);
/* Set position to 500, don't check return since it is unset*/
SendMessage(updown, UDM_SETPOS32, 0 , 500 );
/* Set position to 500 */
r = SendMessage(updown, UDM_SETPOS32, 0 , 500 );
if (!r)
{
win_skip("UDM_SETPOS32 and UDM_GETPOS32 need 5.80\n");
DestroyWindow(updown);
return;
}
expect(50,r);
/* Since UDM_SETBUDDYINT was not set at creation bRet will always be true as a return from UDM_GETPOS32 */
@ -464,30 +461,83 @@ static void test_updown_pos32(void)
expect(1,high);
ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_pos32_seq, "test updown pos32", FALSE);
DestroyWindow(updown);
/* there's no attempt to update buddy Edit if text didn't change */
SetWindowTextA(g_edit, "50");
updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT, g_edit);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
r = SendMessage(updown, UDM_SETPOS32, 0, 50);
expect(50,r);
ok_sequence(sequences, EDIT_SEQ_INDEX, test_updown_pos_nochange_seq,
"test updown pos, no change", FALSE);
DestroyWindow(updown);
}
static void test_updown_buddy(void)
{
HWND buddyReturn;
HWND updown, buddyReturn, buddy;
WNDPROC proc;
DWORD style;
updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
buddyReturn = (HWND)SendMessage(updown, UDM_GETBUDDY, 0 , 0 );
ok(buddyReturn == edit, "Expected edit handle\n");
ok(buddyReturn == g_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_SETBUDDY, (WPARAM) g_edit, 0);
ok(buddyReturn == g_edit, "Expected edit handle\n");
buddyReturn = (HWND)SendMessage(updown, UDM_GETBUDDY, 0 , 0 );
ok(buddyReturn == edit, "Expected edit handle\n");
ok(buddyReturn == g_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);
DestroyWindow(updown);
buddy = create_edit_control();
proc = (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC);
updown= create_updown_control(UDS_ALIGNRIGHT, buddy);
ok(proc == (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "No subclassing expected\n");
style = GetWindowLongA(updown, GWL_STYLE);
SetWindowLongA(updown, GWL_STYLE, style | UDS_ARROWKEYS);
style = GetWindowLongA(updown, GWL_STYLE);
ok(style & UDS_ARROWKEYS, "Expected UDS_ARROWKEYS\n");
/* no subclass if UDS_ARROWKEYS set after creation */
ok(proc == (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "No subclassing expected\n");
DestroyWindow(updown);
updown= create_updown_control(UDS_ALIGNRIGHT | UDS_ARROWKEYS, buddy);
ok(proc != (WNDPROC)GetWindowLongPtrA(buddy, GWLP_WNDPROC), "Subclassing expected\n");
if (pSetWindowSubclass)
{
/* updown uses subclass helpers for buddy on >5.8x systems */
ok(GetPropA(buddy, "CC32SubclassInfo") != NULL, "Expected CC32SubclassInfo property\n");
}
DestroyWindow(updown);
DestroyWindow(buddy);
}
static void test_updown_base(void)
{
HWND updown;
int r;
CHAR text[10];
updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
@ -520,12 +570,36 @@ static void test_updown_base(void)
expect(10,r);
ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_base_seq, "test updown base", FALSE);
DestroyWindow(updown);
/* switch base with buddy attached */
updown = create_updown_control(UDS_SETBUDDYINT | UDS_ALIGNRIGHT, g_edit);
r = SendMessage(updown, UDM_SETPOS, 0, 10);
expect(50, r);
GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
ok(lstrcmpA(text, "10") == 0, "Expected '10', got '%s'\n", text);
r = SendMessage(updown, UDM_SETBASE, 16, 0);
expect(10, r);
GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
/* FIXME: currently hex output isn't properly formatted, but for this
test only change from initial text matters */
ok(lstrcmpA(text, "10") != 0, "Expected '0x000A', got '%s'\n", text);
DestroyWindow(updown);
}
static void test_updown_unicode(void)
{
HWND updown;
int r;
updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* Set it to ANSI, don't check return as we don't know previous state */
@ -537,6 +611,12 @@ static void test_updown_unicode(void)
r = SendMessage(updown, UDM_SETUNICODEFORMAT, 1 , 0);
expect(0,r);
r = SendMessage(updown, UDM_GETUNICODEFORMAT, 0 , 0);
if (!r)
{
win_skip("UDM_SETUNICODEFORMAT not available\n");
DestroyWindow(updown);
return;
}
expect(1,r);
/* And now set it back to ANSI */
@ -546,49 +626,161 @@ static void test_updown_unicode(void)
expect(0,r);
ok_sequence(sequences, UPDOWN_SEQ_INDEX, test_updown_unicode_seq, "test updown unicode", FALSE);
DestroyWindow(updown);
}
static void test_create_updown_control(void)
static void test_updown_create(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);
HWND updown;
RECT r;
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();
updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
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);
GetWindowTextA(g_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);
DestroyWindow(updown);
/* create with zero width */
updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
ok(updown != NULL, "Failed to create updown control\n");
r.right = 0;
GetClientRect(updown, &r);
ok(r.right > 0, "Expected default width, got %d\n", r.right);
DestroyWindow(updown);
/* create with really small width */
updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 2, 0,
parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
ok(updown != NULL, "Failed to create updown control\n");
r.right = 0;
GetClientRect(updown, &r);
ok(r.right != 2 && r.right > 0, "Expected default width, got %d\n", r.right);
DestroyWindow(updown);
/* create with width greater than default */
updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 100, 0,
parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
ok(updown != NULL, "Failed to create updown control\n");
r.right = 0;
GetClientRect(updown, &r);
ok(r.right < 100 && r.right > 0, "Expected default width, got %d\n", r.right);
DestroyWindow(updown);
/* create with zero height, UDS_HORZ */
updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
ok(updown != NULL, "Failed to create updown control\n");
r.bottom = 0;
GetClientRect(updown, &r);
ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
DestroyWindow(updown);
/* create with really small height, UDS_HORZ */
updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 2,
parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
ok(updown != NULL, "Failed to create updown control\n");
r.bottom = 0;
GetClientRect(updown, &r);
ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
DestroyWindow(updown);
/* create with height greater than default, UDS_HORZ */
updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 100,
parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
ok(updown != NULL, "Failed to create updown control\n");
r.bottom = 0;
GetClientRect(updown, &r);
ok(r.bottom < 100 && r.bottom > 0, "Expected default height, got %d\n", r.bottom);
DestroyWindow(updown);
}
static void test_UDS_SETBUDDYINT(void)
{
HWND updown;
DWORD style, ret;
CHAR text[10];
/* cleanup buddy */
text[0] = '\0';
SetWindowTextA(g_edit, text);
/* creating without UDS_SETBUDDYINT */
updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
/* try to set UDS_SETBUDDYINT after creation */
style = GetWindowLongA(updown, GWL_STYLE);
SetWindowLongA(updown, GWL_STYLE, style | UDS_SETBUDDYINT);
style = GetWindowLongA(updown, GWL_STYLE);
ok(style & UDS_SETBUDDYINT, "Expected UDS_SETBUDDY to be set\n");
SendMessage(updown, UDM_SETPOS, 0, 20);
GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
ok(lstrlenA(text) == 0, "Expected empty string\n");
DestroyWindow(updown);
/* creating with UDS_SETBUDDYINT */
updown = create_updown_control(UDS_SETBUDDYINT | UDS_ALIGNRIGHT, g_edit);
GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
/* 50 is initial value here */
ok(lstrcmpA(text, "50") == 0, "Expected '50', got '%s'\n", text);
/* now remove style flag */
style = GetWindowLongA(updown, GWL_STYLE);
SetWindowLongA(updown, GWL_STYLE, style & ~UDS_SETBUDDYINT);
SendMessage(updown, UDM_SETPOS, 0, 20);
GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
ok(lstrcmpA(text, "20") == 0, "Expected '20', got '%s'\n", text);
/* set edit text directly, check position */
strcpy(text, "10");
SetWindowTextA(g_edit, text);
ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
expect(10, ret);
strcpy(text, "11");
SetWindowTextA(g_edit, text);
ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
expect(11, LOWORD(ret));
expect(0, HIWORD(ret));
/* set to invalid value */
strcpy(text, "21st");
SetWindowTextA(g_edit, text);
ret = SendMessageA(updown, UDM_GETPOS, 0, 0);
expect(11, LOWORD(ret));
expect(TRUE, HIWORD(ret));
/* set style back */
style = GetWindowLongA(updown, GWL_STYLE);
SetWindowLongA(updown, GWL_STYLE, style | UDS_SETBUDDYINT);
SendMessage(updown, UDM_SETPOS, 0, 30);
GetWindowTextA(g_edit, text, sizeof(text)/sizeof(CHAR));
ok(lstrcmpA(text, "30") == 0, "Expected '30', got '%s'\n", text);
DestroyWindow(updown);
}
START_TEST(updown)
{
HMODULE mod = GetModuleHandleA("comctl32.dll");
pSetWindowSubclass = (void*)GetProcAddress(mod, (LPSTR)410);
InitCommonControls();
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
parent_wnd = create_parent_window();
ok(parent_wnd != NULL, "Failed to create parent window!\n");
g_edit = create_edit_control();
ok(g_edit != NULL, "Failed to create edit control\n");
test_updown_create();
test_updown_pos();
test_updown_pos32();
test_updown_buddy();
test_updown_base();
test_updown_unicode();
}
test_UDS_SETBUDDYINT();
START_TEST(updown)
{
InitCommonControls();
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
test_create_updown_control();
DestroyWindow(g_edit);
DestroyWindow(parent_wnd);
}

View file

@ -0,0 +1,142 @@
/*
* Utility routines for comctl32 v6 tests
*
* Copyright 2006 Mike McCormack for CodeWeavers
* Copyright 2007 George Gov
* Copyright 2009 Owen Rudge for CodeWeavers
*
* 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
*/
#define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
#ifdef __i386__
#define ARCH "x86"
#elif defined __x86_64__
#define ARCH "amd64"
#else
#define ARCH "none"
#endif
static const CHAR manifest_name[] = "cc6.manifest";
static const CHAR manifest[] =
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"
" <assemblyIdentity\n"
" type=\"win32\"\n"
" name=\"Wine.ComCtl32.Tests\"\n"
" version=\"1.0.0.0\"\n"
" processorArchitecture=\"" ARCH "\"\n"
" />\n"
"<description>Wine comctl32 test suite</description>\n"
"<dependency>\n"
" <dependentAssembly>\n"
" <assemblyIdentity\n"
" type=\"win32\"\n"
" name=\"microsoft.windows.common-controls\"\n"
" version=\"6.0.0.0\"\n"
" processorArchitecture=\"" ARCH "\"\n"
" publicKeyToken=\"6595b64144ccf1df\"\n"
" language=\"*\"\n"
" />\n"
"</dependentAssembly>\n"
"</dependency>\n"
"</assembly>\n";
static void unload_v6_module(ULONG_PTR cookie, HANDLE hCtx)
{
HANDLE hKernel32;
BOOL (WINAPI *pDeactivateActCtx)(DWORD, ULONG_PTR);
VOID (WINAPI *pReleaseActCtx)(HANDLE);
hKernel32 = GetModuleHandleA("kernel32.dll");
pDeactivateActCtx = (void*)GetProcAddress(hKernel32, "DeactivateActCtx");
pReleaseActCtx = (void*)GetProcAddress(hKernel32, "ReleaseActCtx");
if (!pDeactivateActCtx || !pReleaseActCtx)
{
win_skip("Activation contexts unsupported\n");
return;
}
pDeactivateActCtx(0, cookie);
pReleaseActCtx(hCtx);
DeleteFileA(manifest_name);
}
static BOOL load_v6_module(ULONG_PTR *pcookie, HANDLE *hCtx)
{
HANDLE hKernel32;
HANDLE (WINAPI *pCreateActCtxA)(ACTCTXA*);
BOOL (WINAPI *pActivateActCtx)(HANDLE, ULONG_PTR*);
ACTCTXA ctx;
BOOL ret;
HANDLE file;
DWORD written;
hKernel32 = GetModuleHandleA("kernel32.dll");
pCreateActCtxA = (void*)GetProcAddress(hKernel32, "CreateActCtxA");
pActivateActCtx = (void*)GetProcAddress(hKernel32, "ActivateActCtx");
if (!(pCreateActCtxA && pActivateActCtx))
{
win_skip("Activation contexts unsupported. No version 6 tests possible.\n");
return FALSE;
}
/* create manifest */
file = CreateFileA( manifest_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL );
if (file != INVALID_HANDLE_VALUE)
{
ret = (WriteFile( file, manifest, sizeof(manifest)-1, &written, NULL ) &&
written == sizeof(manifest)-1);
CloseHandle( file );
if (!ret)
{
DeleteFileA( manifest_name );
skip("Failed to fill manifest file. Skipping comctl32 V6 tests.\n");
return FALSE;
}
else
trace("created %s\n", manifest_name);
}
else
{
skip("Failed to create manifest file. Skipping comctl32 V6 tests.\n");
return FALSE;
}
memset(&ctx, 0, sizeof(ctx));
ctx.cbSize = sizeof(ctx);
ctx.lpSource = manifest_name;
*hCtx = pCreateActCtxA(&ctx);
ok(*hCtx != 0, "Expected context handle\n");
ret = pActivateActCtx(*hCtx, pcookie);
expect(TRUE, ret);
if (!ret)
{
win_skip("A problem during context activation occurred.\n");
DeleteFileA(manifest_name);
}
return ret;
}
#undef expect
#undef ARCH