[COMCTL32_WINETEST] Sync with Wine Staging 4.18. CORE-16441

This commit is contained in:
Amine Khaldi 2019-10-26 22:52:00 +01:00
parent 5ddec3d944
commit 8addeea484
11 changed files with 1316 additions and 186 deletions

File diff suppressed because it is too large Load diff

View file

@ -1485,16 +1485,31 @@ static void test_edit_control_scroll(void)
DestroyWindow (hwEdit);
}
static BOOL is_cjk(HDC dc)
{
const DWORD FS_DBCS_MASK = FS_JISJAPAN|FS_CHINESESIMP|FS_WANSUNG|FS_CHINESETRAD|FS_JOHAB;
FONTSIGNATURE fs;
switch (GdiGetCodePage(dc)) {
case 932: case 936: case 949: case 950: case 1361:
return TRUE;
default:
return (GetTextCharsetInfo(dc, &fs, 0) != DEFAULT_CHARSET &&
(fs.fsCsb[0] & FS_DBCS_MASK));
}
}
static void test_margins_usefontinfo(UINT charset)
{
INT margins, threshold, expect, empty_expect, small_expect;
HWND hwnd;
HDC hdc;
TEXTMETRICW tm;
SIZE size;
BOOL cjk;
LOGFONTA lf;
HFONT hfont;
RECT rect;
INT margins, threshold, expect, empty_expect;
const UINT small_margins = MAKELONG(1, 5);
memset(&lf, 0, sizeof(lf));
lf.lfHeight = -11;
@ -1513,43 +1528,31 @@ static void test_margins_usefontinfo(UINT charset)
hdc = GetDC(hwnd);
hfont = SelectObject(hdc, hfont);
size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy );
expect = MAKELONG(size.cx / 2, size.cx / 2);
small_expect = 0;
empty_expect = size.cx >= 28 ? small_expect : expect;
charset = GetTextCharset(hdc);
switch (charset)
{
case SHIFTJIS_CHARSET:
case HANGUL_CHARSET:
case GB2312_CHARSET:
case CHINESEBIG5_CHARSET:
cjk = TRUE;
break;
default:
cjk = FALSE;
size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
!(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
hfont = SelectObject(hdc, hfont);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
DeleteObject(hfont);
return;
}
expect = MAKELONG(size.cx / 2, size.cx / 2);
hfont = SelectObject(hdc, hfont);
ReleaseDC(hwnd, hdc);
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
if (!cjk)
ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
else
{
ok(HIWORD(margins) > 0 && LOWORD(margins) > 0, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
expect = empty_expect = small_expect = margins;
}
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
expect = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
DestroyWindow(hwnd);
threshold = (size.cx / 2 + size.cx) * 2;
threshold = HIWORD(expect) + LOWORD(expect) + size.cx * 2;
empty_expect = threshold > 80 ? small_margins : expect;
/* Size below which non-cjk margins are zero */
/* Size below the threshold, margins remain unchanged */
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold - 1, 100, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "got %p\n", hwnd);
GetClientRect(hwnd, &rect);
@ -1559,11 +1562,13 @@ static void test_margins_usefontinfo(UINT charset)
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == small_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
ok(margins == small_margins, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
DestroyWindow(hwnd);
/* Size at which non-cjk margins become non-zero */
/* Size at the threshold, margins become non-zero */
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, threshold, 100, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "got %p\n", hwnd);
GetClientRect(hwnd, &rect);
@ -1573,6 +1578,8 @@ static void test_margins_usefontinfo(UINT charset)
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
DestroyWindow(hwnd);
@ -1587,6 +1594,8 @@ static void test_margins_usefontinfo(UINT charset)
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == empty_expect, "%d: got %d, %d\n", charset, HIWORD(margins), LOWORD(margins));
DestroyWindow(hwnd);
@ -1594,6 +1603,151 @@ static void test_margins_usefontinfo(UINT charset)
DeleteObject(hfont);
}
static INT get_cjk_fontinfo_margin(INT width, INT side_bearing)
{
INT margin;
if (side_bearing < 0)
margin = min(-side_bearing, width/2);
else
margin = 0;
return margin;
}
static DWORD get_cjk_font_margins(HDC hdc)
{
ABC abc[256];
SHORT left, right;
UINT i;
if (!GetCharABCWidthsW(hdc, 0, 255, abc))
return 0;
left = right = 0;
for (i = 0; i < ARRAY_SIZE(abc); i++) {
if (-abc[i].abcA > right) right = -abc[i].abcA;
if (-abc[i].abcC > left) left = -abc[i].abcC;
}
return MAKELONG(left, right);
}
static void test_margins_default(const char* facename, UINT charset)
{
HWND hwnd;
HDC hdc;
TEXTMETRICW tm;
SIZE size;
BOOL cjk;
LOGFONTA lf;
HFONT hfont;
RECT rect;
INT margins, expect, font_expect;
const UINT small_margins = MAKELONG(1, 5);
const WCHAR EditW[] = {'E','d','i','t',0}, strW[] = {'W',0};
struct char_width_info {
INT lsb, rsb, unknown;
} info;
HMODULE hgdi32;
BOOL (WINAPI *pGetCharWidthInfo)(HDC, struct char_width_info *);
hgdi32 = GetModuleHandleA("gdi32.dll");
pGetCharWidthInfo = (void *)GetProcAddress(hgdi32, "GetCharWidthInfo");
memset(&lf, 0, sizeof(lf));
lf.lfHeight = -11;
lf.lfWeight = FW_NORMAL;
lf.lfCharSet = charset;
strcpy(lf.lfFaceName, facename);
hfont = CreateFontIndirectA(&lf);
ok(hfont != NULL, "got %p\n", hfont);
/* Unicode version */
hwnd = CreateWindowExW(0, EditW, strW, WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "got %p\n", hwnd);
GetClientRect(hwnd, &rect);
ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
hdc = GetDC(hwnd);
hfont = SelectObject(hdc, hfont);
size.cx = GdiGetCharDimensions( hdc, &tm, &size.cy );
if ((charset != tm.tmCharSet && charset != DEFAULT_CHARSET) ||
!(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR))) {
skip("%s for charset %d isn't available\n", lf.lfFaceName, charset);
hfont = SelectObject(hdc, hfont);
ReleaseDC(hwnd, hdc);
DestroyWindow(hwnd);
DeleteObject(hfont);
return;
}
cjk = is_cjk(hdc);
if (cjk && pGetCharWidthInfo && pGetCharWidthInfo(hdc, &info)) {
short left, right;
left = get_cjk_fontinfo_margin(size.cx, info.lsb);
right = get_cjk_fontinfo_margin(size.cx, info.rsb);
expect = MAKELONG(left, right);
font_expect = get_cjk_font_margins(hdc);
if (!font_expect)
/* In this case, margins aren't updated */
font_expect = small_margins;
}
else
font_expect = expect = MAKELONG(size.cx / 2, size.cx / 2);
hfont = SelectObject(hdc, hfont);
ReleaseDC(hwnd, hdc);
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins));
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
DestroyWindow(hwnd);
/* ANSI version */
hwnd = CreateWindowExA(0, "Edit", "A", WS_POPUP, 0, 0, 5000, 1000, NULL, NULL, NULL, NULL);
ok(hwnd != NULL, "got %p\n", hwnd);
GetClientRect(hwnd, &rect);
ok(!IsRectEmpty(&rect), "got rect %s\n", wine_dbgstr_rect(&rect));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == 0, "got %x\n", margins);
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
SendMessageA(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == font_expect, "%s:%d: got %d, %d\n", facename, charset, HIWORD(margins), LOWORD(margins));
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, small_margins);
SendMessageA(hwnd, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO, EC_USEFONTINFO));
margins = SendMessageA(hwnd, EM_GETMARGINS, 0, 0);
ok(margins == expect, "%s:%d: expected %d, %d, got %d, %d\n", facename, charset, HIWORD(expect), LOWORD(expect), HIWORD(margins), LOWORD(margins));
DestroyWindow(hwnd);
DeleteObject(hfont);
}
static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
{
return 0;
}
static BOOL is_font_installed(const char*name)
{
HDC hdc = GetDC(NULL);
BOOL ret = FALSE;
if (!EnumFontFamiliesA(hdc, name, find_font_proc, 0))
ret = TRUE;
ReleaseDC(NULL, hdc);
return ret;
}
static void test_margins(void)
{
DWORD old_margins, new_margins;
@ -1668,27 +1822,45 @@ static void test_margins(void)
but not by < Win 8 and Win 10. */
test_margins_usefontinfo(DEFAULT_CHARSET);
}
static INT CALLBACK find_font_proc(const LOGFONTA *elf, const TEXTMETRICA *ntm, DWORD type, LPARAM lParam)
{
return 0;
test_margins_default("Tahoma", ANSI_CHARSET);
test_margins_default("Tahoma", EASTEUROPE_CHARSET);
test_margins_default("Tahoma", HANGUL_CHARSET);
test_margins_default("Tahoma", CHINESEBIG5_CHARSET);
if (is_font_installed("MS PGothic")) {
test_margins_default("MS PGothic", SHIFTJIS_CHARSET);
test_margins_default("MS PGothic", GREEK_CHARSET);
}
else
skip("MS PGothic is not available, skipping some margin tests\n");
if (is_font_installed("Ume P Gothic")) {
test_margins_default("Ume P Gothic", SHIFTJIS_CHARSET);
test_margins_default("Ume P Gothic", GREEK_CHARSET);
}
else
skip("Ume P Gothic is not available, skipping some margin tests\n");
if (is_font_installed("SimSun")) {
test_margins_default("SimSun", GB2312_CHARSET);
test_margins_default("SimSun", ANSI_CHARSET);
}
else
skip("SimSun is not available, skipping some margin tests\n");
}
static void test_margins_font_change(void)
{
DWORD margins, font_margins, ret;
DWORD margins, font_margins;
HFONT hfont, hfont2;
HWND hwEdit;
LOGFONTA lf;
HDC hdc;
hdc = GetDC(0);
ret = EnumFontFamiliesA(hdc, "Arial", find_font_proc, 0);
ReleaseDC(0, hdc);
if (ret)
if (!is_font_installed("Arial"))
{
trace("Arial not found - skipping font change margin tests\n");
skip("Arial not found - skipping font change margin tests\n");
return;
}
@ -1699,7 +1871,7 @@ static void test_margins_font_change(void)
memset(&lf, 0, sizeof(lf));
strcpy(lf.lfFaceName, "Arial");
lf.lfHeight = 16;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfCharSet = GREEK_CHARSET; /* to avoid associated charset feature */
hfont = CreateFontIndirectA(&lf);
lf.lfHeight = 30;
hfont2 = CreateFontIndirectA(&lf);
@ -3143,6 +3315,9 @@ static void test_change_focus(void)
HWND hwnd, parent_wnd;
WNDPROC oldproc;
MSG msg;
POINT orig_pos;
GetCursorPos(&orig_pos);
parent_wnd = CreateWindowA("ParentWnd", "", WS_OVERLAPPEDWINDOW,
0, 0, 200, 200, NULL, NULL, GetModuleHandleA(NULL), NULL);
@ -3157,6 +3332,8 @@ static void test_change_focus(void)
oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)edit_subclass_proc);
SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
SetCursorPos(400, 400);
SetFocus(parent_wnd);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
SetFocus(hwnd);
@ -3168,6 +3345,8 @@ static void test_change_focus(void)
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
ok_sequence(sequences, COMBINED_SEQ_INDEX, killfocus_combined_seq, "Kill focus", TRUE);
SetCursorPos(orig_pos.x, orig_pos.y);
DestroyWindow(hwnd);
}

View file

@ -1563,8 +1563,7 @@ cleanup:
if(hbmDst)
DeleteObject(hbmDst);
if(hdcDst)
DeleteDC(hdcDst);
DeleteDC(hdcDst);
if(hbmMask)
DeleteObject(hbmMask);
@ -2181,7 +2180,7 @@ static void test_color_table(UINT ilc)
rgb[2].rgbBlue = 0xff;
check_color_table("remove all, add 8", hdc, himl, ilc, rgb, default_table);
/* remove all, add 4. Color table remains the same since it's inplicitly
/* remove all, add 4. Color table remains the same since it's implicitly
been set by the previous _Add */
ret = pImageList_Remove(himl, -1);
ok(ret, "got %d\n", ret);

View file

@ -784,6 +784,135 @@ static void test_listbox_height(void)
DestroyWindow( hList );
}
static void test_changing_selection_styles(void)
{
static const DWORD styles[] =
{
0,
LBS_NODATA | LBS_OWNERDRAWFIXED
};
static const DWORD selstyles[] =
{
0,
LBS_MULTIPLESEL,
LBS_EXTENDEDSEL,
LBS_MULTIPLESEL | LBS_EXTENDEDSEL
};
static const LONG selexpect_single[] = { 0, 0, 1 };
static const LONG selexpect_single2[] = { 1, 0, 0 };
static const LONG selexpect_multi[] = { 1, 0, 1 };
static const LONG selexpect_multi2[] = { 1, 1, 0 };
HWND parent, listbox;
DWORD style;
LONG ret;
UINT i, j, k;
parent = create_parent();
ok(parent != NULL, "Failed to create parent window.\n");
for (i = 0; i < ARRAY_SIZE(styles); i++)
{
/* Test if changing selection styles affects selection storage */
for (j = 0; j < ARRAY_SIZE(selstyles); j++)
{
LONG setcursel_expect, selitemrange_expect, getselcount_expect;
const LONG *selexpect;
listbox = CreateWindowA(WC_LISTBOXA, "TestList", styles[i] | selstyles[j] | WS_CHILD | WS_VISIBLE,
0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0);
ok(listbox != NULL, "%u: Failed to create ListBox window.\n", j);
if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
{
setcursel_expect = LB_ERR;
selitemrange_expect = LB_OKAY;
getselcount_expect = 2;
selexpect = selexpect_multi;
}
else
{
setcursel_expect = 2;
selitemrange_expect = LB_ERR;
getselcount_expect = LB_ERR;
selexpect = selexpect_single;
}
for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
{
ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"x");
ok(ret == k, "%u: Unexpected return value %d, expected %d.\n", j, ret, k);
}
ret = SendMessageA(listbox, LB_GETCOUNT, 0, 0);
ok(ret == ARRAY_SIZE(selexpect_multi), "%u: Unexpected count %d.\n", j, ret);
/* Select items with different methods */
ret = SendMessageA(listbox, LB_SETCURSEL, 2, 0);
ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(0, 0));
ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(2, 2));
ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
/* Verify that the proper items are selected */
for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
{
ret = SendMessageA(listbox, LB_GETSEL, k, 0);
ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
j, ret, selexpect[k]);
}
/* Now change the selection style */
style = GetWindowLongA(listbox, GWL_STYLE);
ok((style & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) == selstyles[j],
"%u: unexpected window styles %#x.\n", j, style);
if (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL))
style &= ~selstyles[j];
else
style |= LBS_MULTIPLESEL | LBS_EXTENDEDSEL;
SetWindowLongA(listbox, GWL_STYLE, style);
style = GetWindowLongA(listbox, GWL_STYLE);
ok(!(style & selstyles[j]), "%u: unexpected window styles %#x.\n", j, style);
/* Verify that the same items are selected */
ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
j, getselcount_expect, ret);
for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
{
ret = SendMessageA(listbox, LB_GETSEL, k, 0);
ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
j, ret, selexpect[k]);
}
/* Lastly see if we can still change the selection as before with old style */
if (setcursel_expect != LB_ERR) setcursel_expect = 0;
ret = SendMessageA(listbox, LB_SETCURSEL, 0, 0);
ok(ret == setcursel_expect, "%u: Unexpected return value %d.\n", j, ret);
ret = SendMessageA(listbox, LB_SELITEMRANGE, TRUE, MAKELPARAM(1, 1));
ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
ret = SendMessageA(listbox, LB_SELITEMRANGE, FALSE, MAKELPARAM(2, 2));
ok(ret == selitemrange_expect, "%u: Unexpected return value %d.\n", j, ret);
/* And verify the selections */
selexpect = (selstyles[j] & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) ? selexpect_multi2 : selexpect_single2;
ret = SendMessageA(listbox, LB_GETSELCOUNT, 0, 0);
ok(ret == getselcount_expect, "%u: expected %d from LB_GETSELCOUNT, got %d\n",
j, getselcount_expect, ret);
for (k = 0; k < ARRAY_SIZE(selexpect_multi); k++)
{
ret = SendMessageA(listbox, LB_GETSEL, k, 0);
ok(ret == selexpect[k], "%u: Unexpected selection state %d, expected %d.\n",
j, ret, selexpect[k]);
}
DestroyWindow(listbox);
}
}
DestroyWindow(parent);
}
static void test_itemfrompoint(void)
{
/* WS_POPUP is required in order to have a more accurate size calculation (
@ -1812,7 +1941,7 @@ static void test_listbox_dlgdir(void)
strcpy(pathBuffer, "C:\\");
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
ok(res, "DlgDirList failed to list C:\\ folders\n");
todo_wine ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
ok(!strcmp(pathBuffer, "*"), "DlgDirList set the invalid path spec '%s', expected '*'\n", pathBuffer);
strcpy(pathBuffer, "C:\\*");
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
@ -1823,8 +1952,8 @@ static void test_listbox_dlgdir(void)
SetLastError(0xdeadbeef);
strcpy(pathBuffer, "C:\\INVALID$$DIR");
res = DlgDirListA(hWnd, pathBuffer, ID_TEST_LISTBOX, 0, DDL_DIRECTORY | DDL_EXCLUSIVE);
todo_wine ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
todo_wine ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
ok(!res, "DlgDirList should have failed with 0 but %d was returned\n", res);
ok(GetLastError() == ERROR_NO_WILDCARD_CHARACTERS,
"GetLastError should return 0x589, got 0x%X\n",GetLastError());
DestroyWindow(hWnd);
@ -1867,6 +1996,11 @@ static void test_set_count( void )
GetUpdateRect( listbox, &r, TRUE );
ok( !IsRectEmpty( &r ), "got empty rect\n");
ret = SendMessageA( listbox, LB_SETCOUNT, -5, 0 );
ok( ret == 0, "got %d\n", ret );
ret = SendMessageA( listbox, LB_GETCOUNT, 0, 0 );
ok( ret == -5, "got %d\n", ret );
DestroyWindow( listbox );
for (i = 0; i < ARRAY_SIZE(styles); ++i)
@ -1906,6 +2040,69 @@ static void test_GetListBoxInfo(void)
DestroyWindow(parent);
}
static void test_init_storage( void )
{
static const DWORD styles[] =
{
LBS_HASSTRINGS,
LBS_NODATA | LBS_OWNERDRAWFIXED,
};
HWND parent, listbox;
LONG ret, items_size;
int i, j;
parent = create_parent();
for (i = 0; i < ARRAY_SIZE(styles); i++)
{
listbox = CreateWindowA(WC_LISTBOXA, "TestList", styles[i] | WS_CHILD,
0, 0, 100, 100, parent, (HMENU)ID_LISTBOX, NULL, 0);
items_size = SendMessageA(listbox, LB_INITSTORAGE, 100, 0);
ok(items_size >= 100, "expected at least 100, got %d\n", items_size);
ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
/* it doesn't grow since the space was already reserved */
ret = SendMessageA(listbox, LB_INITSTORAGE, items_size, 0);
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
/* it doesn't shrink the reserved space */
ret = SendMessageA(listbox, LB_INITSTORAGE, 42, 0);
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
/* now populate almost all of it so it's not reserved anymore */
if (styles[i] & LBS_NODATA)
{
ret = SendMessageA(listbox, LB_SETCOUNT, items_size - 1, 0);
ok(ret == 0, "unexpected return value %d\n", ret);
}
else
{
for (j = 0; j < items_size - 1; j++)
{
ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
ok(ret == j, "expected %d, got %d\n", j, ret);
}
}
/* we still have one more reserved slot, so it doesn't grow yet */
ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
/* fill the slot and check again, it should grow this time */
ret = SendMessageA(listbox, LB_INSERTSTRING, -1, (LPARAM)"");
ok(ret == items_size - 1, "expected %d, got %d\n", items_size - 1, ret);
ret = SendMessageA(listbox, LB_INITSTORAGE, 0, 0);
ok(ret == items_size, "expected %d, got %d\n", items_size, ret);
ret = SendMessageA(listbox, LB_INITSTORAGE, 1, 0);
ok(ret > items_size, "expected it to grow past %d, got %d\n", items_size, ret);
DestroyWindow(listbox);
}
DestroyWindow(parent);
}
static void test_missing_lbuttonup(void)
{
HWND listbox, parent, capture;
@ -2420,11 +2617,13 @@ START_TEST(listbox)
test_LB_SELITEMRANGE();
test_LB_SETCURSEL();
test_listbox_height();
test_changing_selection_styles();
test_itemfrompoint();
test_listbox_item_data();
test_listbox_LB_DIR();
test_listbox_dlgdir();
test_set_count();
test_init_storage();
test_GetListBoxInfo();
test_missing_lbuttonup();
test_extents();

View file

@ -6475,6 +6475,86 @@ static void test_LVM_GETCOUNTPERPAGE(void)
ok(ret, "Failed to unregister test class.\n");
}
static void test_item_state_change(void)
{
static const DWORD styles[] = { LVS_ICON, LVS_LIST, LVS_REPORT, LVS_SMALLICON };
LVITEMA item;
HWND hwnd;
DWORD res;
int i;
for (i = 0; i < ARRAY_SIZE(styles); i++)
{
hwnd = create_listview_control(styles[i]);
insert_item(hwnd, 0);
/* LVM_SETITEMSTATE with mask */
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
memset(&item, 0, sizeof(item));
item.mask = LVIF_STATE;
item.stateMask = LVIS_SELECTED;
item.state = LVIS_SELECTED;
res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
ok(res, "Failed to set item state.\n");
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState);
ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
/* LVM_SETITEMSTATE 0 mask */
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
memset(&item, 0, sizeof(item));
item.stateMask = LVIS_SELECTED;
item.state = 0;
res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
ok(res, "Failed to set item state.\n");
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState);
ok(g_nmlistview.uOldState == LVIS_SELECTED, "Unexpected old state %#x.\n", g_nmlistview.uOldState);
ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
/* LVM_SETITEM changes state */
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
memset(&item, 0, sizeof(item));
item.stateMask = LVIS_SELECTED;
item.state = LVIS_SELECTED;
item.mask = LVIF_STATE;
res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
ok(res, "Failed to set item.\n");
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
ok(g_nmlistview.uNewState == LVIS_SELECTED, "Unexpected new state %#x.\n", g_nmlistview.uNewState);
ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState);
ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
/* LVM_SETITEM no state changes */
memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
memset(&item, 0, sizeof(item));
item.lParam = 11;
item.mask = LVIF_PARAM;
res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
ok(res, "Failed to set item.\n");
ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState);
ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState);
ok(g_nmlistview.uChanged == LVIF_PARAM, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
DestroyWindow(hwnd);
}
}
START_TEST(listview)
{
ULONG_PTR ctx_cookie;
@ -6538,6 +6618,7 @@ START_TEST(listview)
test_LVSCW_AUTOSIZE();
test_LVN_ENDLABELEDIT();
test_LVM_GETCOUNTPERPAGE();
test_item_state_change();
if (!load_v6_module(&ctx_cookie, &hCtx))
{
@ -6582,6 +6663,7 @@ START_TEST(listview)
test_LVSCW_AUTOSIZE();
test_LVN_ENDLABELEDIT();
test_LVM_GETCOUNTPERPAGE();
test_item_state_change();
unload_v6_module(ctx_cookie, hCtx);

View file

@ -564,9 +564,11 @@ static void test_wm_notifyformat(void)
static const INT formats[] = {NFR_UNICODE, NFR_ANSI};
HWND parent, pager, child;
LRESULT ret;
BOOL bret;
INT i;
ok(register_notifyformat_class(), "Register test class failed, error 0x%08x\n", GetLastError());
bret = register_notifyformat_class();
ok(bret, "Register test class failed, error 0x%08x\n", GetLastError());
for (i = 0; i < ARRAY_SIZE(formats); i++)
{
@ -1280,9 +1282,11 @@ static void test_wm_notify(void)
{&nmtv, sizeof(nmtv), &nmtv.itemOld.mask, TVIF_TEXT, &nmtv.itemOld.pszText, &nmtv.itemOld.cchTextMax,
TVN_SELCHANGEDW, TVN_SELCHANGEDA, CONVERT_SEND, TVITEM_OLD_HANDLER}
};
BOOL bret;
INT i;
ok(register_test_notify_class(), "Register test class failed, error 0x%08x\n", GetLastError());
bret = register_test_notify_class();
ok(bret, "Register test class failed, error 0x%08x\n", GetLastError());
parent = CreateWindowA(class, "parent", WS_OVERLAPPED, 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), 0);
ok(parent != NULL, "CreateWindow failed\n");

View file

@ -254,6 +254,13 @@ static void test_PBM_STEPIT(void)
{ 3, 15, 5 },
{ 3, 15, -5 },
{ 3, 15, 50 },
{ -15, 15, 5 },
{ -3, -2, -5 },
{ 0, 0, 1 },
{ 5, 5, 1 },
{ 0, 0, -1 },
{ 5, 5, -1 },
{ 10, 5, 2 },
};
HWND progress;
int i, j;
@ -261,6 +268,7 @@ static void test_PBM_STEPIT(void)
for (i = 0; i < ARRAY_SIZE(stepit_tests); i++)
{
struct stepit_test *test = &stepit_tests[i];
PBRANGE range;
LRESULT ret;
progress = create_progress(0);
@ -268,6 +276,9 @@ static void test_PBM_STEPIT(void)
ret = SendMessageA(progress, PBM_SETRANGE32, test->min, test->max);
ok(ret != 0, "Unexpected return value.\n");
SendMessageA(progress, PBM_GETRANGE, 0, (LPARAM)&range);
ok(range.iLow == test->min && range.iHigh == test->max, "Unexpected range.\n");
SendMessageA(progress, PBM_SETPOS, test->min, 0);
SendMessageA(progress, PBM_SETSTEP, test->step, 0);
@ -277,15 +288,20 @@ static void test_PBM_STEPIT(void)
int current;
pos += test->step;
if (pos > test->max)
pos = (pos - test->min) % (test->max - test->min) + test->min;
if (pos < test->min)
pos = (pos - test->min) % (test->max - test->min) + test->max;
if (test->min != test->max)
{
if (pos > test->max)
pos = (pos - test->min) % (test->max - test->min) + test->min;
if (pos < test->min)
pos = (pos - test->min) % (test->max - test->min) + test->max;
}
else
pos = test->min;
SendMessageA(progress, PBM_STEPIT, 0, 0);
current = SendMessageA(progress, PBM_GETPOS, 0, 0);
ok(current == pos, "Unexpected position %d, expected %d.\n", current, pos);
ok(current == pos, "%u: unexpected position %d, expected %d.\n", i, current, pos);
}
DestroyWindow(progress);

View file

@ -273,6 +273,9 @@ static void test_subclass(void)
ret = pSetWindowSubclass(hwnd, NULL, 1, 0);
ok(ret == FALSE, "Expected FALSE\n");
pRemoveWindowSubclass(hwnd, wnd_proc_sub, 2);
pRemoveWindowSubclass(hwnd, wnd_proc_sub, 5);
DestroyWindow(hwnd);
}

View file

@ -931,7 +931,7 @@ static void test_selection(void)
static void test_thumb_length(void)
{
HWND hWndTrackbar;
int r;
int r, r2;
hWndTrackbar = create_trackbar(defaultstyle, hWndParent);
ok(hWndTrackbar != NULL, "Expected non NULL value\n");
@ -963,6 +963,22 @@ static void test_thumb_length(void)
ok_sequence(sequences, PARENT_SEQ_INDEX, parent_thumb_length_test_seq, "parent thumb length test sequence", TRUE);
DestroyWindow(hWndTrackbar);
/* Fixed thumb length does not depend on window size. */
hWndTrackbar = CreateWindowA(TRACKBAR_CLASSA, "Trackbar Control", WS_VISIBLE | TBS_ENABLESELRANGE
| TBS_FIXEDLENGTH, 0, 0, 0, 0, hWndParent, NULL, GetModuleHandleA(NULL), NULL);
r = SendMessageA(hWndTrackbar, TBM_GETTHUMBLENGTH, 0, 0);
DestroyWindow(hWndTrackbar);
hWndTrackbar = CreateWindowA(TRACKBAR_CLASSA, "Trackbar Control", WS_VISIBLE | TBS_ENABLESELRANGE
| TBS_FIXEDLENGTH, 0, 0, 200, 200, hWndParent, NULL, GetModuleHandleA(NULL), NULL);
r2 = SendMessageA(hWndTrackbar, TBM_GETTHUMBLENGTH, 0, 0);
ok(r2 == r, "Unexpected thumb length %d.\n", r);
DestroyWindow(hWndTrackbar);
}
static void test_tic_settings(void)

View file

@ -1364,7 +1364,7 @@ static LRESULT CALLBACK parent_wnd_proc(HWND hWnd, UINT message, WPARAM wParam,
visibleItem = (HTREEITEM)SendMessageA(pHdr->hwndFrom, TVM_GETNEXTITEM,
TVGN_NEXTVISIBLE, (LPARAM)visibleItem);
*(HTREEITEM*)&rect = visibleItem;
ok(visibleItem != NULL, "There must be a visible item after the first visisble item.\n");
ok(visibleItem != NULL, "There must be a visible item after the first one.\n");
ok(SendMessageA(pHdr->hwndFrom, TVM_GETITEMRECT, TRUE, (LPARAM)&rect),
"Failed to get rect for second visible item.\n");
}

View file

@ -28,7 +28,6 @@
* - check UDM_SETBUDDY message
* - check UDM_GETBUDDY message
* - up-down control and buddy control must have the same parent
* - up-down control notifies its parent window when its position changes with UDN_DELTAPOS + WM_VSCROLL or WM_HSCROLL
* - check UDS_ALIGN[LEFT,RIGHT]...check that width of buddy window is decreased
* - check that UDS_SETBUDDYINT sets the caption of the buddy window when it is changed
* - check that the thousands operator is set for large numbers
@ -165,6 +164,32 @@ static const struct message test_updown_pos_nochange_seq[] = {
{ 0 }
};
static const struct message test_updown_pos_notifications_seq[] = {
{ WM_CTLCOLOREDIT, sent|optional },
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_SETFOCUS) },
{ WM_NOTIFY, sent|id, 0, 0, UDN_DELTAPOS },
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_UPDATE) },
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_CHANGE) },
{ WM_VSCROLL, sent|wparam, MAKELONG(SB_THUMBPOSITION, 51) },
{ WM_CTLCOLOREDIT, sent|optional },
{ WM_VSCROLL, sent|wparam, MAKELONG(SB_ENDSCROLL, 51) },
/* no WM_NOTIFY(NM_RELEASEDCAPTURE) message */
{ 0 }
};
static const struct message test_updown_pos_notifications_horz_seq[] = {
{ WM_CTLCOLOREDIT, sent|optional },
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_SETFOCUS) },
{ WM_NOTIFY, sent|id, 0, 0, UDN_DELTAPOS },
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_UPDATE) },
{ WM_COMMAND, sent|wparam, MAKELONG(0, EN_CHANGE) },
{ WM_HSCROLL, sent|wparam, MAKELONG(SB_THUMBPOSITION, 51) },
{ WM_CTLCOLOREDIT, sent|optional },
{ WM_HSCROLL, sent|wparam, MAKELONG(SB_ENDSCROLL, 51) },
/* no WM_NOTIFY(NM_RELEASEDCAPTURE) message */
{ 0 }
};
static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static LONG defwndproc_counter = 0;
@ -186,6 +211,8 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
if (defwndproc_counter) msg.flags |= defwinproc;
msg.wParam = wParam;
msg.lParam = lParam;
if (message == WM_NOTIFY && lParam)
msg.id = ((NMHDR*)lParam)->code;
add_message(sequences, PARENT_SEQ_INDEX, &msg);
}
@ -900,6 +927,52 @@ static void test_CreateUpDownControl(void)
DestroyWindow(updown);
}
static void test_updown_pos_notifications(void)
{
HWND updown;
RECT rect;
UINT x, y;
int result;
/* test updown control notifications without UDS_HORZ style */
updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT, g_edit);
SetFocus(updown);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* click on the up-arrow button */
GetClientRect(updown, &rect);
x = rect.left + (rect.right - rect.left) / 2;
y = rect.top + (rect.bottom - rect.top) / 4;
result = SendMessageA(updown, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));
expect(result, 0);
result = SendMessageA(updown, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
expect(result, 0);
ok_sequence(sequences, PARENT_SEQ_INDEX, test_updown_pos_notifications_seq,
"test updown to parent notify (vertical)", FALSE);
DestroyWindow(updown);
/* test updown control notifications with UDS_HORZ style */
updown = create_updown_control(UDS_ALIGNRIGHT | UDS_SETBUDDYINT | UDS_HORZ, g_edit);
SetFocus(updown);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* click on the right-arrow button */
GetClientRect(updown, &rect);
x = rect.left + (rect.right - rect.left) * 3 / 4;
y = rect.top + (rect.bottom - rect.top) / 2;
result = SendMessageA(updown, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));
expect(result, 0);
result = SendMessageA(updown, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
expect(result, 0);
ok_sequence(sequences, PARENT_SEQ_INDEX, test_updown_pos_notifications_horz_seq,
"test updown to parent notify (horizontal)", FALSE);
DestroyWindow(updown);
}
static void init_functions(void)
{
HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
@ -931,6 +1004,7 @@ START_TEST(updown)
test_updown_unicode();
test_UDS_SETBUDDYINT();
test_CreateUpDownControl();
test_updown_pos_notifications();
DestroyWindow(g_edit);
DestroyWindow(parent_wnd);