mirror of
https://github.com/reactos/reactos.git
synced 2025-05-31 15:08:14 +00:00
[COMCTL32_WINETEST] Sync with Wine Staging 4.18. CORE-16441
This commit is contained in:
parent
5ddec3d944
commit
8addeea484
11 changed files with 1316 additions and 186 deletions
|
@ -48,7 +48,8 @@ static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST);
|
|||
#define ID_BUTTON 0x000e
|
||||
|
||||
#define COMBINED_SEQ_INDEX 0
|
||||
#define NUM_MSG_SEQUENCES 1
|
||||
#define PARENT_CD_SEQ_INDEX 1
|
||||
#define NUM_MSG_SEQUENCES 2
|
||||
|
||||
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
|
||||
|
||||
|
@ -160,11 +161,40 @@ static LRESULT CALLBACK button_subclass_proc(HWND hwnd, UINT message, WPARAM wPa
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
DWORD button;
|
||||
UINT line;
|
||||
UINT state;
|
||||
DWORD ret;
|
||||
BOOL empty;
|
||||
} test_cd;
|
||||
|
||||
#define set_test_cd_state(s) do { \
|
||||
test_cd.state = (s); \
|
||||
test_cd.empty = TRUE; \
|
||||
test_cd.line = __LINE__; \
|
||||
} while (0)
|
||||
|
||||
#define set_test_cd_ret(r) do { \
|
||||
test_cd.ret = (r); \
|
||||
test_cd.empty = TRUE; \
|
||||
test_cd.line = __LINE__; \
|
||||
} while (0)
|
||||
|
||||
static void disable_test_cd(void)
|
||||
{
|
||||
test_cd.line = 0;
|
||||
}
|
||||
|
||||
static LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static LONG defwndproc_counter = 0;
|
||||
static LONG beginpaint_counter = 0;
|
||||
static HDC cd_first_hdc;
|
||||
struct message msg = { 0 };
|
||||
NMCUSTOMDRAW *cd = (NMCUSTOMDRAW*)lParam;
|
||||
NMBCDROPDOWN *bcd = (NMBCDROPDOWN*)lParam;
|
||||
LRESULT ret;
|
||||
|
||||
if (ignore_message( message )) return 0;
|
||||
|
@ -184,6 +214,76 @@ static LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam
|
|||
add_message(sequences, COMBINED_SEQ_INDEX, &msg);
|
||||
}
|
||||
|
||||
if (message == WM_NOTIFY && cd->hdr.code == NM_CUSTOMDRAW && test_cd.line)
|
||||
{
|
||||
/* Ignore an inconsistency across Windows versions */
|
||||
UINT state = cd->uItemState & ~CDIS_SHOWKEYBOARDCUES;
|
||||
|
||||
/* Some Windows configurations paint twice with different DC */
|
||||
if (test_cd.empty)
|
||||
{
|
||||
cd_first_hdc = cd->hdc;
|
||||
test_cd.empty = FALSE;
|
||||
}
|
||||
|
||||
ok_(__FILE__,test_cd.line)(!(cd->dwDrawStage & CDDS_ITEM),
|
||||
"[%u] CDDS_ITEM is set\n", test_cd.button);
|
||||
|
||||
ok_(__FILE__,test_cd.line)(state == test_cd.state,
|
||||
"[%u] expected uItemState %u, got %u\n", test_cd.button,
|
||||
test_cd.state, state);
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|parent|wparam|lparam|id|custdraw;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = NM_CUSTOMDRAW;
|
||||
msg.stage = cd->dwDrawStage;
|
||||
if (cd->hdc == cd_first_hdc)
|
||||
add_message(sequences, PARENT_CD_SEQ_INDEX, &msg);
|
||||
|
||||
ret = test_cd.ret;
|
||||
switch (msg.stage)
|
||||
{
|
||||
case CDDS_PREERASE:
|
||||
ret &= ~CDRF_NOTIFYPOSTPAINT;
|
||||
cd->dwItemSpec = 0xdeadbeef;
|
||||
break;
|
||||
case CDDS_PREPAINT:
|
||||
ret &= ~CDRF_NOTIFYPOSTERASE;
|
||||
break;
|
||||
case CDDS_POSTERASE:
|
||||
case CDDS_POSTPAINT:
|
||||
ok_(__FILE__,test_cd.line)(cd->dwItemSpec == 0xdeadbeef,
|
||||
"[%u] NMCUSTOMDRAW was not shared, stage %u\n", test_cd.button, msg.stage);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (message == WM_NOTIFY && bcd->hdr.code == BCN_DROPDOWN)
|
||||
{
|
||||
UINT button = GetWindowLongW(bcd->hdr.hwndFrom, GWL_STYLE) & BS_TYPEMASK;
|
||||
RECT rc;
|
||||
|
||||
GetClientRect(bcd->hdr.hwndFrom, &rc);
|
||||
|
||||
ok(bcd->hdr.hwndFrom != NULL, "Received BCN_DROPDOWN with no hwnd attached, wParam %lu id %lu\n",
|
||||
wParam, bcd->hdr.idFrom);
|
||||
ok(bcd->hdr.idFrom == wParam, "[%u] Mismatch between wParam (%lu) and idFrom (%lu)\n",
|
||||
button, wParam, bcd->hdr.idFrom);
|
||||
ok(EqualRect(&rc, &bcd->rcButton), "[%u] Wrong rcButton, expected %s got %s\n",
|
||||
button, wine_dbgstr_rect(&rc), wine_dbgstr_rect(&bcd->rcButton));
|
||||
|
||||
msg.message = message;
|
||||
msg.flags = sent|parent|wparam|lparam|id;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
msg.id = BCN_DROPDOWN;
|
||||
add_message(sequences, COMBINED_SEQ_INDEX, &msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (message == WM_PAINT)
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
|
@ -461,6 +561,60 @@ static const struct message setcheck_radio_redraw_seq[] =
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message empty_cd_seq[] = { { 0 } };
|
||||
|
||||
static const struct message pre_cd_seq[] =
|
||||
{
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message pre_pre_cd_seq[] =
|
||||
{
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE },
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message pre_post_pre_cd_seq[] =
|
||||
{
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE },
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTERASE },
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message pre_pre_post_cd_seq[] =
|
||||
{
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE },
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT },
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message pre_post_pre_post_cd_seq[] =
|
||||
{
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREERASE },
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTERASE },
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT },
|
||||
{ WM_NOTIFY, sent|parent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message bcn_dropdown_seq[] =
|
||||
{
|
||||
{ WM_KEYDOWN, sent|wparam|lparam, VK_DOWN, 0 },
|
||||
{ BCM_SETDROPDOWNSTATE, sent|wparam|lparam|defwinproc, 1, 0 },
|
||||
{ WM_NOTIFY, sent|parent|id, 0, 0, BCN_DROPDOWN },
|
||||
{ BCM_SETDROPDOWNSTATE, sent|wparam|lparam|defwinproc, 0, 0 },
|
||||
{ WM_KEYUP, sent|wparam|lparam, VK_DOWN, 0xc0000000 },
|
||||
{ WM_PAINT, sent },
|
||||
{ WM_DRAWITEM, sent|parent|optional }, /* for owner draw button */
|
||||
{ WM_PAINT, sent|optional }, /* sometimes sent rarely */
|
||||
{ WM_DRAWITEM, sent|parent|optional },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static HWND create_button(DWORD style, HWND parent)
|
||||
{
|
||||
HMENU menuid = 0;
|
||||
|
@ -479,6 +633,13 @@ static HWND create_button(DWORD style, HWND parent)
|
|||
|
||||
static void test_button_messages(void)
|
||||
{
|
||||
enum cd_seq_type
|
||||
{
|
||||
cd_seq_empty,
|
||||
cd_seq_normal,
|
||||
cd_seq_optional
|
||||
};
|
||||
|
||||
static const struct
|
||||
{
|
||||
DWORD style;
|
||||
|
@ -489,55 +650,74 @@ static void test_button_messages(void)
|
|||
const struct message *setstate;
|
||||
const struct message *clearstate;
|
||||
const struct message *setcheck;
|
||||
enum cd_seq_type cd_setfocus_type;
|
||||
enum cd_seq_type cd_setstyle_type;
|
||||
enum cd_seq_type cd_setstate_type;
|
||||
enum cd_seq_type cd_setcheck_type;
|
||||
} button[] = {
|
||||
{ BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
|
||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq },
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq,
|
||||
cd_seq_normal, cd_seq_normal, cd_seq_normal, cd_seq_optional },
|
||||
{ BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
|
||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq },
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq,
|
||||
cd_seq_normal, cd_seq_normal, cd_seq_normal, cd_seq_optional },
|
||||
{ BS_CHECKBOX, DLGC_BUTTON,
|
||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
||||
setstate_static_seq, setstate_static_seq, setcheck_static_seq },
|
||||
setstate_static_seq, setstate_static_seq, setcheck_static_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional },
|
||||
{ BS_AUTOCHECKBOX, DLGC_BUTTON,
|
||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
||||
setstate_static_seq, setstate_static_seq, setcheck_static_seq },
|
||||
setstate_static_seq, setstate_static_seq, setcheck_static_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional },
|
||||
{ BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
|
||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
||||
setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq },
|
||||
setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional },
|
||||
{ BS_3STATE, DLGC_BUTTON,
|
||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
||||
setstate_static_seq, setstate_static_seq, setcheck_static_seq },
|
||||
setstate_static_seq, setstate_static_seq, setcheck_static_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional },
|
||||
{ BS_AUTO3STATE, DLGC_BUTTON,
|
||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
||||
setstate_static_seq, setstate_static_seq, setcheck_static_seq },
|
||||
setstate_static_seq, setstate_static_seq, setcheck_static_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional },
|
||||
{ BS_GROUPBOX, DLGC_STATIC,
|
||||
setfocus_groupbox_seq, killfocus_static_seq, setstyle_static_seq,
|
||||
setstate_static_seq, setstate_static_seq, setcheck_ignored_seq },
|
||||
setstate_static_seq, setstate_static_seq, setcheck_ignored_seq,
|
||||
cd_seq_empty, cd_seq_empty, cd_seq_empty, cd_seq_empty },
|
||||
{ BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
|
||||
setfocus_seq, killfocus_seq, setstyle_user_seq,
|
||||
setstate_user_seq, clearstate_seq, setcheck_ignored_seq },
|
||||
setstate_user_seq, clearstate_seq, setcheck_ignored_seq,
|
||||
cd_seq_normal, cd_seq_empty, cd_seq_empty, cd_seq_empty },
|
||||
{ BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
|
||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
||||
setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq },
|
||||
setstate_static_seq, setstate_static_seq, setcheck_radio_redraw_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_optional },
|
||||
{ BS_OWNERDRAW, DLGC_BUTTON,
|
||||
setfocus_ownerdraw_seq, killfocus_ownerdraw_seq, setstyle_ownerdraw_seq,
|
||||
setstate_ownerdraw_seq, clearstate_ownerdraw_seq, setcheck_ignored_seq },
|
||||
setstate_ownerdraw_seq, clearstate_ownerdraw_seq, setcheck_ignored_seq,
|
||||
cd_seq_empty, cd_seq_empty, cd_seq_empty, cd_seq_empty },
|
||||
{ BS_SPLITBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON | DLGC_WANTARROWS,
|
||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq },
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty },
|
||||
{ BS_DEFSPLITBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON | DLGC_WANTARROWS,
|
||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq },
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty },
|
||||
{ BS_COMMANDLINK, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
|
||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq },
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty },
|
||||
{ BS_DEFCOMMANDLINK, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
|
||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq },
|
||||
setstate_seq, setstate_seq, setcheck_ignored_seq,
|
||||
cd_seq_optional, cd_seq_optional, cd_seq_optional, cd_seq_empty }
|
||||
};
|
||||
LOGFONTA logfont = { 0 };
|
||||
const struct message *seq;
|
||||
const struct message *seq, *cd_seq;
|
||||
HFONT zfont, hfont2;
|
||||
unsigned int i;
|
||||
HWND hwnd, parent;
|
||||
|
@ -565,6 +745,11 @@ static void test_button_messages(void)
|
|||
hfont2 = CreateFontIndirectA(&logfont);
|
||||
ok(hfont2 != NULL, "Failed to create Tahoma font\n");
|
||||
|
||||
#define check_cd_seq(type, context) do { \
|
||||
if (button[i].type != cd_seq_optional || !test_cd.empty) \
|
||||
ok_sequence(sequences, PARENT_CD_SEQ_INDEX, cd_seq, "[CustomDraw] " context, FALSE); \
|
||||
} while(0)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(button); i++)
|
||||
{
|
||||
HFONT prevfont, hfont;
|
||||
|
@ -572,6 +757,7 @@ static void test_button_messages(void)
|
|||
DWORD style, state;
|
||||
HDC hdc;
|
||||
|
||||
test_cd.button = button[i].style;
|
||||
hwnd = create_button(button[i].style, parent);
|
||||
ok(hwnd != NULL, "Failed to create a button.\n");
|
||||
|
||||
|
@ -599,27 +785,35 @@ static void test_button_messages(void)
|
|||
SetFocus(0);
|
||||
flush_events();
|
||||
SetFocus(0);
|
||||
cd_seq = (button[i].cd_setfocus_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq;
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
set_test_cd_ret(CDRF_DODEFAULT);
|
||||
set_test_cd_state(CDIS_FOCUS);
|
||||
|
||||
todo = button[i].style != BS_OWNERDRAW;
|
||||
ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
|
||||
SetFocus(hwnd);
|
||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setfocus, "SetFocus(hwnd) on a button", todo);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setfocus, "SetFocus(hwnd) on a button", FALSE);
|
||||
check_cd_seq(cd_setfocus_type, "SetFocus(hwnd)");
|
||||
|
||||
todo = button[i].style == BS_OWNERDRAW;
|
||||
set_test_cd_state(0);
|
||||
SetFocus(0);
|
||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].killfocus, "SetFocus(0) on a button", todo);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].killfocus, "SetFocus(0) on a button", FALSE);
|
||||
check_cd_seq(cd_setfocus_type, "SetFocus(0)");
|
||||
ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
|
||||
|
||||
cd_seq = (button[i].cd_setstyle_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq;
|
||||
set_test_cd_state(0);
|
||||
|
||||
SendMessageA(hwnd, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE);
|
||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
todo = button[i].style == BS_OWNERDRAW;
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setstyle, "BM_SETSTYLE on a button", todo);
|
||||
check_cd_seq(cd_setstyle_type, "BM_SETSTYLE");
|
||||
|
||||
style = GetWindowLongA(hwnd, GWL_STYLE);
|
||||
style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY);
|
||||
|
@ -629,12 +823,15 @@ static void test_button_messages(void)
|
|||
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0);
|
||||
ok(state == 0, "expected state 0, got %04x\n", state);
|
||||
|
||||
cd_seq = (button[i].cd_setstate_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq;
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
set_test_cd_state(CDIS_SELECTED);
|
||||
|
||||
SendMessageA(hwnd, BM_SETSTATE, TRUE, 0);
|
||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setstate, "BM_SETSTATE/TRUE on a button", FALSE);
|
||||
check_cd_seq(cd_setstate_type, "BM_SETSTATE/TRUE");
|
||||
|
||||
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0);
|
||||
ok(state == BST_PUSHED, "expected state 0x0004, got %04x\n", state);
|
||||
|
@ -644,11 +841,13 @@ static void test_button_messages(void)
|
|||
ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
|
||||
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
set_test_cd_state(0);
|
||||
|
||||
SendMessageA(hwnd, BM_SETSTATE, FALSE, 0);
|
||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].clearstate, "BM_SETSTATE/FALSE on a button", FALSE);
|
||||
check_cd_seq(cd_setstate_type, "BM_SETSTATE/FALSE");
|
||||
|
||||
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0);
|
||||
ok(state == 0, "expected state 0, got %04x\n", state);
|
||||
|
@ -660,7 +859,9 @@ static void test_button_messages(void)
|
|||
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0);
|
||||
ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state);
|
||||
|
||||
cd_seq = (button[i].cd_setcheck_type == cd_seq_empty) ? empty_cd_seq : pre_pre_cd_seq;
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
set_test_cd_state(0);
|
||||
|
||||
if (button[i].style == BS_RADIOBUTTON ||
|
||||
button[i].style == BS_AUTORADIOBUTTON)
|
||||
|
@ -674,6 +875,7 @@ static void test_button_messages(void)
|
|||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, seq, "BM_SETCHECK on a button", FALSE);
|
||||
check_cd_seq(cd_setcheck_type, "BM_SETCHECK");
|
||||
|
||||
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0);
|
||||
ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state);
|
||||
|
@ -683,11 +885,13 @@ static void test_button_messages(void)
|
|||
ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
|
||||
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
set_test_cd_state(0);
|
||||
|
||||
SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0);
|
||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setcheck, "BM_SETCHECK on a button", FALSE);
|
||||
check_cd_seq(cd_setcheck_type, "BM_SETCHECK");
|
||||
|
||||
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0);
|
||||
if (button[i].style == BS_PUSHBUTTON ||
|
||||
|
@ -735,9 +939,60 @@ static void test_button_messages(void)
|
|||
|
||||
DeleteDC(hdc);
|
||||
|
||||
/* Test Custom Draw return values */
|
||||
if (button[i].cd_setfocus_type != cd_seq_empty &&
|
||||
broken(button[i].style != BS_USERBUTTON) /* WinXP */)
|
||||
{
|
||||
static const struct
|
||||
{
|
||||
const char *context;
|
||||
LRESULT val;
|
||||
const struct message *seq;
|
||||
} ret[] = {
|
||||
{ "CDRF_DODEFAULT", CDRF_DODEFAULT, pre_pre_cd_seq },
|
||||
{ "CDRF_DOERASE", CDRF_DOERASE, pre_pre_cd_seq },
|
||||
{ "CDRF_SKIPDEFAULT", CDRF_SKIPDEFAULT, pre_cd_seq },
|
||||
{ "CDRF_SKIPDEFAULT | CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT",
|
||||
CDRF_SKIPDEFAULT | CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT, pre_cd_seq },
|
||||
{ "CDRF_NOTIFYPOSTERASE", CDRF_NOTIFYPOSTERASE, pre_post_pre_cd_seq },
|
||||
{ "CDRF_NOTIFYPOSTPAINT", CDRF_NOTIFYPOSTPAINT, pre_pre_post_cd_seq },
|
||||
{ "CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT",
|
||||
CDRF_NOTIFYPOSTERASE | CDRF_NOTIFYPOSTPAINT, pre_post_pre_post_cd_seq },
|
||||
};
|
||||
UINT k;
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(ret); k++)
|
||||
{
|
||||
disable_test_cd();
|
||||
SetFocus(0);
|
||||
set_test_cd_ret(ret[k].val);
|
||||
set_test_cd_state(CDIS_FOCUS);
|
||||
SetFocus(hwnd);
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
if (button[i].cd_setfocus_type != cd_seq_optional || !test_cd.empty)
|
||||
ok_sequence(sequences, PARENT_CD_SEQ_INDEX, ret[k].seq, ret[k].context, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
disable_test_cd();
|
||||
|
||||
if (!broken(LOBYTE(LOWORD(GetVersion())) < 6)) /* not available pre-Vista */
|
||||
{
|
||||
/* Send down arrow key to make the buttons send the drop down notification */
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
SendMessageW(hwnd, WM_KEYDOWN, VK_DOWN, 0);
|
||||
SendMessageW(hwnd, WM_KEYUP, VK_DOWN, 0xc0000000);
|
||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, bcn_dropdown_seq, "BCN_DROPDOWN from the button", FALSE);
|
||||
}
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
#undef check_cd_seq
|
||||
|
||||
DeleteObject(hfont2);
|
||||
DestroyWindow(parent);
|
||||
|
||||
|
@ -1228,6 +1483,214 @@ static void register_parent_class(void)
|
|||
RegisterClassA(&cls);
|
||||
}
|
||||
|
||||
static void test_bcm_splitinfo(HWND hwnd)
|
||||
{
|
||||
UINT button = GetWindowLongA(hwnd, GWL_STYLE) & BS_TYPEMASK;
|
||||
int glyph_size = GetSystemMetrics(SM_CYMENUCHECK);
|
||||
int border_w = GetSystemMetrics(SM_CXEDGE) * 2;
|
||||
BUTTON_SPLITINFO info, dummy;
|
||||
HIMAGELIST img;
|
||||
BOOL ret;
|
||||
|
||||
memset(&info, 0xCC, sizeof(info));
|
||||
info.mask = 0;
|
||||
memcpy(&dummy, &info, sizeof(info));
|
||||
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
if (ret != TRUE)
|
||||
{
|
||||
static BOOL once;
|
||||
if (!once)
|
||||
win_skip("BCM_GETSPLITINFO message is unavailable. Skipping related tests\n"); /* Pre-Vista */
|
||||
once = TRUE;
|
||||
return;
|
||||
}
|
||||
ok(!memcmp(&info, &dummy, sizeof(info)), "[%u] split info struct was changed with mask = 0\n", button);
|
||||
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, 0);
|
||||
ok(ret == FALSE, "[%u] expected FALSE, got %d\n", button, ret);
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, 0);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
|
||||
info.mask = BCSIF_GLYPH | BCSIF_SIZE | BCSIF_STYLE;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == (BCSIF_GLYPH | BCSIF_SIZE | BCSIF_STYLE), "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.himlGlyph == (HIMAGELIST)0x36, "[%u] expected 0x36 default glyph, got 0x%p\n", button, info.himlGlyph);
|
||||
ok(info.uSplitStyle == BCSS_STRETCH, "[%u] expected 0x%08x default style, got 0x%08x\n", button, BCSS_STRETCH, info.uSplitStyle);
|
||||
ok(info.size.cx == glyph_size, "[%u] expected %d default size.cx, got %d\n", button, glyph_size, info.size.cx);
|
||||
ok(info.size.cy == 0, "[%u] expected 0 default size.cy, got %d\n", button, info.size.cy);
|
||||
|
||||
info.mask = BCSIF_SIZE;
|
||||
info.size.cx = glyph_size + 7;
|
||||
info.size.cy = 0;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.size.cx = info.size.cy = 0xdeadbeef;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == BCSIF_SIZE, "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.size.cx == glyph_size + 7, "[%u] expected %d, got %d\n", button, glyph_size + 7, info.size.cx);
|
||||
ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy);
|
||||
|
||||
/* Invalid size.cx resets it to default glyph size, while size.cy is stored */
|
||||
info.size.cx = 0;
|
||||
info.size.cy = -20;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.size.cx = info.size.cy = 0xdeadbeef;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == BCSIF_SIZE, "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx);
|
||||
ok(info.size.cy == -20, "[%u] expected -20, got %d\n", button, info.size.cy);
|
||||
|
||||
info.size.cx = -glyph_size - 7;
|
||||
info.size.cy = -10;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.size.cx = info.size.cy = 0xdeadbeef;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == BCSIF_SIZE, "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx);
|
||||
ok(info.size.cy == -10, "[%u] expected -10, got %d\n", button, info.size.cy);
|
||||
|
||||
/* Set to a valid size other than glyph_size */
|
||||
info.mask = BCSIF_SIZE;
|
||||
info.size.cx = glyph_size + 7;
|
||||
info.size.cy = 11;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.size.cx = info.size.cy = 0xdeadbeef;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == BCSIF_SIZE, "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.size.cx == glyph_size + 7, "[%u] expected %d, got %d\n", button, glyph_size + 7, info.size.cx);
|
||||
ok(info.size.cy == 11, "[%u] expected 11, got %d\n", button, info.size.cy);
|
||||
|
||||
/* Change the glyph, size.cx should be automatically adjusted and size.cy set to 0 */
|
||||
dummy.mask = BCSIF_GLYPH;
|
||||
dummy.himlGlyph = (HIMAGELIST)0x35;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&dummy);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.mask = BCSIF_GLYPH | BCSIF_SIZE;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == (BCSIF_GLYPH | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.himlGlyph == (HIMAGELIST)0x35, "[%u] expected 0x35, got %p\n", button, info.himlGlyph);
|
||||
ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx);
|
||||
ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy);
|
||||
|
||||
/* Unless the size is specified manually */
|
||||
dummy.mask = BCSIF_GLYPH | BCSIF_SIZE;
|
||||
dummy.himlGlyph = (HIMAGELIST)0x34;
|
||||
dummy.size.cx = glyph_size + 11;
|
||||
dummy.size.cy = 7;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&dummy);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == (BCSIF_GLYPH | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.himlGlyph == (HIMAGELIST)0x34, "[%u] expected 0x34, got %p\n", button, info.himlGlyph);
|
||||
ok(info.size.cx == glyph_size + 11, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx);
|
||||
ok(info.size.cy == 7, "[%u] expected 7, got %d\n", button, info.size.cy);
|
||||
|
||||
/* Add the BCSS_IMAGE style manually with the wrong BCSIF_GLYPH mask, should treat it as invalid image */
|
||||
info.mask = BCSIF_GLYPH | BCSIF_STYLE;
|
||||
info.himlGlyph = (HIMAGELIST)0x37;
|
||||
info.uSplitStyle = BCSS_IMAGE;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.mask |= BCSIF_SIZE;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == (BCSIF_GLYPH | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.himlGlyph == (HIMAGELIST)0x37, "[%u] expected 0x37, got %p\n", button, info.himlGlyph);
|
||||
ok(info.uSplitStyle == BCSS_IMAGE, "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_IMAGE, info.uSplitStyle);
|
||||
ok(info.size.cx == border_w, "[%u] expected %d, got %d\n", button, border_w, info.size.cx);
|
||||
ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy);
|
||||
|
||||
/* Change the size to prevent ambiguity */
|
||||
dummy.mask = BCSIF_SIZE;
|
||||
dummy.size.cx = glyph_size + 5;
|
||||
dummy.size.cy = 4;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&dummy);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == (BCSIF_GLYPH | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.himlGlyph == (HIMAGELIST)0x37, "[%u] expected 0x37, got %p\n", button, info.himlGlyph);
|
||||
ok(info.uSplitStyle == BCSS_IMAGE, "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_IMAGE, info.uSplitStyle);
|
||||
ok(info.size.cx == glyph_size + 5, "[%u] expected %d, got %d\n", button, glyph_size + 5, info.size.cx);
|
||||
ok(info.size.cy == 4, "[%u] expected 4, got %d\n", button, info.size.cy);
|
||||
|
||||
/* Now remove the BCSS_IMAGE style manually with the wrong BCSIF_IMAGE mask */
|
||||
info.mask = BCSIF_IMAGE | BCSIF_STYLE;
|
||||
info.himlGlyph = (HIMAGELIST)0x35;
|
||||
info.uSplitStyle = BCSS_STRETCH;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.mask |= BCSIF_SIZE;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == (BCSIF_IMAGE | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.himlGlyph == (HIMAGELIST)0x35, "[%u] expected 0x35, got %p\n", button, info.himlGlyph);
|
||||
ok(info.uSplitStyle == BCSS_STRETCH, "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_STRETCH, info.uSplitStyle);
|
||||
ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx);
|
||||
ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy);
|
||||
|
||||
/* Add a proper valid image, the BCSS_IMAGE style should be set automatically */
|
||||
img = pImageList_Create(42, 33, ILC_COLOR, 1, 1);
|
||||
ok(img != NULL, "[%u] failed to create ImageList\n", button);
|
||||
info.mask = BCSIF_IMAGE;
|
||||
info.himlGlyph = img;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.mask |= BCSIF_STYLE | BCSIF_SIZE;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == (BCSIF_IMAGE | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.himlGlyph == img, "[%u] expected %p, got %p\n", button, img, info.himlGlyph);
|
||||
ok(info.uSplitStyle == (BCSS_IMAGE | BCSS_STRETCH), "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_IMAGE | BCSS_STRETCH, info.uSplitStyle);
|
||||
ok(info.size.cx == 42 + border_w, "[%u] expected %d, got %d\n", button, 42 + border_w, info.size.cx);
|
||||
ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy);
|
||||
pImageList_Destroy(img);
|
||||
dummy.mask = BCSIF_SIZE;
|
||||
dummy.size.cx = glyph_size + 5;
|
||||
dummy.size.cy = 4;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&dummy);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
|
||||
/* Change it to a glyph; when both specified, BCSIF_GLYPH takes priority */
|
||||
info.mask = BCSIF_GLYPH | BCSIF_IMAGE;
|
||||
info.himlGlyph = (HIMAGELIST)0x37;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.mask |= BCSIF_STYLE | BCSIF_SIZE;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == (BCSIF_GLYPH | BCSIF_IMAGE | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.himlGlyph == (HIMAGELIST)0x37, "[%u] expected 0x37, got %p\n", button, info.himlGlyph);
|
||||
ok(info.uSplitStyle == BCSS_STRETCH, "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_STRETCH, info.uSplitStyle);
|
||||
ok(info.size.cx == glyph_size, "[%u] expected %d, got %d\n", button, glyph_size, info.size.cx);
|
||||
ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy);
|
||||
|
||||
/* Try a NULL image */
|
||||
info.mask = BCSIF_IMAGE;
|
||||
info.himlGlyph = NULL;
|
||||
ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
info.mask |= BCSIF_STYLE | BCSIF_SIZE;
|
||||
ret = SendMessageA(hwnd, BCM_GETSPLITINFO, 0, (LPARAM)&info);
|
||||
ok(ret == TRUE, "[%u] expected TRUE, got %d\n", button, ret);
|
||||
ok(info.mask == (BCSIF_IMAGE | BCSIF_STYLE | BCSIF_SIZE), "[%u] wrong mask, got %u\n", button, info.mask);
|
||||
ok(info.himlGlyph == NULL, "[%u] expected NULL, got %p\n", button, info.himlGlyph);
|
||||
ok(info.uSplitStyle == (BCSS_IMAGE | BCSS_STRETCH), "[%u] expected 0x%08x style, got 0x%08x\n", button, BCSS_IMAGE | BCSS_STRETCH, info.uSplitStyle);
|
||||
ok(info.size.cx == border_w, "[%u] expected %d, got %d\n", button, border_w, info.size.cx);
|
||||
ok(info.size.cy == 0, "[%u] expected 0, got %d\n", button, info.size.cy);
|
||||
}
|
||||
|
||||
static void test_button_data(void)
|
||||
{
|
||||
static const DWORD styles[] =
|
||||
|
@ -1280,6 +1743,9 @@ static void test_button_data(void)
|
|||
ok(desc->style == (WS_CHILD | BS_NOTIFY | styles[i]), "Unexpected 'style' field.\n");
|
||||
}
|
||||
|
||||
/* Data set and retrieved by these messages is valid for all buttons */
|
||||
test_bcm_splitinfo(hwnd);
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
|
@ -1431,14 +1897,31 @@ static void test_bcm_get_ideal_size(void)
|
|||
{
|
||||
static const char *button_text2 = "WWWW\nWWWW";
|
||||
static const char *button_text = "WWWW";
|
||||
static const WCHAR button_note_short[] = { 'W',0 };
|
||||
static const WCHAR button_note_long[] = { 'W','W','W','W','W','W','W','W','W','W','W','W','W','W','W','W',0 };
|
||||
static const WCHAR button_note_wordy[] = { 'T','h','i','s',' ','i','s',' ','a',' ','l','o','n','g',' ','n','o','t','e',' ','f','o','r',' ','t','h','e',' ','b','u','t','t','o','n',',',' ',
|
||||
'w','i','t','h',' ','m','a','n','y',' ','w','o','r','d','s',',',' ','w','h','i','c','h',' ','s','h','o','u','l','d',' ','b','e',' ',
|
||||
'o','v','e','r','a','l','l',' ','l','o','n','g','e','r',' ','t','h','a','n',' ','t','h','e',' ','t','e','x','t',' ','(','g','i','v','e','n',' ',
|
||||
't','h','e',' ','s','m','a','l','l','e','r',' ','f','o','n','t',')',' ','a','n','d',' ','t','h','u','s',' ','w','r','a','p','.',0 };
|
||||
static const DWORD imagelist_aligns[] = {BUTTON_IMAGELIST_ALIGN_LEFT, BUTTON_IMAGELIST_ALIGN_RIGHT,
|
||||
BUTTON_IMAGELIST_ALIGN_TOP, BUTTON_IMAGELIST_ALIGN_BOTTOM,
|
||||
BUTTON_IMAGELIST_ALIGN_CENTER};
|
||||
static const DWORD aligns[] = {0, BS_TOP, BS_LEFT, BS_RIGHT, BS_BOTTOM,
|
||||
BS_CENTER, BS_VCENTER, BS_RIGHTBUTTON, WS_EX_RIGHT};
|
||||
DWORD default_style = WS_TABSTOP | WS_POPUP | WS_VISIBLE;
|
||||
const LONG client_width = 400, client_height = 200;
|
||||
LONG image_width, height, line_count, text_width;
|
||||
const LONG client_width = 400, client_height = 200, extra_width = 123, large_height = 500;
|
||||
struct
|
||||
{
|
||||
DWORD style;
|
||||
LONG extra_width;
|
||||
} pushtype[] =
|
||||
{
|
||||
{ BS_PUSHBUTTON, 0 },
|
||||
{ BS_DEFPUSHBUTTON, 0 },
|
||||
{ BS_SPLITBUTTON, extra_width * 2 + GetSystemMetrics(SM_CXEDGE) },
|
||||
{ BS_DEFSPLITBUTTON, extra_width * 2 + GetSystemMetrics(SM_CXEDGE) }
|
||||
};
|
||||
LONG image_width = 48, height = 48, line_count, text_width;
|
||||
HFONT hfont, prev_font;
|
||||
DWORD style, type;
|
||||
BOOL ret;
|
||||
|
@ -1453,7 +1936,7 @@ static void test_bcm_get_ideal_size(void)
|
|||
HIMAGELIST himl;
|
||||
BUTTON_IMAGELIST biml = {0};
|
||||
RECT rect;
|
||||
INT i, j;
|
||||
INT i, j, k;
|
||||
|
||||
/* Check for NULL pointer handling */
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_PUSHBUTTON | default_style, 0, 0, client_width, client_height,
|
||||
|
@ -1496,34 +1979,49 @@ static void test_bcm_get_ideal_size(void)
|
|||
|
||||
/* Tests for image placements */
|
||||
/* Prepare bitmap */
|
||||
image_width = 48;
|
||||
height = 48;
|
||||
hdc = GetDC(0);
|
||||
hmask = CreateCompatibleBitmap(hdc, image_width, height);
|
||||
hbmp = CreateCompatibleBitmap(hdc, image_width, height);
|
||||
himl = pImageList_Create(image_width, height, ILC_COLOR, 1, 1);
|
||||
pImageList_Add(himl, hbmp, 0);
|
||||
|
||||
#define set_split_info(hwnd) do { \
|
||||
BUTTON_SPLITINFO _info; \
|
||||
int _ret; \
|
||||
_info.mask = BCSIF_SIZE; \
|
||||
_info.size.cx = extra_width; \
|
||||
_info.size.cy = large_height; \
|
||||
_ret = SendMessageA(hwnd, BCM_SETSPLITINFO, 0, (LPARAM)&_info); \
|
||||
ok(_ret == TRUE, "Expected BCM_SETSPLITINFO message to return true\n"); \
|
||||
} while (0)
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(pushtype); k++)
|
||||
{
|
||||
/* Only bitmap for push button, ideal size should be enough for image and text */
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | BS_BITMAP | default_style, 0, 0, client_width,
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, pushtype[k].style | BS_BITMAP | default_style, 0, 0, client_width,
|
||||
client_height, NULL, NULL, 0, NULL);
|
||||
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||
set_split_info(hwnd);
|
||||
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||
ZeroMemory(&size, sizeof(size));
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||
/* Ideal size contains text rect even show bitmap only */
|
||||
ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)),
|
||||
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, image_width + text_width,
|
||||
size.cy, max(height, tm.tmHeight));
|
||||
ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight),
|
||||
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
|
||||
image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight));
|
||||
ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height);
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
/* Image alignments when button has bitmap and text*/
|
||||
for (i = 0; i < ARRAY_SIZE(aligns); i++)
|
||||
for (j = 0; j < ARRAY_SIZE(aligns); j++)
|
||||
{
|
||||
style = BS_DEFPUSHBUTTON | default_style | aligns[i] | aligns[j];
|
||||
style = pushtype[k].style | default_style | aligns[i] | aligns[j];
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, style, 0, 0, client_width, client_height, NULL, NULL, 0, NULL);
|
||||
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||
set_split_info(hwnd);
|
||||
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||
ZeroMemory(&size, sizeof(size));
|
||||
|
@ -1531,42 +2029,44 @@ static void test_bcm_get_ideal_size(void)
|
|||
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||
if (!(style & (BS_CENTER | BS_VCENTER)) || ((style & BS_CENTER) && (style & BS_CENTER) != BS_CENTER)
|
||||
|| !(style & BS_VCENTER) || (style & BS_VCENTER) == BS_VCENTER)
|
||||
ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)),
|
||||
ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight),
|
||||
"Style: 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", style, size.cx,
|
||||
image_width + text_width, size.cy, max(height, tm.tmHeight));
|
||||
image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight));
|
||||
else
|
||||
ok((size.cx >= max(text_width, height) && size.cy >= height + tm.tmHeight),
|
||||
ok(size.cx >= max(text_width, height) + pushtype[k].extra_width && size.cy >= height + tm.tmHeight,
|
||||
"Style: 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", style, size.cx,
|
||||
max(text_width, height), size.cy, height + tm.tmHeight);
|
||||
max(text_width, height) + pushtype[k].extra_width, size.cy, height + tm.tmHeight);
|
||||
ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height);
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
/* Image list alignments */
|
||||
himl = pImageList_Create(image_width, height, ILC_COLOR, 1, 1);
|
||||
pImageList_Add(himl, hbmp, 0);
|
||||
biml.himl = himl;
|
||||
for (i = 0; i < ARRAY_SIZE(imagelist_aligns); i++)
|
||||
{
|
||||
biml.uAlign = imagelist_aligns[i];
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | default_style, 0, 0, client_width,
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, pushtype[k].style | default_style, 0, 0, client_width,
|
||||
client_height, NULL, NULL, 0, NULL);
|
||||
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||
set_split_info(hwnd);
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||
SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml);
|
||||
ZeroMemory(&size, sizeof(size));
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||
if (biml.uAlign == BUTTON_IMAGELIST_ALIGN_TOP || biml.uAlign == BUTTON_IMAGELIST_ALIGN_BOTTOM)
|
||||
ok((size.cx >= max(text_width, height) && size.cy >= height + tm.tmHeight),
|
||||
ok(size.cx >= max(text_width, height) + pushtype[k].extra_width && size.cy >= height + tm.tmHeight,
|
||||
"Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n", biml.uAlign, size.cx,
|
||||
max(text_width, height), size.cy, height + tm.tmHeight);
|
||||
max(text_width, height) + pushtype[k].extra_width, size.cy, height + tm.tmHeight);
|
||||
else if (biml.uAlign == BUTTON_IMAGELIST_ALIGN_LEFT || biml.uAlign == BUTTON_IMAGELIST_ALIGN_RIGHT)
|
||||
ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)),
|
||||
ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight),
|
||||
"Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n", biml.uAlign, size.cx,
|
||||
image_width + text_width, size.cy, max(height, tm.tmHeight));
|
||||
image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight));
|
||||
else
|
||||
ok(size.cx >= image_width && size.cy >= height, "Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n",
|
||||
biml.uAlign, size.cx, image_width, size.cy, height);
|
||||
ok(size.cx >= image_width + pushtype[k].extra_width && size.cy >= height,
|
||||
"Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n",
|
||||
biml.uAlign, size.cx, image_width + pushtype[k].extra_width, size.cy, height);
|
||||
ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height);
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
|
@ -1579,33 +2079,41 @@ static void test_bcm_get_ideal_size(void)
|
|||
hicon = CreateIconIndirect(&icon_info);
|
||||
|
||||
/* Only icon, ideal size should be enough for image and text */
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | BS_ICON | default_style, 0, 0, client_width,
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, pushtype[k].style | BS_ICON | default_style, 0, 0, client_width,
|
||||
client_height, NULL, NULL, 0, NULL);
|
||||
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||
set_split_info(hwnd);
|
||||
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon);
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||
ZeroMemory(&size, sizeof(size));
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||
/* Ideal size contains text rect even show icons only */
|
||||
ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)),
|
||||
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, image_width + text_width, size.cy,
|
||||
max(height, tm.tmHeight));
|
||||
ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight),
|
||||
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
|
||||
image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight));
|
||||
ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height);
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
/* Show icon and text */
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_DEFPUSHBUTTON | default_style, 0, 0, client_width,
|
||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, pushtype[k].style | default_style, 0, 0, client_width,
|
||||
client_height, NULL, NULL, 0, NULL);
|
||||
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||
set_split_info(hwnd);
|
||||
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon);
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||
ZeroMemory(&size, sizeof(size));
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||
ok((size.cx >= image_width + text_width && size.cy >= max(height, tm.tmHeight)),
|
||||
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, image_width + text_width, size.cy,
|
||||
max(height, tm.tmHeight));
|
||||
ok(size.cx >= image_width + text_width + pushtype[k].extra_width && size.cy >= max(height, tm.tmHeight),
|
||||
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
|
||||
image_width + text_width + pushtype[k].extra_width, size.cy, max(height, tm.tmHeight));
|
||||
ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height);
|
||||
DestroyWindow(hwnd);
|
||||
DestroyIcon(hicon);
|
||||
}
|
||||
|
||||
#undef set_split_info
|
||||
|
||||
/* Checkbox */
|
||||
/* Both bitmap and text for checkbox, ideal size is only enough for text because it doesn't support image(but not image list)*/
|
||||
|
@ -1667,7 +2175,7 @@ static void test_bcm_get_ideal_size(void)
|
|||
|
||||
if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK)
|
||||
{
|
||||
todo_wine ok((size.cx == 0 && size.cy > 0), "Style 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n",
|
||||
ok((size.cx == 0 && size.cy > 0), "Style 0x%08x expect ideal cx %d == %d and ideal cy %d > %d\n",
|
||||
style, size.cx, 0, size.cy, 0);
|
||||
}
|
||||
else
|
||||
|
@ -1704,8 +2212,8 @@ static void test_bcm_get_ideal_size(void)
|
|||
}
|
||||
else if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK)
|
||||
{
|
||||
todo_wine ok((size.cx == 0 && size.cy > 0),
|
||||
"Style 0x%08x expect ideal cx %d >= %d and ideal cy %d >= %d\n", style, size.cx, 0,
|
||||
ok((size.cx == 0 && size.cy > 0),
|
||||
"Style 0x%08x expect ideal cx %d == %d and ideal cy %d > %d\n", style, size.cx, 0,
|
||||
size.cy, 0);
|
||||
}
|
||||
else
|
||||
|
@ -1718,8 +2226,58 @@ static void test_bcm_get_ideal_size(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* Command Link with note */
|
||||
hwnd = CreateWindowA(WC_BUTTONA, "a", style, 0, 0, client_width, client_height, NULL, NULL, 0, NULL);
|
||||
ok(hwnd != NULL, "Expected hwnd not NULL\n");
|
||||
SendMessageA(hwnd, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp);
|
||||
ret = SendMessageA(hwnd, BCM_SETNOTE, 0, (LPARAM)button_note_short);
|
||||
ok(ret == TRUE, "Expected BCM_SETNOTE to return true\n");
|
||||
size.cx = 13;
|
||||
size.cy = 0;
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n");
|
||||
ok(size.cx == 13 && size.cy > 0, "Expected ideal cx %d == %d and ideal cy %d > %d\n", size.cx, 13, size.cy, 0);
|
||||
height = size.cy;
|
||||
size.cx = 32767;
|
||||
size.cy = 7;
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n");
|
||||
ok(size.cx < 32767, "Expected ideal cx to have been adjusted\n");
|
||||
ok(size.cx > image_width && size.cy == height, "Expected ideal cx %d > %d and ideal cy %d == %d\n", size.cx, image_width, size.cy, height);
|
||||
|
||||
/* Try longer note without word breaks, shouldn't extend height because no word splitting */
|
||||
ret = SendMessageA(hwnd, BCM_SETNOTE, 0, (LPARAM)button_note_long);
|
||||
ok(ret == TRUE, "Expected BCM_SETNOTE to return true\n");
|
||||
k = size.cx;
|
||||
size.cy = 0;
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n");
|
||||
ok(size.cx == k && size.cy == height, "Expected ideal cx %d == %d and ideal cy %d == %d\n", size.cx, k, size.cy, height);
|
||||
|
||||
/* Now let it extend the width */
|
||||
size.cx = 32767;
|
||||
size.cy = 0;
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n");
|
||||
ok(size.cx > k && size.cy == height, "Expected ideal cx %d > %d and ideal cy %d == %d\n", size.cx, k, size.cy, height);
|
||||
|
||||
/* Use a very long note with words and the same width, should extend the height due to word wrap */
|
||||
ret = SendMessageA(hwnd, BCM_SETNOTE, 0, (LPARAM)button_note_wordy);
|
||||
ok(ret == TRUE, "Expected BCM_SETNOTE to return true\n");
|
||||
k = size.cx;
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n");
|
||||
ok(size.cx <= k && size.cy > height, "Expected ideal cx %d <= %d and ideal cy %d > %d\n", size.cx, k, size.cy, height);
|
||||
|
||||
/* Now try the wordy note with a width smaller than the image itself, which prevents wrapping */
|
||||
size.cx = 13;
|
||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||
ok(ret == TRUE, "Expected BCM_GETIDEALSIZE message to return true\n");
|
||||
ok(size.cx == 13 && size.cy == height, "Expected ideal cx %d == %d and ideal cy %d == %d\n", size.cx, 13, size.cy, height);
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
|
||||
pImageList_Destroy(himl);
|
||||
DestroyIcon(hicon);
|
||||
DeleteObject(hbmp);
|
||||
DeleteObject(hmask);
|
||||
ReleaseDC(0, hdc);
|
||||
|
|
|
@ -1485,16 +1485,31 @@ static void test_edit_control_scroll(void)
|
|||
DestroyWindow (hwEdit);
|
||||
}
|
||||
|
||||
static BOOL is_cjk(HDC dc)
|
||||
{
|
||||
const DWORD FS_DBCS_MASK = FS_JISJAPAN|FS_CHINESESIMP|FS_WANSUNG|FS_CHINESETRAD|FS_JOHAB;
|
||||
FONTSIGNATURE fs;
|
||||
|
||||
switch (GdiGetCodePage(dc)) {
|
||||
case 932: case 936: case 949: case 950: case 1361:
|
||||
return TRUE;
|
||||
default:
|
||||
return (GetTextCharsetInfo(dc, &fs, 0) != DEFAULT_CHARSET &&
|
||||
(fs.fsCsb[0] & FS_DBCS_MASK));
|
||||
}
|
||||
}
|
||||
|
||||
static void test_margins_usefontinfo(UINT charset)
|
||||
{
|
||||
INT margins, threshold, expect, empty_expect, small_expect;
|
||||
HWND hwnd;
|
||||
HDC hdc;
|
||||
TEXTMETRICW tm;
|
||||
SIZE size;
|
||||
BOOL cjk;
|
||||
LOGFONTA lf;
|
||||
HFONT hfont;
|
||||
RECT rect;
|
||||
INT margins, threshold, expect, empty_expect;
|
||||
const UINT small_margins = MAKELONG(1, 5);
|
||||
|
||||
memset(&lf, 0, sizeof(lf));
|
||||
lf.lfHeight = -11;
|
||||
|
@ -1513,43 +1528,31 @@ static void test_margins_usefontinfo(UINT charset)
|
|||
|
||||
hdc = GetDC(hwnd);
|
||||
hfont = SelectObject(hdc, hfont);
|
||||
size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy );
|
||||
expect = MAKELONG(size.cx / 2, size.cx / 2);
|
||||
small_expect = 0;
|
||||
empty_expect = size.cx >= 28 ? small_expect : expect;
|
||||
|
||||
charset = GetTextCharset(hdc);
|
||||
switch (charset)
|
||||
{
|
||||
case SHIFTJIS_CHARSET:
|
||||
case HANGUL_CHARSET:
|
||||
case GB2312_CHARSET:
|
||||
case CHINESEBIG5_CHARSET:
|
||||
cjk = TRUE;
|
||||
break;
|
||||
default:
|
||||
cjk = FALSE;
|
||||
size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
|
||||
if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
|
||||
!(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
|
||||
skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
|
||||
hfont = SelectObject(hdc, hfont);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
DestroyWindow(hwnd);
|
||||
DeleteObject(hfont);
|
||||
return;
|
||||
}
|
||||
|
||||
expect = MAKELONG(size.cx / 2, size.cx / 2);
|
||||
hfont = SelectObject(hdc, hfont);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == 0, "got %x\n", margins);
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
if (!cjk)
|
||||
ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
||||
else
|
||||
{
|
||||
ok(HIWORD(margins) > 0 && LOWORD(margins) > 0, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
||||
expect = empty_expect = small_expect = margins;
|
||||
}
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
|
||||
expect = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
threshold = (size.cx / 2 + size.cx) * 2;
|
||||
threshold = HIWORD(expect) + LOWORD(expect) + size.cx * 2;
|
||||
empty_expect = threshold > 80 ? small_margins : expect;
|
||||
|
||||
/* Size below which non-cjk margins are zero */
|
||||
/* Size below the threshold, margins remain unchanged */
|
||||
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold - 1, 100, NULL, NULL, NULL, NULL);
|
||||
ok(hwnd != NULL, "got %p\n", hwnd);
|
||||
GetClientRect(hwnd, &rect);
|
||||
|
@ -1559,11 +1562,13 @@ static void test_margins_usefontinfo(UINT charset)
|
|||
ok(margins == 0, "got %x\n", margins);
|
||||
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == small_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
||||
ok(margins == small_margins, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
/* Size at which non-cjk margins become non-zero */
|
||||
/* Size at the threshold, margins become non-zero */
|
||||
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold, 100, NULL, NULL, NULL, NULL);
|
||||
ok(hwnd != NULL, "got %p\n", hwnd);
|
||||
GetClientRect(hwnd, &rect);
|
||||
|
@ -1573,6 +1578,8 @@ static void test_margins_usefontinfo(UINT charset)
|
|||
ok(margins == 0, "got %x\n", margins);
|
||||
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
||||
DestroyWindow(hwnd);
|
||||
|
@ -1587,6 +1594,8 @@ static void test_margins_usefontinfo(UINT charset)
|
|||
ok(margins == 0, "got %x\n", margins);
|
||||
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
||||
DestroyWindow(hwnd);
|
||||
|
@ -1594,6 +1603,151 @@ static void test_margins_usefontinfo(UINT charset)
|
|||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
static INT get_cjk_fontinfo_margin(INT width, INT side_bearing)
|
||||
{
|
||||
INT margin;
|
||||
if (side_bearing < 0)
|
||||
margin = min(-side_bearing, width/2);
|
||||
else
|
||||
margin = 0;
|
||||
return margin;
|
||||
}
|
||||
|
||||
static DWORD get_cjk_font_margins(HDC hdc)
|
||||
{
|
||||
ABC abc[256];
|
||||
SHORT left, right;
|
||||
UINT i;
|
||||
|
||||
if (!GetCharABCWidthsW(hdc, 0, 255, abc))
|
||||
return 0;
|
||||
|
||||
left = right = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(abc); i++) {
|
||||
if (-abc[i].abcA > right) right = -abc[i].abcA;
|
||||
if (-abc[i].abcC > left) left = -abc[i].abcC;
|
||||
}
|
||||
return MAKELONG(left, right);
|
||||
}
|
||||
|
||||
static void test_margins_default(const char* facename, UINT charset)
|
||||
{
|
||||
HWND hwnd;
|
||||
HDC hdc;
|
||||
TEXTMETRICW tm;
|
||||
SIZE size;
|
||||
BOOL cjk;
|
||||
LOGFONTA lf;
|
||||
HFONT hfont;
|
||||
RECT rect;
|
||||
INT margins, expect, font_expect;
|
||||
const UINT small_margins = MAKELONG(1, 5);
|
||||
const WCHAR EditW[] = {'E','d','i','t',0}, strW[] = {'W',0};
|
||||
struct char_width_info {
|
||||
INT lsb, rsb, unknown;
|
||||
} info;
|
||||
HMODULE hgdi32;
|
||||
BOOL (WINAPI *pGetCharWidthInfo)(HDC, struct char_width_info *);
|
||||
|
||||
hgdi32 = GetModuleHandleA("gdi32.dll");
|
||||
pGetCharWidthInfo = (void *)GetProcAddress(hgdi32, "GetCharWidthInfo");
|
||||
|
||||
memset(&lf, 0, sizeof(lf));
|
||||
lf.lfHeight = -11;
|
||||
lf.lfWeight = FW_NORMAL;
|
||||
lf.lfCharSet = charset;
|
||||
strcpy(lf.lfFaceName, facename);
|
||||
|
||||
hfont = CreateFontIndirectA(&lf);
|
||||
ok(hfont != NULL, "got %p\n", hfont);
|
||||
|
||||
/* Unicode version */
|
||||
hwnd = CreateWindowExW(0, EditW, strW, WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
|
||||
ok(hwnd != NULL, "got %p\n", hwnd);
|
||||
GetClientRect(hwnd, &rect);
|
||||
ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
|
||||
|
||||
hdc = GetDC(hwnd);
|
||||
hfont = SelectObject(hdc, hfont);
|
||||
size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
|
||||
if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
|
||||
!(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
|
||||
skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
|
||||
hfont = SelectObject(hdc, hfont);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
DestroyWindow(hwnd);
|
||||
DeleteObject(hfont);
|
||||
return;
|
||||
}
|
||||
cjk = is_cjk(hdc);
|
||||
if (cjk && pGetCharWidthInfo && pGetCharWidthInfo(hdc, &info)) {
|
||||
short left, right;
|
||||
|
||||
left = get_cjk_fontinfo_margin(size.cx, info.lsb);
|
||||
right = get_cjk_fontinfo_margin(size.cx, info.rsb);
|
||||
expect = MAKELONG(left, right);
|
||||
|
||||
font_expect = get_cjk_font_margins(hdc);
|
||||
if (!font_expect)
|
||||
/* In this case, margins aren't updated */
|
||||
font_expect = small_margins;
|
||||
}
|
||||
else
|
||||
font_expect = expect = MAKELONG(size.cx / 2, size.cx / 2);
|
||||
|
||||
hfont = SelectObject(hdc, hfont);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == 0, "got %x\n", margins);
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins));
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
/* ANSI version */
|
||||
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
|
||||
ok(hwnd != NULL, "got %p\n", hwnd);
|
||||
GetClientRect(hwnd, &rect);
|
||||
ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
|
||||
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == 0, "got %x\n", margins);
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
|
||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins));
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
|
||||
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
|
||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||
ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
|
||||
DestroyWindow(hwnd);
|
||||
|
||||
DeleteObject(hfont);
|
||||
}
|
||||
|
||||
static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL is_font_installed(const char*name)
|
||||
{
|
||||
HDC hdc = GetDC(NULL);
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!EnumFontFamiliesA(hdc, name, find_font_proc, 0))
|
||||
ret = TRUE;
|
||||
|
||||
ReleaseDC(NULL, hdc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void test_margins(void)
|
||||
{
|
||||
DWORD old_margins, new_margins;
|
||||
|
@ -1668,27 +1822,45 @@ static void test_margins(void)
|
|||
but not by < Win 8 and Win 10. */
|
||||
|
||||
test_margins_usefontinfo(DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
|
||||
{
|
||||
return 0;
|
||||
test_margins_default("Tahoma", ANSI_CHARSET);
|
||||
test_margins_default("Tahoma", EASTEUROPE_CHARSET);
|
||||
|
||||
test_margins_default("Tahoma", HANGUL_CHARSET);
|
||||
test_margins_default("Tahoma", CHINESEBIG5_CHARSET);
|
||||
|
||||
if (is_font_installed("MS PGothic")) {
|
||||
test_margins_default("MS PGothic", SHIFTJIS_CHARSET);
|
||||
test_margins_default("MS PGothic", GREEK_CHARSET);
|
||||
}
|
||||
else
|
||||
skip("MS PGothic is not available, skipping some margin tests\n");
|
||||
|
||||
if (is_font_installed("Ume P Gothic")) {
|
||||
test_margins_default("Ume P Gothic", SHIFTJIS_CHARSET);
|
||||
test_margins_default("Ume P Gothic", GREEK_CHARSET);
|
||||
}
|
||||
else
|
||||
skip("Ume P Gothic is not available, skipping some margin tests\n");
|
||||
|
||||
if (is_font_installed("SimSun")) {
|
||||
test_margins_default("SimSun", GB2312_CHARSET);
|
||||
test_margins_default("SimSun", ANSI_CHARSET);
|
||||
}
|
||||
else
|
||||
skip("SimSun is not available, skipping some margin tests\n");
|
||||
}
|
||||
|
||||
static void test_margins_font_change(void)
|
||||
{
|
||||
DWORD margins, font_margins, ret;
|
||||
DWORD margins, font_margins;
|
||||
HFONT hfont, hfont2;
|
||||
HWND hwEdit;
|
||||
LOGFONTA lf;
|
||||
HDC hdc;
|
||||
|
||||
hdc = GetDC(0);
|
||||
ret = EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0);
|
||||
ReleaseDC(0, hdc);
|
||||
if (ret)
|
||||
if (!is_font_installed("Arial"))
|
||||
{
|
||||
trace("Arial not found - skipping font change margin tests\n");
|
||||
skip("Arial not found - skipping font change margin tests\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1699,7 +1871,7 @@ static void test_margins_font_change(void)
|
|||
memset(&lf, 0, sizeof(lf));
|
||||
strcpy(lf.lfFaceName, "Arial");
|
||||
lf.lfHeight = 16;
|
||||
lf.lfCharSet = DEFAULT_CHARSET;
|
||||
lf.lfCharSet = GREEK_CHARSET; /* to avoid associated charset feature */
|
||||
hfont = CreateFontIndirectA(&lf);
|
||||
lf.lfHeight = 30;
|
||||
hfont2 = CreateFontIndirectA(&lf);
|
||||
|
@ -3143,6 +3315,9 @@ static void test_change_focus(void)
|
|||
HWND hwnd, parent_wnd;
|
||||
WNDPROC oldproc;
|
||||
MSG msg;
|
||||
POINT orig_pos;
|
||||
|
||||
GetCursorPos(&orig_pos);
|
||||
|
||||
parent_wnd = CreateWindowA("ParentWnd", "", WS_OVERLAPPEDWINDOW,
|
||||
0, 0, 200, 200, NULL, NULL, GetModuleHandleA(NULL), NULL);
|
||||
|
@ -3157,6 +3332,8 @@ static void test_change_focus(void)
|
|||
oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)edit_subclass_proc);
|
||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
|
||||
|
||||
SetCursorPos(400, 400);
|
||||
|
||||
SetFocus(parent_wnd);
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
SetFocus(hwnd);
|
||||
|
@ -3168,6 +3345,8 @@ static void test_change_focus(void)
|
|||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, killfocus_combined_seq, "Kill focus", TRUE);
|
||||
|
||||
SetCursorPos(orig_pos.x, orig_pos.y);
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
|
|
|
@ -1563,7 +1563,6 @@ cleanup:
|
|||
if(hbmDst)
|
||||
DeleteObject(hbmDst);
|
||||
|
||||
if(hdcDst)
|
||||
DeleteDC(hdcDst);
|
||||
|
||||
if(hbmMask)
|
||||
|
@ -2181,7 +2180,7 @@ static void test_color_table(UINT ilc)
|
|||
rgb[2].rgbBlue = 0xff;
|
||||
check_color_table("remove all, add 8", hdc, himl, ilc, rgb, default_table);
|
||||
|
||||
/* remove all, add 4. Color table remains the same since it's inplicitly
|
||||
/* remove all, add 4. Color table remains the same since it's implicitly
|
||||
been set by the previous _Add */
|
||||
ret = pImageList_Remove(himl, -1);
|
||||
ok(ret, "got %d\n", ret);
|
||||
|
|
|
@ -784,6 +784,135 @@ static void test_listbox_height(void)
|
|||
DestroyWindow( hList );
|
||||
}
|
||||
|
||||
static void test_changing_selection_styles(void)
|
||||
{
|
||||
static const DWORD styles[] =
|
||||
{
|
||||
0,
|
||||
LBS_NODATA | LBS_OWNERDRAWFIXED
|
||||
};
|
||||
static const DWORD selstyles[] =
|
||||
{
|
||||
0,
|
||||
LBS_MULTIPLESEL,
|
||||
LBS_EXTENDEDSEL,
|
||||
LBS_MULTIPLESEL | LBS_EXTENDEDSEL
|
||||
};
|
||||
static const LONG selexpect_single[] = { 0, 0, 1 };
|
||||
static const LONG selexpect_single2[] = { 1, 0, 0 };
|
||||
static const LONG selexpect_multi[] = { 1, 0, 1 };
|
||||
static const LONG selexpect_multi2[] = { 1, 1, 0 };
|
||||
|
||||
HWND parent, listbox;
|
||||
DWORD style;
|
||||
LONG ret;
|
||||
UINT i, j, k;
|
||||
|
||||
parent = create_parent();
|
||||
ok(parent != NULL, "Failed to create parent window.\n");
|
||||
for (i = 0; i < ARRAY_SIZE(styles); i++)
|
||||
{
|
||||
/* Test if changing selection styles affects selection storage */
|
||||
for (j = 0; j < ARRAY_SIZE(selstyles); j++)
|
||||
{
|
||||
LONG setcursel_expect, selitemrange_expect, getselcount_expect;
|
||||
const LONG *selexpect;
|
||||
|
||||
listbox = CreateWindowA(WC_LISTBOXA, "TestList", styles[i] | selstyles[j] | WS_CHILD | WS_VISIBLE,
|
||||
0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0);
|
||||
ok(listbox != NULL, "%u: Failed to create ListBox window.\n", j);
|
||||
|
||||
if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
|
||||
{
|
||||
setcursel_expect = LB_ERR;
|
||||
selitemrange_expect = LB_OKAY;
|
||||
getselcount_expect = 2;
|
||||
selexpect = selexpect_multi;
|
||||
}
|
||||
else
|
||||
{
|
||||
setcursel_expect = 2;
|
||||
selitemrange_expect = LB_ERR;
|
||||
getselcount_expect = LB_ERR;
|
||||
selexpect = selexpect_single;
|
||||
}
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
|
||||
{
|
||||
ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"x");
|
||||
ok(ret == k, "%u: Unexpected return value %d, expected %d.\n", j, ret, k);
|
||||
}
|
||||
ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
|
||||
ok(ret == ARRAY_SIZE(selexpect_multi), "%u: Unexpected count %d.\n", j, ret);
|
||||
|
||||
/* Select items with different methods */
|
||||
ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0);
|
||||
ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
|
||||
ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 0));
|
||||
ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
|
||||
ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 2));
|
||||
ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
|
||||
|
||||
/* Verify that the proper items are selected */
|
||||
for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
|
||||
{
|
||||
ret = SendMessageA(listbox, LB_GETSEL, k, 0);
|
||||
ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
|
||||
j, ret, selexpect[k]);
|
||||
}
|
||||
|
||||
/* Now change the selection style */
|
||||
style = GetWindowLongA(listbox, GWL_STYLE);
|
||||
ok((style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == selstyles[j],
|
||||
"%u: unexpected window styles %#x.\n", j, style);
|
||||
if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
|
||||
style &= ~selstyles[j];
|
||||
else
|
||||
style |= LBS_MULTIPLESEL | LBS_EXTENDEDSEL;
|
||||
SetWindowLongA(listbox, GWL_STYLE, style);
|
||||
style = GetWindowLongA(listbox, GWL_STYLE);
|
||||
ok(!(style & selstyles[j]), "%u: unexpected window styles %#x.\n", j, style);
|
||||
|
||||
/* Verify that the same items are selected */
|
||||
ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
|
||||
ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
|
||||
j, getselcount_expect, ret);
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
|
||||
{
|
||||
ret = SendMessageA(listbox, LB_GETSEL, k, 0);
|
||||
ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
|
||||
j, ret, selexpect[k]);
|
||||
}
|
||||
|
||||
/* Lastly see if we can still change the selection as before with old style */
|
||||
if (setcursel_expect != LB_ERR) setcursel_expect = 0;
|
||||
ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0);
|
||||
ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
|
||||
ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 1));
|
||||
ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
|
||||
ret = SendMessageA(listbox, LB_SELITEMRANGE, FALSE, MAKELPARAM(2, 2));
|
||||
ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
|
||||
|
||||
/* And verify the selections */
|
||||
selexpect = (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) ? selexpect_multi2 : selexpect_single2;
|
||||
ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
|
||||
ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
|
||||
j, getselcount_expect, ret);
|
||||
|
||||
for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
|
||||
{
|
||||
ret = SendMessageA(listbox, LB_GETSEL, k, 0);
|
||||
ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
|
||||
j, ret, selexpect[k]);
|
||||
}
|
||||
|
||||
DestroyWindow(listbox);
|
||||
}
|
||||
}
|
||||
DestroyWindow(parent);
|
||||
}
|
||||
|
||||
static void test_itemfrompoint(void)
|
||||
{
|
||||
/* WS_POPUP is required in order to have a more accurate size calculation (
|
||||
|
@ -1812,7 +1941,7 @@ static void test_listbox_dlgdir(void)
|
|||
strcpy(pathBuffer, "C:\\");
|
||||
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
|
||||
ok(res, "DlgDirList failed to list C:\\ folders\n");
|
||||
todo_wine ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
|
||||
ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
|
||||
|
||||
strcpy(pathBuffer, "C:\\*");
|
||||
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
|
||||
|
@ -1823,8 +1952,8 @@ static void test_listbox_dlgdir(void)
|
|||
SetLastError(0xdeadbeef);
|
||||
strcpy(pathBuffer, "C:\\INVALID$$DIR");
|
||||
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
|
||||
todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
|
||||
todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
|
||||
ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
|
||||
ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
|
||||
"GetLastError should return 0x589, got 0x%X\n",GetLastError());
|
||||
|
||||
DestroyWindow(hWnd);
|
||||
|
@ -1867,6 +1996,11 @@ static void test_set_count( void )
|
|||
GetUpdateRect( listbox, &r, TRUE );
|
||||
ok( !IsRectEmpty( &r ), "got empty rect\n");
|
||||
|
||||
ret = SendMessageA( listbox, LB_SETCOUNT, -5, 0 );
|
||||
ok( ret == 0, "got %d\n", ret );
|
||||
ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
|
||||
ok( ret == -5, "got %d\n", ret );
|
||||
|
||||
DestroyWindow( listbox );
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(styles); ++i)
|
||||
|
@ -1906,6 +2040,69 @@ static void test_GetListBoxInfo(void)
|
|||
DestroyWindow(parent);
|
||||
}
|
||||
|
||||
static void test_init_storage( void )
|
||||
{
|
||||
static const DWORD styles[] =
|
||||
{
|
||||
LBS_HASSTRINGS,
|
||||
LBS_NODATA | LBS_OWNERDRAWFIXED,
|
||||
};
|
||||
HWND parent, listbox;
|
||||
LONG ret, items_size;
|
||||
int i, j;
|
||||
|
||||
parent = create_parent();
|
||||
for (i = 0; i < ARRAY_SIZE(styles); i++)
|
||||
{
|
||||
listbox = CreateWindowA(WC_LISTBOXA, "TestList", styles[i] | WS_CHILD,
|
||||
0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0);
|
||||
|
||||
items_size = SendMessageA(listbox, LB_INITSTORAGE, 100, 0);
|
||||
ok(items_size >= 100, "expected at least 100, got %d\n", items_size);
|
||||
|
||||
ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
|
||||
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
|
||||
|
||||
/* it doesn't grow since the space was already reserved */
|
||||
ret = SendMessageA(listbox, LB_INITSTORAGE, items_size, 0);
|
||||
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
|
||||
|
||||
/* it doesn't shrink the reserved space */
|
||||
ret = SendMessageA(listbox, LB_INITSTORAGE, 42, 0);
|
||||
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
|
||||
|
||||
/* now populate almost all of it so it's not reserved anymore */
|
||||
if (styles[i] & LBS_NODATA)
|
||||
{
|
||||
ret = SendMessageA(listbox, LB_SETCOUNT, items_size - 1, 0);
|
||||
ok(ret == 0, "unexpected return value %d\n", ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 0; j < items_size - 1; j++)
|
||||
{
|
||||
ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
|
||||
ok(ret == j, "expected %d, got %d\n", j, ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* we still have one more reserved slot, so it doesn't grow yet */
|
||||
ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
|
||||
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
|
||||
|
||||
/* fill the slot and check again, it should grow this time */
|
||||
ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
|
||||
ok(ret == items_size - 1, "expected %d, got %d\n", items_size - 1, ret);
|
||||
ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
|
||||
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
|
||||
ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
|
||||
ok(ret > items_size, "expected it to grow past %d, got %d\n", items_size, ret);
|
||||
|
||||
DestroyWindow(listbox);
|
||||
}
|
||||
DestroyWindow(parent);
|
||||
}
|
||||
|
||||
static void test_missing_lbuttonup(void)
|
||||
{
|
||||
HWND listbox, parent, capture;
|
||||
|
@ -2420,11 +2617,13 @@ START_TEST(listbox)
|
|||
test_LB_SELITEMRANGE();
|
||||
test_LB_SETCURSEL();
|
||||
test_listbox_height();
|
||||
test_changing_selection_styles();
|
||||
test_itemfrompoint();
|
||||
test_listbox_item_data();
|
||||
test_listbox_LB_DIR();
|
||||
test_listbox_dlgdir();
|
||||
test_set_count();
|
||||
test_init_storage();
|
||||
test_GetListBoxInfo();
|
||||
test_missing_lbuttonup();
|
||||
test_extents();
|
||||
|
|
|
@ -6475,6 +6475,86 @@ static void test_LVM_GETCOUNTPERPAGE(void)
|
|||
ok(ret, "Failed to unregister test class.\n");
|
||||
}
|
||||
|
||||
static void test_item_state_change(void)
|
||||
{
|
||||
static const DWORD styles[] = { LVS_ICON, LVS_LIST, LVS_REPORT, LVS_SMALLICON };
|
||||
LVITEMA item;
|
||||
HWND hwnd;
|
||||
DWORD res;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(styles); i++)
|
||||
{
|
||||
hwnd = create_listview_control(styles[i]);
|
||||
|
||||
insert_item(hwnd, 0);
|
||||
|
||||
/* LVM_SETITEMSTATE with mask */
|
||||
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
|
||||
memset(&item, 0, sizeof(item));
|
||||
item.mask = LVIF_STATE;
|
||||
item.stateMask = LVIS_SELECTED;
|
||||
item.state = LVIS_SELECTED;
|
||||
res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
|
||||
ok(res, "Failed to set item state.\n");
|
||||
|
||||
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
|
||||
ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
|
||||
ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
|
||||
ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState);
|
||||
ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
|
||||
ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
|
||||
|
||||
/* LVM_SETITEMSTATE 0 mask */
|
||||
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
|
||||
memset(&item, 0, sizeof(item));
|
||||
item.stateMask = LVIS_SELECTED;
|
||||
item.state = 0;
|
||||
res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
|
||||
ok(res, "Failed to set item state.\n");
|
||||
|
||||
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
|
||||
ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
|
||||
ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
|
||||
ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState);
|
||||
ok(g_nmlistview.uOldState == LVIS_SELECTED, "Unexpected old state %#x.\n", g_nmlistview.uOldState);
|
||||
ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
|
||||
|
||||
/* LVM_SETITEM changes state */
|
||||
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
|
||||
memset(&item, 0, sizeof(item));
|
||||
item.stateMask = LVIS_SELECTED;
|
||||
item.state = LVIS_SELECTED;
|
||||
item.mask = LVIF_STATE;
|
||||
res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
|
||||
ok(res, "Failed to set item.\n");
|
||||
|
||||
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
|
||||
ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
|
||||
ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
|
||||
ok(g_nmlistview.uNewState == LVIS_SELECTED, "Unexpected new state %#x.\n", g_nmlistview.uNewState);
|
||||
ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState);
|
||||
ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
|
||||
|
||||
/* LVM_SETITEM no state changes */
|
||||
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
|
||||
memset(&item, 0, sizeof(item));
|
||||
item.lParam = 11;
|
||||
item.mask = LVIF_PARAM;
|
||||
res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
|
||||
ok(res, "Failed to set item.\n");
|
||||
|
||||
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
|
||||
ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
|
||||
ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
|
||||
ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState);
|
||||
ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState);
|
||||
ok(g_nmlistview.uChanged == LVIF_PARAM, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(listview)
|
||||
{
|
||||
ULONG_PTR ctx_cookie;
|
||||
|
@ -6538,6 +6618,7 @@ START_TEST(listview)
|
|||
test_LVSCW_AUTOSIZE();
|
||||
test_LVN_ENDLABELEDIT();
|
||||
test_LVM_GETCOUNTPERPAGE();
|
||||
test_item_state_change();
|
||||
|
||||
if (!load_v6_module(&ctx_cookie, &hCtx))
|
||||
{
|
||||
|
@ -6582,6 +6663,7 @@ START_TEST(listview)
|
|||
test_LVSCW_AUTOSIZE();
|
||||
test_LVN_ENDLABELEDIT();
|
||||
test_LVM_GETCOUNTPERPAGE();
|
||||
test_item_state_change();
|
||||
|
||||
unload_v6_module(ctx_cookie, hCtx);
|
||||
|
||||
|
|
|
@ -564,9 +564,11 @@ static void test_wm_notifyformat(void)
|
|||
static const INT formats[] = {NFR_UNICODE, NFR_ANSI};
|
||||
HWND parent, pager, child;
|
||||
LRESULT ret;
|
||||
BOOL bret;
|
||||
INT i;
|
||||
|
||||
ok(register_notifyformat_class(), "Register test class failed, error 0x%08x\n", GetLastError());
|
||||
bret = register_notifyformat_class();
|
||||
ok(bret, "Register test class failed, error 0x%08x\n", GetLastError());
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(formats); i++)
|
||||
{
|
||||
|
@ -1280,9 +1282,11 @@ static void test_wm_notify(void)
|
|||
{&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT, &nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
|
||||
TVN_SELCHANGEDW, TVN_SELCHANGEDA, CONVERT_SEND, TVITEM_OLD_HANDLER}
|
||||
};
|
||||
BOOL bret;
|
||||
INT i;
|
||||
|
||||
ok(register_test_notify_class(), "Register test class failed, error 0x%08x\n", GetLastError());
|
||||
bret = register_test_notify_class();
|
||||
ok(bret, "Register test class failed, error 0x%08x\n", GetLastError());
|
||||
|
||||
parent = CreateWindowA(class, "parent", WS_OVERLAPPED, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), 0);
|
||||
ok(parent != NULL, "CreateWindow failed\n");
|
||||
|
|
|
@ -254,6 +254,13 @@ static void test_PBM_STEPIT(void)
|
|||
{ 3, 15, 5 },
|
||||
{ 3, 15, -5 },
|
||||
{ 3, 15, 50 },
|
||||
{ -15, 15, 5 },
|
||||
{ -3, -2, -5 },
|
||||
{ 0, 0, 1 },
|
||||
{ 5, 5, 1 },
|
||||
{ 0, 0, -1 },
|
||||
{ 5, 5, -1 },
|
||||
{ 10, 5, 2 },
|
||||
};
|
||||
HWND progress;
|
||||
int i, j;
|
||||
|
@ -261,6 +268,7 @@ static void test_PBM_STEPIT(void)
|
|||
for (i = 0; i < ARRAY_SIZE(stepit_tests); i++)
|
||||
{
|
||||
struct stepit_test *test = &stepit_tests[i];
|
||||
PBRANGE range;
|
||||
LRESULT ret;
|
||||
|
||||
progress = create_progress(0);
|
||||
|
@ -268,6 +276,9 @@ static void test_PBM_STEPIT(void)
|
|||
ret = SendMessageA(progress, PBM_SETRANGE32, test->min, test->max);
|
||||
ok(ret != 0, "Unexpected return value.\n");
|
||||
|
||||
SendMessageA(progress, PBM_GETRANGE, 0, (LPARAM)&range);
|
||||
ok(range.iLow == test->min && range.iHigh == test->max, "Unexpected range.\n");
|
||||
|
||||
SendMessageA(progress, PBM_SETPOS, test->min, 0);
|
||||
SendMessageA(progress, PBM_SETSTEP, test->step, 0);
|
||||
|
||||
|
@ -277,15 +288,20 @@ static void test_PBM_STEPIT(void)
|
|||
int current;
|
||||
|
||||
pos += test->step;
|
||||
if (test->min != test->max)
|
||||
{
|
||||
if (pos > test->max)
|
||||
pos = (pos - test->min) % (test->max - test->min) + test->min;
|
||||
if (pos < test->min)
|
||||
pos = (pos - test->min) % (test->max - test->min) + test->max;
|
||||
}
|
||||
else
|
||||
pos = test->min;
|
||||
|
||||
SendMessageA(progress, PBM_STEPIT, 0, 0);
|
||||
|
||||
current = SendMessageA(progress, PBM_GETPOS, 0, 0);
|
||||
ok(current == pos, "Unexpected position %d, expected %d.\n", current, pos);
|
||||
ok(current == pos, "%u: unexpected position %d, expected %d.\n", i, current, pos);
|
||||
}
|
||||
|
||||
DestroyWindow(progress);
|
||||
|
|
|
@ -273,6 +273,9 @@ static void test_subclass(void)
|
|||
ret = pSetWindowSubclass(hwnd, NULL, 1, 0);
|
||||
ok(ret == FALSE, "Expected FALSE\n");
|
||||
|
||||
pRemoveWindowSubclass(hwnd, wnd_proc_sub, 2);
|
||||
pRemoveWindowSubclass(hwnd, wnd_proc_sub, 5);
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
|
|
|
@ -931,7 +931,7 @@ static void test_selection(void)
|
|||
static void test_thumb_length(void)
|
||||
{
|
||||
HWND hWndTrackbar;
|
||||
int r;
|
||||
int r, r2;
|
||||
|
||||
hWndTrackbar = create_trackbar(defaultstyle, hWndParent);
|
||||
ok(hWndTrackbar != NULL, "Expected non NULL value\n");
|
||||
|
@ -963,6 +963,22 @@ static void test_thumb_length(void)
|
|||
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_thumb_length_test_seq, "parent thumb length test sequence", TRUE);
|
||||
|
||||
DestroyWindow(hWndTrackbar);
|
||||
|
||||
/* Fixed thumb length does not depend on window size. */
|
||||
hWndTrackbar = CreateWindowA(TRACKBAR_CLASSA, "Trackbar Control", WS_VISIBLE | TBS_ENABLESELRANGE
|
||||
| TBS_FIXEDLENGTH, 0, 0, 0, 0, hWndParent, NULL, GetModuleHandleA(NULL), NULL);
|
||||
|
||||
r = SendMessageA(hWndTrackbar, TBM_GETTHUMBLENGTH, 0, 0);
|
||||
|
||||
DestroyWindow(hWndTrackbar);
|
||||
|
||||
hWndTrackbar = CreateWindowA(TRACKBAR_CLASSA, "Trackbar Control", WS_VISIBLE | TBS_ENABLESELRANGE
|
||||
| TBS_FIXEDLENGTH, 0, 0, 200, 200, hWndParent, NULL, GetModuleHandleA(NULL), NULL);
|
||||
|
||||
r2 = SendMessageA(hWndTrackbar, TBM_GETTHUMBLENGTH, 0, 0);
|
||||
ok(r2 == r, "Unexpected thumb length %d.\n", r);
|
||||
|
||||
DestroyWindow(hWndTrackbar);
|
||||
}
|
||||
|
||||
static void test_tic_settings(void)
|
||||
|
|
|
@ -1364,7 +1364,7 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam,
|
|||
visibleItem = (HTREEITEM)SendMessageA(pHdr->hwndFrom, TVM_GETNEXTITEM,
|
||||
TVGN_NEXTVISIBLE, (LPARAM)visibleItem);
|
||||
*(HTREEITEM*)&rect = visibleItem;
|
||||
ok(visibleItem != NULL, "There must be a visible item after the first visisble item.\n");
|
||||
ok(visibleItem != NULL, "There must be a visible item after the first one.\n");
|
||||
ok(SendMessageA(pHdr->hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rect),
|
||||
"Failed to get rect for second visible item.\n");
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
* - check UDM_SETBUDDY message
|
||||
* - check UDM_GETBUDDY message
|
||||
* - up-down control and buddy control must have the same parent
|
||||
* - up-down control notifies its parent window when its position changes with UDN_DELTAPOS + WM_VSCROLL or WM_HSCROLL
|
||||
* - check UDS_ALIGN[LEFT,RIGHT]...check that width of buddy window is decreased
|
||||
* - check that UDS_SETBUDDYINT sets the caption of the buddy window when it is changed
|
||||
* - check that the thousands operator is set for large numbers
|
||||
|
@ -165,6 +164,32 @@ static const struct message test_updown_pos_nochange_seq[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message test_updown_pos_notifications_seq[] = {
|
||||
{ WM_CTLCOLOREDIT, sent|optional },
|
||||
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_SETFOCUS) },
|
||||
{ WM_NOTIFY, sent|id, 0, 0, UDN_DELTAPOS },
|
||||
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_UPDATE) },
|
||||
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_CHANGE) },
|
||||
{ WM_VSCROLL, sent|wparam, MAKELONG(SB_THUMBPOSITION, 51) },
|
||||
{ WM_CTLCOLOREDIT, sent|optional },
|
||||
{ WM_VSCROLL, sent|wparam, MAKELONG(SB_ENDSCROLL, 51) },
|
||||
/* no WM_NOTIFY(NM_RELEASEDCAPTURE) message */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct message test_updown_pos_notifications_horz_seq[] = {
|
||||
{ WM_CTLCOLOREDIT, sent|optional },
|
||||
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_SETFOCUS) },
|
||||
{ WM_NOTIFY, sent|id, 0, 0, UDN_DELTAPOS },
|
||||
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_UPDATE) },
|
||||
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_CHANGE) },
|
||||
{ WM_HSCROLL, sent|wparam, MAKELONG(SB_THUMBPOSITION, 51) },
|
||||
{ WM_CTLCOLOREDIT, sent|optional },
|
||||
{ WM_HSCROLL, sent|wparam, MAKELONG(SB_ENDSCROLL, 51) },
|
||||
/* no WM_NOTIFY(NM_RELEASEDCAPTURE) message */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
static LONG defwndproc_counter = 0;
|
||||
|
@ -186,6 +211,8 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
|
|||
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||
msg.wParam = wParam;
|
||||
msg.lParam = lParam;
|
||||
if (message == WM_NOTIFY && lParam)
|
||||
msg.id = ((NMHDR*)lParam)->code;
|
||||
add_message(sequences, PARENT_SEQ_INDEX, &msg);
|
||||
}
|
||||
|
||||
|
@ -900,6 +927,52 @@ static void test_CreateUpDownControl(void)
|
|||
DestroyWindow(updown);
|
||||
}
|
||||
|
||||
static void test_updown_pos_notifications(void)
|
||||
{
|
||||
HWND updown;
|
||||
RECT rect;
|
||||
UINT x, y;
|
||||
int result;
|
||||
|
||||
/* test updown control notifications without UDS_HORZ style */
|
||||
updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT, g_edit);
|
||||
SetFocus(updown);
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
|
||||
/* click on the up-arrow button */
|
||||
GetClientRect(updown, &rect);
|
||||
x = rect.left + (rect.right - rect.left) / 2;
|
||||
y = rect.top + (rect.bottom - rect.top) / 4;
|
||||
result = SendMessageA(updown, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));
|
||||
expect(result, 0);
|
||||
result = SendMessageA(updown, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
|
||||
expect(result, 0);
|
||||
|
||||
ok_sequence(sequences, PARENT_SEQ_INDEX, test_updown_pos_notifications_seq,
|
||||
"test updown to parent notify (vertical)", FALSE);
|
||||
|
||||
DestroyWindow(updown);
|
||||
|
||||
/* test updown control notifications with UDS_HORZ style */
|
||||
updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT | UDS_HORZ, g_edit);
|
||||
SetFocus(updown);
|
||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||
|
||||
/* click on the right-arrow button */
|
||||
GetClientRect(updown, &rect);
|
||||
x = rect.left + (rect.right - rect.left) * 3 / 4;
|
||||
y = rect.top + (rect.bottom - rect.top) / 2;
|
||||
result = SendMessageA(updown, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));
|
||||
expect(result, 0);
|
||||
result = SendMessageA(updown, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
|
||||
expect(result, 0);
|
||||
|
||||
ok_sequence(sequences, PARENT_SEQ_INDEX, test_updown_pos_notifications_horz_seq,
|
||||
"test updown to parent notify (horizontal)", FALSE);
|
||||
|
||||
DestroyWindow(updown);
|
||||
}
|
||||
|
||||
static void init_functions(void)
|
||||
{
|
||||
HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
|
||||
|
@ -931,6 +1004,7 @@ START_TEST(updown)
|
|||
test_updown_unicode();
|
||||
test_UDS_SETBUDDYINT();
|
||||
test_CreateUpDownControl();
|
||||
test_updown_pos_notifications();
|
||||
|
||||
DestroyWindow(g_edit);
|
||||
DestroyWindow(parent_wnd);
|
||||
|
|
Loading…
Reference in a new issue