/* Unit test suite for header control. * * Copyright 2005 Vijay Kiran Kamuju * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include "wine/test.h" typedef struct tagEXPECTEDNOTIFY { INT iCode; BOOL fUnicode; HDITEMA hdItem; } EXPECTEDNOTIFY; EXPECTEDNOTIFY expectedNotify[10]; INT nExpectedNotify = 0; INT nReceivedNotify = 0; static HWND hHeaderParentWnd; static HWND hWndHeader; #define MAX_CHARS 100 static void expect_notify(INT iCode, BOOL fUnicode, HDITEMA *lpItem) { assert(nExpectedNotify < 10); expectedNotify[nExpectedNotify].iCode = iCode; expectedNotify[nExpectedNotify].fUnicode = fUnicode; expectedNotify[nExpectedNotify].hdItem = *lpItem; nExpectedNotify++; } static BOOL notifies_received() { BOOL fRet = (nExpectedNotify == nReceivedNotify); nExpectedNotify = nReceivedNotify = 0; return fRet; } static LONG addItem(HWND hdex, int idx, LPCSTR text) { HDITEMA hdItem; hdItem.mask = HDI_TEXT | HDI_WIDTH; hdItem.cxy = 100; hdItem.pszText = (LPSTR)text; hdItem.cchTextMax = 0; return (LONG)SendMessage(hdex, HDM_INSERTITEMA, (WPARAM)idx, (LPARAM)&hdItem); } static LONG setItem(HWND hdex, int idx, LPCSTR text, BOOL fCheckNotifies) { LONG ret; HDITEMA hdexItem; hdexItem.mask = HDI_TEXT; hdexItem.pszText = (LPSTR)text; hdexItem.cchTextMax = 0; if (fCheckNotifies) { expect_notify(HDN_ITEMCHANGINGA, FALSE, &hdexItem); expect_notify(HDN_ITEMCHANGEDA, FALSE, &hdexItem); } ret = (LONG)SendMessage(hdex, HDM_SETITEMA, (WPARAM)idx, (LPARAM)&hdexItem); if (fCheckNotifies) ok(notifies_received(), "setItem(): not all expected notifies were received\n"); return ret; } static LONG setItemUnicodeNotify(HWND hdex, int idx, LPCSTR text, LPCWSTR wText) { LONG ret; HDITEMA hdexItem; HDITEMW hdexNotify; hdexItem.mask = HDI_TEXT; hdexItem.pszText = (LPSTR)text; hdexItem.cchTextMax = 0; hdexNotify.mask = HDI_TEXT; hdexNotify.pszText = (LPWSTR)wText; expect_notify(HDN_ITEMCHANGINGW, TRUE, (HDITEMA*)&hdexNotify); expect_notify(HDN_ITEMCHANGEDW, TRUE, (HDITEMA*)&hdexNotify); ret = (LONG)SendMessage(hdex, HDM_SETITEMA, (WPARAM)idx, (LPARAM)&hdexItem); ok(notifies_received(), "setItemUnicodeNotify(): not all expected notifies were received\n"); return ret; } static LONG delItem(HWND hdex, int idx) { return (LONG)SendMessage(hdex, HDM_DELETEITEM, (WPARAM)idx, 0); } static LONG getItemCount(HWND hdex) { return (LONG)SendMessage(hdex, HDM_GETITEMCOUNT, 0, 0); } static LONG getItem(HWND hdex, int idx, LPSTR textBuffer) { HDITEMA hdItem; hdItem.mask = HDI_TEXT; hdItem.pszText = textBuffer; hdItem.cchTextMax = MAX_CHARS; return (LONG)SendMessage(hdex, HDM_GETITEMA, (WPARAM)idx, (LPARAM)&hdItem); } static HWND create_header_control (void) { HWND handle; HDLAYOUT hlayout; RECT rectwin; WINDOWPOS winpos; handle = CreateWindowEx(0, WC_HEADER, NULL, WS_CHILD|WS_BORDER|WS_VISIBLE|HDS_BUTTONS|HDS_HORZ, 0, 0, 0, 0, hHeaderParentWnd, NULL, NULL, NULL); assert(handle); if (winetest_interactive) ShowWindow (hHeaderParentWnd, SW_SHOW); GetClientRect(hHeaderParentWnd,&rectwin); hlayout.prc = &rectwin; hlayout.pwpos = &winpos; SendMessageA(handle,HDM_LAYOUT,0,(LPARAM) &hlayout); SetWindowPos(handle, winpos.hwndInsertAfter, winpos.x, winpos.y, winpos.cx, winpos.cy, 0); return handle; } static void compare_items(INT iCode, HDITEMA *hdi1, HDITEMA *hdi2, BOOL fUnicode) { ok(hdi1->mask == hdi2->mask, "Notify %d mask mismatch (%08x != %08x)\n", iCode, hdi1->mask, hdi2->mask); if (hdi1->mask & HDI_WIDTH) { ok(hdi1->cxy == hdi2->cxy, "Notify %d cxy mismatch (%08x != %08x)\n", iCode, hdi1->cxy, hdi2->cxy); } if (hdi1->mask & HDI_TEXT) { if (fUnicode) { char buf1[260]; char buf2[260]; WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)hdi1->pszText, -1, buf1, 260, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)hdi2->pszText, -1, buf2, 260, NULL, NULL); ok(lstrcmpW((LPWSTR)hdi1->pszText, (LPWSTR)hdi2->pszText)==0, "Notify %d text mismatch (L\"%s\" vs L\"%s\")\n", iCode, buf1, buf2); } else { ok(strcmp(hdi1->pszText, hdi2->pszText)==0, "Notify %d text mismatch (\"%s\" vs \"%s\")\n", iCode, hdi1->pszText, hdi2->pszText); } } } static const char *str_items[] = {"First Item", "Second Item", "Third Item", "Fourth Item", "Replace Item", "Out Of Range Item"}; static const char pszUniTestA[] = "TST"; static const WCHAR pszUniTestW[] = {'T','S','T',0}; #define TEST_GET_ITEM(i,c)\ { res = getItem(hWndHeader, i, buffer);\ ok(res != 0, "Getting item[%d] using valid index failed unexpectedly (%ld)\n", i, res);\ ok(strcmp(str_items[c], buffer) == 0, "Getting item[%d] returned \"%s\" expecting \"%s\"\n", i, buffer, str_items[c]);\ } #define TEST_GET_ITEMCOUNT(i)\ { res = getItemCount(hWndHeader);\ ok(res == i, "Got Item Count as %ld\n", res);\ } static void test_header_control (void) { LONG res; static char buffer[MAX_CHARS]; int i; hWndHeader = create_header_control (); for (i = 3; i >= 0; i--) { TEST_GET_ITEMCOUNT(3-i); res = addItem(hWndHeader, 0, str_items[i]); ok(res == 0, "Adding simple item failed (%ld)\n", res); } TEST_GET_ITEMCOUNT(4); res = addItem(hWndHeader, 99, str_items[i+1]); ok(res != -1, "Adding Out of Range item should fail with -1 got (%ld)\n", res); TEST_GET_ITEMCOUNT(5); res = addItem(hWndHeader, 5, str_items[i+1]); ok(res != -1, "Adding Out of Range item should fail with -1 got (%ld)\n", res); TEST_GET_ITEMCOUNT(6); for (i = 0; i < 4; i++) { TEST_GET_ITEM(i,i); TEST_GET_ITEMCOUNT(6); } res=getItem(hWndHeader, 99, buffer); ok(res == 0, "Getting Out of Range item should fail with 0 (%ld), got %s\n", res,buffer); res=getItem(hWndHeader, 5, buffer); ok(res == 1, "Getting Out of Range item should fail with 1 (%ld), got %s\n", res,buffer); res=getItem(hWndHeader, -2, buffer); ok(res == 0, "Getting Out of Range item should fail with 0 (%ld), got %s\n", res,buffer); if (winetest_interactive) { UpdateWindow(hHeaderParentWnd); UpdateWindow(hWndHeader); } TEST_GET_ITEMCOUNT(6); res=setItem(hWndHeader, 99, str_items[5], FALSE); ok(res == 0, "Setting Out of Range item should fail with 0 (%ld)\n", res); res=setItem(hWndHeader, 5, str_items[5], TRUE); ok(res == 1, "Setting Out of Range item should fail with 1 (%ld)\n", res); res=setItem(hWndHeader, -2, str_items[5], FALSE); ok(res == 0, "Setting Out of Range item should fail with 0 (%ld)\n", res); TEST_GET_ITEMCOUNT(6); for (i = 0; i < 4; i++) { res = setItem(hWndHeader, i, str_items[4], TRUE); ok(res != 0, "Setting %d item failed (%ld)\n", i+1, res); TEST_GET_ITEM(i, 4); TEST_GET_ITEMCOUNT(6); } SendMessageA(hWndHeader, HDM_SETUNICODEFORMAT, (WPARAM)TRUE, 0); setItemUnicodeNotify(hWndHeader, 3, pszUniTestA, pszUniTestW); SendMessageA(hWndHeader, WM_NOTIFYFORMAT, (WPARAM)hHeaderParentWnd, (LPARAM)NF_REQUERY); setItem(hWndHeader, 3, str_items[4], TRUE); res = delItem(hWndHeader, 5); ok(res == 1, "Deleting Out of Range item should fail with 1 (%ld)\n", res); res = delItem(hWndHeader, -2); ok(res == 0, "Deleting Out of Range item should fail with 0 (%ld)\n", res); TEST_GET_ITEMCOUNT(5); res = delItem(hWndHeader, 3); ok(res != 0, "Deleting using out of range index failed (%ld)\n", res); TEST_GET_ITEMCOUNT(4); res = delItem(hWndHeader, 0); ok(res != 0, "Deleting using out of range index failed (%ld)\n", res); TEST_GET_ITEMCOUNT(3); res = delItem(hWndHeader, 0); ok(res != 0, "Deleting using out of range index failed (%ld)\n", res); TEST_GET_ITEMCOUNT(2); res = delItem(hWndHeader, 0); ok(res != 0, "Deleting using out of range index failed (%ld)\n", res); TEST_GET_ITEMCOUNT(1); DestroyWindow(hWndHeader); } LRESULT CALLBACK HeaderTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_NOTIFY: { NMHEADERA *hdr = (NMHEADER *)lParam; EXPECTEDNOTIFY *expected; if (nReceivedNotify >= nExpectedNotify || hdr->hdr.hwndFrom != hWndHeader ) break; expected = &expectedNotify[nReceivedNotify]; if (hdr->hdr.code != expected->iCode) break; nReceivedNotify++; compare_items(hdr->hdr.code, &expected->hdItem, hdr->pitem, expected->fUnicode); break; } case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProcA(hWnd, msg, wParam, lParam); } return 0L; } static void init(void) { WNDCLASSA wc; INITCOMMONCONTROLSEX icex; icex.dwSize = sizeof(INITCOMMONCONTROLSEX); icex.dwICC = ICC_USEREX_CLASSES; InitCommonControlsEx(&icex); wc.style = CS_HREDRAW | CS_VREDRAW; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = GetModuleHandleA(NULL); wc.hIcon = NULL; wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW)); wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW); wc.lpszMenuName = NULL; wc.lpszClassName = "HeaderTestClass"; wc.lpfnWndProc = HeaderTestWndProc; RegisterClassA(&wc); hHeaderParentWnd = CreateWindowExA(0, "HeaderTestClass", "Header test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0); assert(hHeaderParentWnd != NULL); } START_TEST(header) { init(); test_header_control(); DestroyWindow(hHeaderParentWnd); }