mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:23:05 +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 ID_BUTTON 0x000e
|
||||||
|
|
||||||
#define COMBINED_SEQ_INDEX 0
|
#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];
|
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;
|
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 LRESULT WINAPI test_parent_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
static LONG defwndproc_counter = 0;
|
static LONG defwndproc_counter = 0;
|
||||||
static LONG beginpaint_counter = 0;
|
static LONG beginpaint_counter = 0;
|
||||||
|
static HDC cd_first_hdc;
|
||||||
struct message msg = { 0 };
|
struct message msg = { 0 };
|
||||||
|
NMCUSTOMDRAW *cd = (NMCUSTOMDRAW*)lParam;
|
||||||
|
NMBCDROPDOWN *bcd = (NMBCDROPDOWN*)lParam;
|
||||||
LRESULT ret;
|
LRESULT ret;
|
||||||
|
|
||||||
if (ignore_message( message )) return 0;
|
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);
|
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)
|
if (message == WM_PAINT)
|
||||||
{
|
{
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
|
@ -461,6 +561,60 @@ static const struct message setcheck_radio_redraw_seq[] =
|
||||||
{ 0 }
|
{ 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)
|
static HWND create_button(DWORD style, HWND parent)
|
||||||
{
|
{
|
||||||
HMENU menuid = 0;
|
HMENU menuid = 0;
|
||||||
|
@ -479,6 +633,13 @@ static HWND create_button(DWORD style, HWND parent)
|
||||||
|
|
||||||
static void test_button_messages(void)
|
static void test_button_messages(void)
|
||||||
{
|
{
|
||||||
|
enum cd_seq_type
|
||||||
|
{
|
||||||
|
cd_seq_empty,
|
||||||
|
cd_seq_normal,
|
||||||
|
cd_seq_optional
|
||||||
|
};
|
||||||
|
|
||||||
static const struct
|
static const struct
|
||||||
{
|
{
|
||||||
DWORD style;
|
DWORD style;
|
||||||
|
@ -489,55 +650,74 @@ static void test_button_messages(void)
|
||||||
const struct message *setstate;
|
const struct message *setstate;
|
||||||
const struct message *clearstate;
|
const struct message *clearstate;
|
||||||
const struct message *setcheck;
|
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[] = {
|
} button[] = {
|
||||||
{ BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
|
{ BS_PUSHBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
|
||||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
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,
|
{ BS_DEFPUSHBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
|
||||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
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,
|
{ BS_CHECKBOX, DLGC_BUTTON,
|
||||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
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,
|
{ BS_AUTOCHECKBOX, DLGC_BUTTON,
|
||||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
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,
|
{ BS_RADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
|
||||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
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,
|
{ BS_3STATE, DLGC_BUTTON,
|
||||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
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,
|
{ BS_AUTO3STATE, DLGC_BUTTON,
|
||||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
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,
|
{ BS_GROUPBOX, DLGC_STATIC,
|
||||||
setfocus_groupbox_seq, killfocus_static_seq, setstyle_static_seq,
|
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,
|
{ BS_USERBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
|
||||||
setfocus_seq, killfocus_seq, setstyle_user_seq,
|
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,
|
{ BS_AUTORADIOBUTTON, DLGC_BUTTON | DLGC_RADIOBUTTON,
|
||||||
setfocus_static_seq, killfocus_static_seq, setstyle_static_seq,
|
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,
|
{ BS_OWNERDRAW, DLGC_BUTTON,
|
||||||
setfocus_ownerdraw_seq, killfocus_ownerdraw_seq, setstyle_ownerdraw_seq,
|
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,
|
{ BS_SPLITBUTTON, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON | DLGC_WANTARROWS,
|
||||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
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,
|
{ BS_DEFSPLITBUTTON, DLGC_BUTTON | DLGC_DEFPUSHBUTTON | DLGC_WANTARROWS,
|
||||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
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,
|
{ BS_COMMANDLINK, DLGC_BUTTON | DLGC_UNDEFPUSHBUTTON,
|
||||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
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,
|
{ BS_DEFCOMMANDLINK, DLGC_BUTTON | DLGC_DEFPUSHBUTTON,
|
||||||
setfocus_seq, killfocus_seq, setstyle_seq,
|
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 };
|
LOGFONTA logfont = { 0 };
|
||||||
const struct message *seq;
|
const struct message *seq, *cd_seq;
|
||||||
HFONT zfont, hfont2;
|
HFONT zfont, hfont2;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
HWND hwnd, parent;
|
HWND hwnd, parent;
|
||||||
|
@ -565,6 +745,11 @@ static void test_button_messages(void)
|
||||||
hfont2 = CreateFontIndirectA(&logfont);
|
hfont2 = CreateFontIndirectA(&logfont);
|
||||||
ok(hfont2 != NULL, "Failed to create Tahoma font\n");
|
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++)
|
for (i = 0; i < ARRAY_SIZE(button); i++)
|
||||||
{
|
{
|
||||||
HFONT prevfont, hfont;
|
HFONT prevfont, hfont;
|
||||||
|
@ -572,6 +757,7 @@ static void test_button_messages(void)
|
||||||
DWORD style, state;
|
DWORD style, state;
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
|
|
||||||
|
test_cd.button = button[i].style;
|
||||||
hwnd = create_button(button[i].style, parent);
|
hwnd = create_button(button[i].style, parent);
|
||||||
ok(hwnd != NULL, "Failed to create a button.\n");
|
ok(hwnd != NULL, "Failed to create a button.\n");
|
||||||
|
|
||||||
|
@ -599,27 +785,35 @@ static void test_button_messages(void)
|
||||||
SetFocus(0);
|
SetFocus(0);
|
||||||
flush_events();
|
flush_events();
|
||||||
SetFocus(0);
|
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);
|
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());
|
ok(GetFocus() == 0, "expected focus 0, got %p\n", GetFocus());
|
||||||
SetFocus(hwnd);
|
SetFocus(hwnd);
|
||||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
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);
|
SetFocus(0);
|
||||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
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());
|
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, BM_SETSTYLE, button[i].style | BS_BOTTOM, TRUE);
|
||||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||||
todo = button[i].style == BS_OWNERDRAW;
|
todo = button[i].style == BS_OWNERDRAW;
|
||||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, button[i].setstyle, "BM_SETSTYLE on a button", todo);
|
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 = GetWindowLongA(hwnd, GWL_STYLE);
|
||||||
style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY);
|
style &= ~(WS_VISIBLE | WS_CHILD | BS_NOTIFY);
|
||||||
|
@ -629,12 +823,15 @@ static void test_button_messages(void)
|
||||||
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0);
|
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0);
|
||||||
ok(state == 0, "expected state 0, got %04x\n", state);
|
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);
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
set_test_cd_state(CDIS_SELECTED);
|
||||||
|
|
||||||
SendMessageA(hwnd, BM_SETSTATE, TRUE, 0);
|
SendMessageA(hwnd, BM_SETSTATE, TRUE, 0);
|
||||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
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);
|
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);
|
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0);
|
||||||
ok(state == BST_PUSHED, "expected state 0x0004, got %04x\n", state);
|
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);
|
ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
|
||||||
|
|
||||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
set_test_cd_state(0);
|
||||||
|
|
||||||
SendMessageA(hwnd, BM_SETSTATE, FALSE, 0);
|
SendMessageA(hwnd, BM_SETSTATE, FALSE, 0);
|
||||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
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);
|
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);
|
state = SendMessageA(hwnd, BM_GETSTATE, 0, 0);
|
||||||
ok(state == 0, "expected state 0, got %04x\n", state);
|
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);
|
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0);
|
||||||
ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state);
|
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);
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
set_test_cd_state(0);
|
||||||
|
|
||||||
if (button[i].style == BS_RADIOBUTTON ||
|
if (button[i].style == BS_RADIOBUTTON ||
|
||||||
button[i].style == BS_AUTORADIOBUTTON)
|
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 */
|
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, seq, "BM_SETCHECK on a button", FALSE);
|
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);
|
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0);
|
||||||
ok(state == BST_UNCHECKED, "expected BST_UNCHECKED, got %04x\n", state);
|
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);
|
ok(style == button[i].style, "expected style %04x got %04x\n", button[i].style, style);
|
||||||
|
|
||||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
|
set_test_cd_state(0);
|
||||||
|
|
||||||
SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0);
|
SendMessageA(hwnd, BM_SETCHECK, BST_CHECKED, 0);
|
||||||
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
SendMessageA(hwnd, WM_APP, 0, 0); /* place a separator mark here */
|
||||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
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);
|
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);
|
state = SendMessageA(hwnd, BM_GETCHECK, 0, 0);
|
||||||
if (button[i].style == BS_PUSHBUTTON ||
|
if (button[i].style == BS_PUSHBUTTON ||
|
||||||
|
@ -735,9 +939,60 @@ static void test_button_messages(void)
|
||||||
|
|
||||||
DeleteDC(hdc);
|
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);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef check_cd_seq
|
||||||
|
|
||||||
DeleteObject(hfont2);
|
DeleteObject(hfont2);
|
||||||
DestroyWindow(parent);
|
DestroyWindow(parent);
|
||||||
|
|
||||||
|
@ -1228,6 +1483,214 @@ static void register_parent_class(void)
|
||||||
RegisterClassA(&cls);
|
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 void test_button_data(void)
|
||||||
{
|
{
|
||||||
static const DWORD styles[] =
|
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");
|
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);
|
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_text2 = "WWWW\nWWWW";
|
||||||
static const char *button_text = "WWWW";
|
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,
|
static const DWORD imagelist_aligns[] = {BUTTON_IMAGELIST_ALIGN_LEFT, BUTTON_IMAGELIST_ALIGN_RIGHT,
|
||||||
BUTTON_IMAGELIST_ALIGN_TOP, BUTTON_IMAGELIST_ALIGN_BOTTOM,
|
BUTTON_IMAGELIST_ALIGN_TOP, BUTTON_IMAGELIST_ALIGN_BOTTOM,
|
||||||
BUTTON_IMAGELIST_ALIGN_CENTER};
|
BUTTON_IMAGELIST_ALIGN_CENTER};
|
||||||
static const DWORD aligns[] = {0, BS_TOP, BS_LEFT, BS_RIGHT, BS_BOTTOM,
|
static const DWORD aligns[] = {0, BS_TOP, BS_LEFT, BS_RIGHT, BS_BOTTOM,
|
||||||
BS_CENTER, BS_VCENTER, BS_RIGHTBUTTON, WS_EX_RIGHT};
|
BS_CENTER, BS_VCENTER, BS_RIGHTBUTTON, WS_EX_RIGHT};
|
||||||
DWORD default_style = WS_TABSTOP | WS_POPUP | WS_VISIBLE;
|
DWORD default_style = WS_TABSTOP | WS_POPUP | WS_VISIBLE;
|
||||||
const LONG client_width = 400, client_height = 200;
|
const LONG client_width = 400, client_height = 200, extra_width = 123, large_height = 500;
|
||||||
LONG image_width, height, line_count, text_width;
|
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;
|
HFONT hfont, prev_font;
|
||||||
DWORD style, type;
|
DWORD style, type;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
@ -1453,7 +1936,7 @@ static void test_bcm_get_ideal_size(void)
|
||||||
HIMAGELIST himl;
|
HIMAGELIST himl;
|
||||||
BUTTON_IMAGELIST biml = {0};
|
BUTTON_IMAGELIST biml = {0};
|
||||||
RECT rect;
|
RECT rect;
|
||||||
INT i, j;
|
INT i, j, k;
|
||||||
|
|
||||||
/* Check for NULL pointer handling */
|
/* Check for NULL pointer handling */
|
||||||
hwnd = CreateWindowA(WC_BUTTONA, button_text, BS_PUSHBUTTON | default_style, 0, 0, client_width, client_height,
|
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 */
|
/* Tests for image placements */
|
||||||
/* Prepare bitmap */
|
/* Prepare bitmap */
|
||||||
image_width = 48;
|
|
||||||
height = 48;
|
|
||||||
hdc = GetDC(0);
|
hdc = GetDC(0);
|
||||||
hmask = CreateCompatibleBitmap(hdc, image_width, height);
|
hmask = CreateCompatibleBitmap(hdc, image_width, height);
|
||||||
hbmp = 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 */
|
/* 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);
|
client_height, NULL, NULL, 0, NULL);
|
||||||
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||||
|
set_split_info(hwnd);
|
||||||
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
|
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
|
||||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||||
ZeroMemory(&size, sizeof(size));
|
ZeroMemory(&size, sizeof(size));
|
||||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||||
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||||
/* Ideal size contains text rect even show bitmap only */
|
/* Ideal size contains text rect even show bitmap only */
|
||||||
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),
|
||||||
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, image_width + text_width,
|
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
|
||||||
size.cy, max(height, tm.tmHeight));
|
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);
|
DestroyWindow(hwnd);
|
||||||
|
|
||||||
/* Image alignments when button has bitmap and text*/
|
/* Image alignments when button has bitmap and text*/
|
||||||
for (i = 0; i < ARRAY_SIZE(aligns); i++)
|
for (i = 0; i < ARRAY_SIZE(aligns); i++)
|
||||||
for (j = 0; j < ARRAY_SIZE(aligns); j++)
|
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);
|
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");
|
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||||
|
set_split_info(hwnd);
|
||||||
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
|
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hbmp);
|
||||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||||
ZeroMemory(&size, sizeof(size));
|
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");
|
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||||
if (!(style & (BS_CENTER | BS_VCENTER)) || ((style & BS_CENTER) && (style & BS_CENTER) != BS_CENTER)
|
if (!(style & (BS_CENTER | BS_VCENTER)) || ((style & BS_CENTER) && (style & BS_CENTER) != BS_CENTER)
|
||||||
|| !(style & BS_VCENTER) || (style & BS_VCENTER) == BS_VCENTER)
|
|| !(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,
|
"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
|
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,
|
"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);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Image list alignments */
|
/* Image list alignments */
|
||||||
himl = pImageList_Create(image_width, height, ILC_COLOR, 1, 1);
|
|
||||||
pImageList_Add(himl, hbmp, 0);
|
|
||||||
biml.himl = himl;
|
biml.himl = himl;
|
||||||
for (i = 0; i < ARRAY_SIZE(imagelist_aligns); i++)
|
for (i = 0; i < ARRAY_SIZE(imagelist_aligns); i++)
|
||||||
{
|
{
|
||||||
biml.uAlign = 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);
|
client_height, NULL, NULL, 0, NULL);
|
||||||
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||||
|
set_split_info(hwnd);
|
||||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||||
SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml);
|
SendMessageA(hwnd, BCM_SETIMAGELIST, 0, (LPARAM)&biml);
|
||||||
ZeroMemory(&size, sizeof(size));
|
ZeroMemory(&size, sizeof(size));
|
||||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||||
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||||
if (biml.uAlign == BUTTON_IMAGELIST_ALIGN_TOP || biml.uAlign == BUTTON_IMAGELIST_ALIGN_BOTTOM)
|
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,
|
"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)
|
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,
|
"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
|
else
|
||||||
ok(size.cx >= image_width && size.cy >= height, "Align:%d expect ideal cx %d >= %d and ideal cy %d >= %d\n",
|
ok(size.cx >= image_width + pushtype[k].extra_width && size.cy >= height,
|
||||||
biml.uAlign, 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 + pushtype[k].extra_width, size.cy, height);
|
||||||
|
ok(size.cy < large_height, "Expect ideal cy %d < %d\n", size.cy, large_height);
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1579,33 +2079,41 @@ static void test_bcm_get_ideal_size(void)
|
||||||
hicon = CreateIconIndirect(&icon_info);
|
hicon = CreateIconIndirect(&icon_info);
|
||||||
|
|
||||||
/* Only icon, ideal size should be enough for image and text */
|
/* 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);
|
client_height, NULL, NULL, 0, NULL);
|
||||||
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||||
|
set_split_info(hwnd);
|
||||||
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon);
|
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon);
|
||||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||||
ZeroMemory(&size, sizeof(size));
|
ZeroMemory(&size, sizeof(size));
|
||||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||||
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||||
/* Ideal size contains text rect even show icons only */
|
/* Ideal size contains text rect even show icons only */
|
||||||
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),
|
||||||
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, image_width + text_width, size.cy,
|
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
|
||||||
max(height, tm.tmHeight));
|
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);
|
DestroyWindow(hwnd);
|
||||||
|
|
||||||
/* Show icon and text */
|
/* 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);
|
client_height, NULL, NULL, 0, NULL);
|
||||||
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
ok(hwnd != NULL, "Expect hwnd not NULL\n");
|
||||||
|
set_split_info(hwnd);
|
||||||
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon);
|
SendMessageA(hwnd, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)hicon);
|
||||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, (LPARAM)TRUE);
|
||||||
ZeroMemory(&size, sizeof(size));
|
ZeroMemory(&size, sizeof(size));
|
||||||
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
ret = SendMessageA(hwnd, BCM_GETIDEALSIZE, 0, (LPARAM)&size);
|
||||||
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
ok(ret, "Expect BCM_GETIDEALSIZE message to return true\n");
|
||||||
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),
|
||||||
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx, image_width + text_width, size.cy,
|
"Expect ideal cx %d >= %d and ideal cy %d >= %d\n", size.cx,
|
||||||
max(height, tm.tmHeight));
|
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);
|
DestroyWindow(hwnd);
|
||||||
|
DestroyIcon(hicon);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef set_split_info
|
||||||
|
|
||||||
/* Checkbox */
|
/* Checkbox */
|
||||||
/* Both bitmap and text for checkbox, ideal size is only enough for text because it doesn't support image(but not image list)*/
|
/* 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)
|
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);
|
style, size.cx, 0, size.cy, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1704,8 +2212,8 @@ static void test_bcm_get_ideal_size(void)
|
||||||
}
|
}
|
||||||
else if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK)
|
else if (type == BS_COMMANDLINK || type == BS_DEFCOMMANDLINK)
|
||||||
{
|
{
|
||||||
todo_wine ok((size.cx == 0 && size.cy > 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,
|
"Style 0x%08x expect ideal cx %d == %d and ideal cy %d > %d\n", style, size.cx, 0,
|
||||||
size.cy, 0);
|
size.cy, 0);
|
||||||
}
|
}
|
||||||
else
|
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);
|
pImageList_Destroy(himl);
|
||||||
DestroyIcon(hicon);
|
|
||||||
DeleteObject(hbmp);
|
DeleteObject(hbmp);
|
||||||
DeleteObject(hmask);
|
DeleteObject(hmask);
|
||||||
ReleaseDC(0, hdc);
|
ReleaseDC(0, hdc);
|
||||||
|
|
|
@ -1485,16 +1485,31 @@ static void test_edit_control_scroll(void)
|
||||||
DestroyWindow (hwEdit);
|
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)
|
static void test_margins_usefontinfo(UINT charset)
|
||||||
{
|
{
|
||||||
INT margins, threshold, expect, empty_expect, small_expect;
|
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
|
TEXTMETRICW tm;
|
||||||
SIZE size;
|
SIZE size;
|
||||||
BOOL cjk;
|
|
||||||
LOGFONTA lf;
|
LOGFONTA lf;
|
||||||
HFONT hfont;
|
HFONT hfont;
|
||||||
RECT rect;
|
RECT rect;
|
||||||
|
INT margins, threshold, expect, empty_expect;
|
||||||
|
const UINT small_margins = MAKELONG(1, 5);
|
||||||
|
|
||||||
memset(&lf, 0, sizeof(lf));
|
memset(&lf, 0, sizeof(lf));
|
||||||
lf.lfHeight = -11;
|
lf.lfHeight = -11;
|
||||||
|
@ -1513,43 +1528,31 @@ static void test_margins_usefontinfo(UINT charset)
|
||||||
|
|
||||||
hdc = GetDC(hwnd);
|
hdc = GetDC(hwnd);
|
||||||
hfont = SelectObject(hdc, hfont);
|
hfont = SelectObject(hdc, hfont);
|
||||||
size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy );
|
size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
|
||||||
expect = MAKELONG(size.cx / 2, size.cx / 2);
|
if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
|
||||||
small_expect = 0;
|
!(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
|
||||||
empty_expect = size.cx >= 28 ? small_expect : expect;
|
skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
|
||||||
|
hfont = SelectObject(hdc, hfont);
|
||||||
charset = GetTextCharset(hdc);
|
ReleaseDC(hwnd, hdc);
|
||||||
switch (charset)
|
DestroyWindow(hwnd);
|
||||||
{
|
DeleteObject(hfont);
|
||||||
case SHIFTJIS_CHARSET:
|
return;
|
||||||
case HANGUL_CHARSET:
|
|
||||||
case GB2312_CHARSET:
|
|
||||||
case CHINESEBIG5_CHARSET:
|
|
||||||
cjk = TRUE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cjk = FALSE;
|
|
||||||
}
|
}
|
||||||
|
expect = MAKELONG(size.cx / 2, size.cx / 2);
|
||||||
hfont = SelectObject(hdc, hfont);
|
hfont = SelectObject(hdc, hfont);
|
||||||
ReleaseDC(hwnd, hdc);
|
ReleaseDC(hwnd, hdc);
|
||||||
|
|
||||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||||
ok(margins == 0, "got %x\n", margins);
|
ok(margins == 0, "got %x\n", margins);
|
||||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
||||||
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
|
||||||
if (!cjk)
|
expect = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||||
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;
|
|
||||||
}
|
|
||||||
DestroyWindow(hwnd);
|
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);
|
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold - 1, 100, NULL, NULL, NULL, NULL);
|
||||||
ok(hwnd != NULL, "got %p\n", hwnd);
|
ok(hwnd != NULL, "got %p\n", hwnd);
|
||||||
GetClientRect(hwnd, &rect);
|
GetClientRect(hwnd, &rect);
|
||||||
|
@ -1559,11 +1562,13 @@ static void test_margins_usefontinfo(UINT charset)
|
||||||
ok(margins == 0, "got %x\n", margins);
|
ok(margins == 0, "got %x\n", margins);
|
||||||
|
|
||||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
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);
|
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);
|
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);
|
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold, 100, NULL, NULL, NULL, NULL);
|
||||||
ok(hwnd != NULL, "got %p\n", hwnd);
|
ok(hwnd != NULL, "got %p\n", hwnd);
|
||||||
GetClientRect(hwnd, &rect);
|
GetClientRect(hwnd, &rect);
|
||||||
|
@ -1573,6 +1578,8 @@ static void test_margins_usefontinfo(UINT charset)
|
||||||
ok(margins == 0, "got %x\n", margins);
|
ok(margins == 0, "got %x\n", margins);
|
||||||
|
|
||||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
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);
|
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||||
ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
|
@ -1587,6 +1594,8 @@ static void test_margins_usefontinfo(UINT charset)
|
||||||
ok(margins == 0, "got %x\n", margins);
|
ok(margins == 0, "got %x\n", margins);
|
||||||
|
|
||||||
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
|
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);
|
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
|
||||||
ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
|
@ -1594,6 +1603,151 @@ static void test_margins_usefontinfo(UINT charset)
|
||||||
DeleteObject(hfont);
|
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)
|
static void test_margins(void)
|
||||||
{
|
{
|
||||||
DWORD old_margins, new_margins;
|
DWORD old_margins, new_margins;
|
||||||
|
@ -1668,27 +1822,45 @@ static void test_margins(void)
|
||||||
but not by < Win 8 and Win 10. */
|
but not by < Win 8 and Win 10. */
|
||||||
|
|
||||||
test_margins_usefontinfo(DEFAULT_CHARSET);
|
test_margins_usefontinfo(DEFAULT_CHARSET);
|
||||||
}
|
|
||||||
|
|
||||||
static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
|
test_margins_default("Tahoma", ANSI_CHARSET);
|
||||||
{
|
test_margins_default("Tahoma", EASTEUROPE_CHARSET);
|
||||||
return 0;
|
|
||||||
|
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)
|
static void test_margins_font_change(void)
|
||||||
{
|
{
|
||||||
DWORD margins, font_margins, ret;
|
DWORD margins, font_margins;
|
||||||
HFONT hfont, hfont2;
|
HFONT hfont, hfont2;
|
||||||
HWND hwEdit;
|
HWND hwEdit;
|
||||||
LOGFONTA lf;
|
LOGFONTA lf;
|
||||||
HDC hdc;
|
|
||||||
|
|
||||||
hdc = GetDC(0);
|
if (!is_font_installed("Arial"))
|
||||||
ret = EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0);
|
|
||||||
ReleaseDC(0, hdc);
|
|
||||||
if (ret)
|
|
||||||
{
|
{
|
||||||
trace("Arial not found - skipping font change margin tests\n");
|
skip("Arial not found - skipping font change margin tests\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1699,7 +1871,7 @@ static void test_margins_font_change(void)
|
||||||
memset(&lf, 0, sizeof(lf));
|
memset(&lf, 0, sizeof(lf));
|
||||||
strcpy(lf.lfFaceName, "Arial");
|
strcpy(lf.lfFaceName, "Arial");
|
||||||
lf.lfHeight = 16;
|
lf.lfHeight = 16;
|
||||||
lf.lfCharSet = DEFAULT_CHARSET;
|
lf.lfCharSet = GREEK_CHARSET; /* to avoid associated charset feature */
|
||||||
hfont = CreateFontIndirectA(&lf);
|
hfont = CreateFontIndirectA(&lf);
|
||||||
lf.lfHeight = 30;
|
lf.lfHeight = 30;
|
||||||
hfont2 = CreateFontIndirectA(&lf);
|
hfont2 = CreateFontIndirectA(&lf);
|
||||||
|
@ -3143,6 +3315,9 @@ static void test_change_focus(void)
|
||||||
HWND hwnd, parent_wnd;
|
HWND hwnd, parent_wnd;
|
||||||
WNDPROC oldproc;
|
WNDPROC oldproc;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
POINT orig_pos;
|
||||||
|
|
||||||
|
GetCursorPos(&orig_pos);
|
||||||
|
|
||||||
parent_wnd = CreateWindowA("ParentWnd", "", WS_OVERLAPPEDWINDOW,
|
parent_wnd = CreateWindowA("ParentWnd", "", WS_OVERLAPPEDWINDOW,
|
||||||
0, 0, 200, 200, NULL, NULL, GetModuleHandleA(NULL), NULL);
|
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);
|
oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)edit_subclass_proc);
|
||||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
|
SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
|
||||||
|
|
||||||
|
SetCursorPos(400, 400);
|
||||||
|
|
||||||
SetFocus(parent_wnd);
|
SetFocus(parent_wnd);
|
||||||
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
||||||
SetFocus(hwnd);
|
SetFocus(hwnd);
|
||||||
|
@ -3168,6 +3345,8 @@ static void test_change_focus(void)
|
||||||
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
|
||||||
ok_sequence(sequences, COMBINED_SEQ_INDEX, killfocus_combined_seq, "Kill focus", TRUE);
|
ok_sequence(sequences, COMBINED_SEQ_INDEX, killfocus_combined_seq, "Kill focus", TRUE);
|
||||||
|
|
||||||
|
SetCursorPos(orig_pos.x, orig_pos.y);
|
||||||
|
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1563,7 +1563,6 @@ cleanup:
|
||||||
if(hbmDst)
|
if(hbmDst)
|
||||||
DeleteObject(hbmDst);
|
DeleteObject(hbmDst);
|
||||||
|
|
||||||
if(hdcDst)
|
|
||||||
DeleteDC(hdcDst);
|
DeleteDC(hdcDst);
|
||||||
|
|
||||||
if(hbmMask)
|
if(hbmMask)
|
||||||
|
@ -2181,7 +2180,7 @@ static void test_color_table(UINT ilc)
|
||||||
rgb[2].rgbBlue = 0xff;
|
rgb[2].rgbBlue = 0xff;
|
||||||
check_color_table("remove all, add 8", hdc, himl, ilc, rgb, default_table);
|
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 */
|
been set by the previous _Add */
|
||||||
ret = pImageList_Remove(himl, -1);
|
ret = pImageList_Remove(himl, -1);
|
||||||
ok(ret, "got %d\n", ret);
|
ok(ret, "got %d\n", ret);
|
||||||
|
|
|
@ -784,6 +784,135 @@ static void test_listbox_height(void)
|
||||||
DestroyWindow( hList );
|
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)
|
static void test_itemfrompoint(void)
|
||||||
{
|
{
|
||||||
/* WS_POPUP is required in order to have a more accurate size calculation (
|
/* 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:\\");
|
strcpy(pathBuffer, "C:\\");
|
||||||
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
|
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
|
||||||
ok(res, "DlgDirList failed to list C:\\ folders\n");
|
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:\\*");
|
strcpy(pathBuffer, "C:\\*");
|
||||||
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
|
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
|
||||||
|
@ -1823,8 +1952,8 @@ static void test_listbox_dlgdir(void)
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
strcpy(pathBuffer, "C:\\INVALID$$DIR");
|
strcpy(pathBuffer, "C:\\INVALID$$DIR");
|
||||||
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
|
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);
|
ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
|
||||||
todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
|
ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
|
||||||
"GetLastError should return 0x589, got 0x%X\n",GetLastError());
|
"GetLastError should return 0x589, got 0x%X\n",GetLastError());
|
||||||
|
|
||||||
DestroyWindow(hWnd);
|
DestroyWindow(hWnd);
|
||||||
|
@ -1867,6 +1996,11 @@ static void test_set_count( void )
|
||||||
GetUpdateRect( listbox, &r, TRUE );
|
GetUpdateRect( listbox, &r, TRUE );
|
||||||
ok( !IsRectEmpty( &r ), "got empty rect\n");
|
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 );
|
DestroyWindow( listbox );
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(styles); ++i)
|
for (i = 0; i < ARRAY_SIZE(styles); ++i)
|
||||||
|
@ -1906,6 +2040,69 @@ static void test_GetListBoxInfo(void)
|
||||||
DestroyWindow(parent);
|
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)
|
static void test_missing_lbuttonup(void)
|
||||||
{
|
{
|
||||||
HWND listbox, parent, capture;
|
HWND listbox, parent, capture;
|
||||||
|
@ -2420,11 +2617,13 @@ START_TEST(listbox)
|
||||||
test_LB_SELITEMRANGE();
|
test_LB_SELITEMRANGE();
|
||||||
test_LB_SETCURSEL();
|
test_LB_SETCURSEL();
|
||||||
test_listbox_height();
|
test_listbox_height();
|
||||||
|
test_changing_selection_styles();
|
||||||
test_itemfrompoint();
|
test_itemfrompoint();
|
||||||
test_listbox_item_data();
|
test_listbox_item_data();
|
||||||
test_listbox_LB_DIR();
|
test_listbox_LB_DIR();
|
||||||
test_listbox_dlgdir();
|
test_listbox_dlgdir();
|
||||||
test_set_count();
|
test_set_count();
|
||||||
|
test_init_storage();
|
||||||
test_GetListBoxInfo();
|
test_GetListBoxInfo();
|
||||||
test_missing_lbuttonup();
|
test_missing_lbuttonup();
|
||||||
test_extents();
|
test_extents();
|
||||||
|
|
|
@ -6475,6 +6475,86 @@ static void test_LVM_GETCOUNTPERPAGE(void)
|
||||||
ok(ret, "Failed to unregister test class.\n");
|
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)
|
START_TEST(listview)
|
||||||
{
|
{
|
||||||
ULONG_PTR ctx_cookie;
|
ULONG_PTR ctx_cookie;
|
||||||
|
@ -6538,6 +6618,7 @@ START_TEST(listview)
|
||||||
test_LVSCW_AUTOSIZE();
|
test_LVSCW_AUTOSIZE();
|
||||||
test_LVN_ENDLABELEDIT();
|
test_LVN_ENDLABELEDIT();
|
||||||
test_LVM_GETCOUNTPERPAGE();
|
test_LVM_GETCOUNTPERPAGE();
|
||||||
|
test_item_state_change();
|
||||||
|
|
||||||
if (!load_v6_module(&ctx_cookie, &hCtx))
|
if (!load_v6_module(&ctx_cookie, &hCtx))
|
||||||
{
|
{
|
||||||
|
@ -6582,6 +6663,7 @@ START_TEST(listview)
|
||||||
test_LVSCW_AUTOSIZE();
|
test_LVSCW_AUTOSIZE();
|
||||||
test_LVN_ENDLABELEDIT();
|
test_LVN_ENDLABELEDIT();
|
||||||
test_LVM_GETCOUNTPERPAGE();
|
test_LVM_GETCOUNTPERPAGE();
|
||||||
|
test_item_state_change();
|
||||||
|
|
||||||
unload_v6_module(ctx_cookie, hCtx);
|
unload_v6_module(ctx_cookie, hCtx);
|
||||||
|
|
||||||
|
|
|
@ -564,9 +564,11 @@ static void test_wm_notifyformat(void)
|
||||||
static const INT formats[] = {NFR_UNICODE, NFR_ANSI};
|
static const INT formats[] = {NFR_UNICODE, NFR_ANSI};
|
||||||
HWND parent, pager, child;
|
HWND parent, pager, child;
|
||||||
LRESULT ret;
|
LRESULT ret;
|
||||||
|
BOOL bret;
|
||||||
INT i;
|
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++)
|
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,
|
{&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT, &nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
|
||||||
TVN_SELCHANGEDW, TVN_SELCHANGEDA, CONVERT_SEND, TVITEM_OLD_HANDLER}
|
TVN_SELCHANGEDW, TVN_SELCHANGEDA, CONVERT_SEND, TVITEM_OLD_HANDLER}
|
||||||
};
|
};
|
||||||
|
BOOL bret;
|
||||||
INT i;
|
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);
|
parent = CreateWindowA(class, "parent", WS_OVERLAPPED, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), 0);
|
||||||
ok(parent != NULL, "CreateWindow failed\n");
|
ok(parent != NULL, "CreateWindow failed\n");
|
||||||
|
|
|
@ -254,6 +254,13 @@ static void test_PBM_STEPIT(void)
|
||||||
{ 3, 15, 5 },
|
{ 3, 15, 5 },
|
||||||
{ 3, 15, -5 },
|
{ 3, 15, -5 },
|
||||||
{ 3, 15, 50 },
|
{ 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;
|
HWND progress;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -261,6 +268,7 @@ static void test_PBM_STEPIT(void)
|
||||||
for (i = 0; i < ARRAY_SIZE(stepit_tests); i++)
|
for (i = 0; i < ARRAY_SIZE(stepit_tests); i++)
|
||||||
{
|
{
|
||||||
struct stepit_test *test = &stepit_tests[i];
|
struct stepit_test *test = &stepit_tests[i];
|
||||||
|
PBRANGE range;
|
||||||
LRESULT ret;
|
LRESULT ret;
|
||||||
|
|
||||||
progress = create_progress(0);
|
progress = create_progress(0);
|
||||||
|
@ -268,6 +276,9 @@ static void test_PBM_STEPIT(void)
|
||||||
ret = SendMessageA(progress, PBM_SETRANGE32, test->min, test->max);
|
ret = SendMessageA(progress, PBM_SETRANGE32, test->min, test->max);
|
||||||
ok(ret != 0, "Unexpected return value.\n");
|
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_SETPOS, test->min, 0);
|
||||||
SendMessageA(progress, PBM_SETSTEP, test->step, 0);
|
SendMessageA(progress, PBM_SETSTEP, test->step, 0);
|
||||||
|
|
||||||
|
@ -277,15 +288,20 @@ static void test_PBM_STEPIT(void)
|
||||||
int current;
|
int current;
|
||||||
|
|
||||||
pos += test->step;
|
pos += test->step;
|
||||||
|
if (test->min != test->max)
|
||||||
|
{
|
||||||
if (pos > test->max)
|
if (pos > test->max)
|
||||||
pos = (pos - test->min) % (test->max - test->min) + test->min;
|
pos = (pos - test->min) % (test->max - test->min) + test->min;
|
||||||
if (pos < test->min)
|
if (pos < test->min)
|
||||||
pos = (pos - test->min) % (test->max - test->min) + test->max;
|
pos = (pos - test->min) % (test->max - test->min) + test->max;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pos = test->min;
|
||||||
|
|
||||||
SendMessageA(progress, PBM_STEPIT, 0, 0);
|
SendMessageA(progress, PBM_STEPIT, 0, 0);
|
||||||
|
|
||||||
current = SendMessageA(progress, PBM_GETPOS, 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);
|
DestroyWindow(progress);
|
||||||
|
|
|
@ -273,6 +273,9 @@ static void test_subclass(void)
|
||||||
ret = pSetWindowSubclass(hwnd, NULL, 1, 0);
|
ret = pSetWindowSubclass(hwnd, NULL, 1, 0);
|
||||||
ok(ret == FALSE, "Expected FALSE\n");
|
ok(ret == FALSE, "Expected FALSE\n");
|
||||||
|
|
||||||
|
pRemoveWindowSubclass(hwnd, wnd_proc_sub, 2);
|
||||||
|
pRemoveWindowSubclass(hwnd, wnd_proc_sub, 5);
|
||||||
|
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -931,7 +931,7 @@ static void test_selection(void)
|
||||||
static void test_thumb_length(void)
|
static void test_thumb_length(void)
|
||||||
{
|
{
|
||||||
HWND hWndTrackbar;
|
HWND hWndTrackbar;
|
||||||
int r;
|
int r, r2;
|
||||||
|
|
||||||
hWndTrackbar = create_trackbar(defaultstyle, hWndParent);
|
hWndTrackbar = create_trackbar(defaultstyle, hWndParent);
|
||||||
ok(hWndTrackbar != NULL, "Expected non NULL value\n");
|
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);
|
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_thumb_length_test_seq, "parent thumb length test sequence", TRUE);
|
||||||
|
|
||||||
DestroyWindow(hWndTrackbar);
|
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)
|
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,
|
visibleItem = (HTREEITEM)SendMessageA(pHdr->hwndFrom, TVM_GETNEXTITEM,
|
||||||
TVGN_NEXTVISIBLE, (LPARAM)visibleItem);
|
TVGN_NEXTVISIBLE, (LPARAM)visibleItem);
|
||||||
*(HTREEITEM*)&rect = 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),
|
ok(SendMessageA(pHdr->hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rect),
|
||||||
"Failed to get rect for second visible item.\n");
|
"Failed to get rect for second visible item.\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
* - check UDM_SETBUDDY message
|
* - check UDM_SETBUDDY message
|
||||||
* - check UDM_GETBUDDY message
|
* - check UDM_GETBUDDY message
|
||||||
* - up-down control and buddy control must have the same parent
|
* - 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 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 UDS_SETBUDDYINT sets the caption of the buddy window when it is changed
|
||||||
* - check that the thousands operator is set for large numbers
|
* - check that the thousands operator is set for large numbers
|
||||||
|
@ -165,6 +164,32 @@ static const struct message test_updown_pos_nochange_seq[] = {
|
||||||
{ 0 }
|
{ 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 LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
static LONG defwndproc_counter = 0;
|
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;
|
if (defwndproc_counter) msg.flags |= defwinproc;
|
||||||
msg.wParam = wParam;
|
msg.wParam = wParam;
|
||||||
msg.lParam = lParam;
|
msg.lParam = lParam;
|
||||||
|
if (message == WM_NOTIFY && lParam)
|
||||||
|
msg.id = ((NMHDR*)lParam)->code;
|
||||||
add_message(sequences, PARENT_SEQ_INDEX, &msg);
|
add_message(sequences, PARENT_SEQ_INDEX, &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,6 +927,52 @@ static void test_CreateUpDownControl(void)
|
||||||
DestroyWindow(updown);
|
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)
|
static void init_functions(void)
|
||||||
{
|
{
|
||||||
HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
|
HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
|
||||||
|
@ -931,6 +1004,7 @@ START_TEST(updown)
|
||||||
test_updown_unicode();
|
test_updown_unicode();
|
||||||
test_UDS_SETBUDDYINT();
|
test_UDS_SETBUDDYINT();
|
||||||
test_CreateUpDownControl();
|
test_CreateUpDownControl();
|
||||||
|
test_updown_pos_notifications();
|
||||||
|
|
||||||
DestroyWindow(g_edit);
|
DestroyWindow(g_edit);
|
||||||
DestroyWindow(parent_wnd);
|
DestroyWindow(parent_wnd);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue