| /* Unit test suite for tab control. |
| * |
| * Copyright 2003 Vitaliy Margolen |
| * Copyright 2007 Hagop Hagopian |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include <windows.h> |
| #include <commctrl.h> |
| #include <stdio.h> |
| |
| #include "wine/test.h" |
| #include "msg.h" |
| |
| #define DEFAULT_MIN_TAB_WIDTH 54 |
| #define TAB_PADDING_X 6 |
| #define EXTRA_ICON_PADDING 3 |
| #define MAX_TABLEN 32 |
| |
| #define NUM_MSG_SEQUENCES 2 |
| #define PARENT_SEQ_INDEX 0 |
| #define TAB_SEQ_INDEX 1 |
| |
| #define expect(expected, got) ok ( expected == got, "Expected %d, got %d\n", expected, got) |
| #define expect_str(expected, got)\ |
| ok ( strcmp(expected, got) == 0, "Expected '%s', got '%s'\n", expected, got) |
| |
| #define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num) |
| |
| static void CheckSize(HWND hwnd, INT width, INT height, const char *msg, int line) |
| { |
| RECT r; |
| |
| SendMessageA(hwnd, TCM_GETITEMRECT, 0, (LPARAM)&r); |
| if (width >= 0 && height < 0) |
| ok_(__FILE__,line) (width == r.right - r.left, "%s: Expected width [%d] got [%d]\n", |
| msg, width, r.right - r.left); |
| else if (height >= 0 && width < 0) |
| ok_(__FILE__,line) (height == r.bottom - r.top, "%s: Expected height [%d] got [%d]\n", |
| msg, height, r.bottom - r.top); |
| else |
| ok_(__FILE__,line) ((width == r.right - r.left) && (height == r.bottom - r.top ), |
| "%s: Expected [%d,%d] got [%d,%d]\n", msg, width, height, |
| r.right - r.left, r.bottom - r.top); |
| } |
| |
| #define CHECKSIZE(hwnd,width,height,msg) CheckSize(hwnd,width,height,msg,__LINE__) |
| |
| static void TabCheckSetSize(HWND hwnd, INT set_width, INT set_height, INT exp_width, |
| INT exp_height, const char *msg, int line) |
| { |
| SendMessageA(hwnd, TCM_SETITEMSIZE, 0, |
| MAKELPARAM((set_width >= 0) ? set_width : 0, (set_height >= 0) ? set_height : 0)); |
| if (winetest_interactive) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW); |
| CheckSize(hwnd, exp_width, exp_height, msg, line); |
| } |
| |
| #define TABCHECKSETSIZE(hwnd,set_width,set_height,exp_width,exp_height,msg) \ |
| TabCheckSetSize(hwnd,set_width,set_height,exp_width,exp_height,msg,__LINE__) |
| |
| static HFONT hFont; |
| static DRAWITEMSTRUCT g_drawitem; |
| static HWND parent_wnd; |
| |
| static struct msg_sequence *sequences[NUM_MSG_SEQUENCES]; |
| |
| static const struct message add_tab_to_parent[] = { |
| { TCM_INSERTITEMA, sent }, |
| { TCM_INSERTITEMA, sent|optional }, |
| { WM_NOTIFYFORMAT, sent|defwinproc }, |
| { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc|optional, 0, 0 }, |
| { WM_PARENTNOTIFY, sent|defwinproc }, |
| { TCM_INSERTITEMA, sent }, |
| { TCM_INSERTITEMA, sent }, |
| { TCM_INSERTITEMA, sent }, |
| { TCM_INSERTITEMA, sent|optional }, |
| { 0 } |
| }; |
| |
| static const struct message add_tab_to_parent_interactive[] = { |
| { TCM_INSERTITEMA, sent }, |
| { TCM_INSERTITEMA, sent }, |
| { WM_NOTIFYFORMAT, sent|defwinproc }, |
| { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc, 0, 0 }, |
| { WM_PARENTNOTIFY, sent|defwinproc }, |
| { TCM_INSERTITEMA, sent }, |
| { TCM_INSERTITEMA, sent }, |
| { TCM_INSERTITEMA, sent }, |
| { WM_SHOWWINDOW, sent}, |
| { WM_WINDOWPOSCHANGING, sent}, |
| { WM_WINDOWPOSCHANGING, sent}, |
| { WM_NCACTIVATE, sent}, |
| { WM_ACTIVATE, sent}, |
| { WM_IME_SETCONTEXT, sent|defwinproc|optional}, |
| { WM_IME_NOTIFY, sent|defwinproc|optional}, |
| { WM_SETFOCUS, sent|defwinproc}, |
| { WM_WINDOWPOSCHANGED, sent}, |
| { WM_SIZE, sent}, |
| { WM_MOVE, sent}, |
| { 0 } |
| }; |
| |
| static const struct message add_tab_control_parent_seq[] = { |
| { WM_NOTIFYFORMAT, sent }, |
| { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message add_tab_control_parent_seq_interactive[] = { |
| { WM_NOTIFYFORMAT, sent }, |
| { WM_QUERYUISTATE, sent|wparam|lparam, 0, 0 }, |
| { WM_WINDOWPOSCHANGING, sent|optional}, |
| { WM_NCACTIVATE, sent}, |
| { WM_ACTIVATE, sent}, |
| { WM_WINDOWPOSCHANGING, sent|optional}, |
| { WM_KILLFOCUS, sent}, |
| { WM_IME_SETCONTEXT, sent|optional}, |
| { WM_IME_NOTIFY, sent|optional}, |
| { 0 } |
| }; |
| |
| static const struct message empty_sequence[] = { |
| { 0 } |
| }; |
| |
| static const struct message get_item_count_seq[] = { |
| { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message get_row_count_seq[] = { |
| { TCM_GETROWCOUNT, sent|wparam|lparam, 0, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message get_item_rect_seq[] = { |
| { TCM_GETITEMRECT, sent }, |
| { TCM_GETITEMRECT, sent }, |
| { 0 } |
| }; |
| |
| static const struct message getset_cur_focus_seq[] = { |
| { TCM_SETCURFOCUS, sent|lparam, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_SETCURFOCUS, sent|lparam, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_SETCURSEL, sent|lparam, 0 }, |
| { TCM_SETCURFOCUS, sent|lparam, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message getset_cur_sel_seq[] = { |
| { TCM_SETCURSEL, sent|lparam, 0 }, |
| { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_SETCURSEL, sent|lparam, 0 }, |
| { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 }, |
| { TCM_SETCURSEL, sent|lparam, 0 }, |
| { TCM_SETCURSEL, sent|lparam, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message getset_extended_style_seq[] = { |
| { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 }, |
| { TCM_SETEXTENDEDSTYLE, sent }, |
| { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 }, |
| { TCM_SETEXTENDEDSTYLE, sent }, |
| { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message getset_unicode_format_seq[] = { |
| { CCM_SETUNICODEFORMAT, sent|lparam, 0 }, |
| { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 }, |
| { CCM_SETUNICODEFORMAT, sent|lparam, 0 }, |
| { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 }, |
| { CCM_SETUNICODEFORMAT, sent|lparam, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message getset_item_seq[] = { |
| { TCM_SETITEMA, sent }, |
| { TCM_GETITEMA, sent }, |
| { TCM_GETITEMA, sent }, |
| { 0 } |
| }; |
| |
| static const struct message getset_tooltip_seq[] = { |
| { WM_NOTIFYFORMAT, sent|optional }, |
| { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 }, |
| { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, |
| { WM_NOTIFYFORMAT, sent|optional }, |
| { TCM_SETTOOLTIPS, sent|lparam, 0 }, |
| { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 }, |
| { TCM_SETTOOLTIPS, sent|lparam, 0 }, |
| { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message getset_tooltip_parent_seq[] = { |
| { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message insert_focus_seq[] = { |
| { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_INSERTITEMA, sent|wparam, 1 }, |
| { WM_NOTIFYFORMAT, sent|defwinproc|optional }, |
| { WM_QUERYUISTATE, sent|defwinproc|optional }, |
| { WM_PARENTNOTIFY, sent|defwinproc|optional }, |
| { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_INSERTITEMA, sent|wparam, 2 }, |
| { WM_NOTIFYFORMAT, sent|defwinproc|optional }, |
| { WM_QUERYUISTATE, sent|defwinproc|optional, }, |
| { WM_PARENTNOTIFY, sent|defwinproc|optional }, |
| { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_INSERTITEMA, sent|wparam, 3 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message delete_focus_seq[] = { |
| { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_DELETEITEM, sent|wparam|lparam, 1, 0 }, |
| { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { TCM_DELETEITEM, sent|wparam|lparam, 0, 0 }, |
| { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 }, |
| { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 }, |
| { 0 } |
| }; |
| |
| static const struct message rbuttonup_seq[] = { |
| { WM_RBUTTONUP, sent|wparam|lparam, 0, 0 }, |
| { WM_CONTEXTMENU, sent|defwinproc }, |
| { 0 } |
| }; |
| |
| static HWND |
| create_tabcontrol (DWORD style, DWORD mask) |
| { |
| HWND handle; |
| TCITEMA tcNewTab; |
| static char text1[] = "Tab 1", |
| text2[] = "Wide Tab 2", |
| text3[] = "T 3"; |
| |
| handle = CreateWindowA(WC_TABCONTROLA, "TestTab", |
| WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style, 10, 10, 300, 100, NULL, |
| NULL, NULL, 0); |
| ok(handle != NULL, "failed to create tab wnd\n"); |
| |
| SetWindowLongA(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style); |
| SendMessageA(handle, WM_SETFONT, 0, (LPARAM)hFont); |
| |
| tcNewTab.mask = mask; |
| tcNewTab.pszText = text1; |
| tcNewTab.iImage = 0; |
| SendMessageA(handle, TCM_INSERTITEMA, 0, (LPARAM)&tcNewTab); |
| tcNewTab.pszText = text2; |
| tcNewTab.iImage = 1; |
| SendMessageA(handle, TCM_INSERTITEMA, 1, (LPARAM)&tcNewTab); |
| tcNewTab.pszText = text3; |
| tcNewTab.iImage = 2; |
| SendMessageA(handle, TCM_INSERTITEMA, 2, (LPARAM)&tcNewTab); |
| |
| if (winetest_interactive) |
| { |
| ShowWindow (handle, SW_SHOW); |
| RedrawWindow (handle, NULL, 0, RDW_UPDATENOW); |
| Sleep (1000); |
| } |
| |
| return handle; |
| } |
| |
| static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) |
| { |
| static LONG defwndproc_counter = 0; |
| struct message msg = { 0 }; |
| LRESULT ret; |
| |
| /* do not log painting messages */ |
| if (message != WM_PAINT && |
| message != WM_ERASEBKGND && |
| message != WM_NCPAINT && |
| message != WM_NCHITTEST && |
| message != WM_GETTEXT && |
| message != WM_GETICON && |
| message != WM_DEVICECHANGE) |
| { |
| msg.message = message; |
| msg.flags = sent|wparam|lparam; |
| if (defwndproc_counter) msg.flags |= defwinproc; |
| msg.wParam = wParam; |
| msg.lParam = lParam; |
| add_message(sequences, PARENT_SEQ_INDEX, &msg); |
| } |
| |
| /* dump sent structure data */ |
| if (message == WM_DRAWITEM) |
| g_drawitem = *(DRAWITEMSTRUCT*)lParam; |
| |
| defwndproc_counter++; |
| ret = DefWindowProcA(hwnd, message, wParam, lParam); |
| defwndproc_counter--; |
| |
| return ret; |
| } |
| |
| static BOOL registerParentWindowClass(void) |
| { |
| WNDCLASSA cls; |
| |
| cls.style = 0; |
| cls.lpfnWndProc = parentWindowProcess; |
| cls.cbClsExtra = 0; |
| cls.cbWndExtra = 0; |
| cls.hInstance = GetModuleHandleA(NULL); |
| cls.hIcon = 0; |
| cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); |
| cls.hbrBackground = GetStockObject(WHITE_BRUSH); |
| cls.lpszMenuName = NULL; |
| cls.lpszClassName = "Tab test parent class"; |
| return RegisterClassA(&cls); |
| } |
| |
| static HWND createParentWindow(void) |
| { |
| if (!registerParentWindowClass()) |
| return NULL; |
| |
| return CreateWindowExA(0, "Tab test parent class", "Tab test parent window", |
| WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 0, 0, 100, 100, |
| GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL); |
| } |
| |
| static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) |
| { |
| WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA); |
| static LONG defwndproc_counter = 0; |
| struct message msg = { 0 }; |
| LRESULT ret; |
| |
| /* do not log painting messages */ |
| if (message != WM_PAINT && |
| message != WM_ERASEBKGND && |
| message != WM_NCPAINT && |
| message != WM_NCHITTEST && |
| message != WM_GETTEXT && |
| message != WM_GETICON && |
| message != WM_DEVICECHANGE) |
| { |
| msg.message = message; |
| msg.flags = sent|wparam|lparam; |
| if (defwndproc_counter) msg.flags |= defwinproc; |
| msg.wParam = wParam; |
| msg.lParam = lParam; |
| add_message(sequences, TAB_SEQ_INDEX, &msg); |
| } |
| |
| defwndproc_counter++; |
| ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam); |
| defwndproc_counter--; |
| |
| return ret; |
| } |
| |
| static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT nTabs) |
| { |
| HWND tabHandle; |
| TCITEMA tcNewTab; |
| WNDPROC oldproc; |
| RECT rect; |
| INT i; |
| |
| GetClientRect(parent_wnd, &rect); |
| |
| tabHandle = CreateWindowA(WC_TABCONTROLA, "TestTab", |
| WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style, 0, 0, rect.right, |
| rect.bottom, parent_wnd, NULL, NULL, 0); |
| ok(tabHandle != NULL, "failed to create tab wnd\n"); |
| |
| oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tabSubclassProcess); |
| SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)oldproc); |
| |
| tcNewTab.mask = mask; |
| |
| for (i = 0; i < nTabs; i++) |
| { |
| char tabName[MAX_TABLEN]; |
| |
| sprintf(tabName, "Tab %d", i+1); |
| tcNewTab.pszText = tabName; |
| tcNewTab.iImage = i; |
| SendMessageA(tabHandle, TCM_INSERTITEMA, i, (LPARAM)&tcNewTab); |
| } |
| |
| if (winetest_interactive) |
| { |
| ShowWindow (tabHandle, SW_SHOW); |
| RedrawWindow (tabHandle, NULL, 0, RDW_UPDATENOW); |
| Sleep (1000); |
| } |
| |
| return tabHandle; |
| } |
| |
| static HWND create_tooltip (HWND hTab, char toolTipText[]) |
| { |
| HWND hwndTT; |
| |
| TTTOOLINFOA ti; |
| LPSTR lptstr = toolTipText; |
| RECT rect; |
| |
| /* Creating a tooltip window*/ |
| hwndTT = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, NULL, |
| WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, |
| CW_USEDEFAULT, hTab, NULL, 0, NULL); |
| |
| SetWindowPos( |
| hwndTT, |
| HWND_TOPMOST, |
| 0, 0, 0, 0, |
| SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); |
| |
| GetClientRect (hTab, &rect); |
| |
| /* Initialize members of toolinfo*/ |
| ti.cbSize = sizeof(TTTOOLINFOA); |
| ti.uFlags = TTF_SUBCLASS; |
| ti.hwnd = hTab; |
| ti.hinst = 0; |
| ti.uId = 0; |
| ti.lpszText = lptstr; |
| |
| ti.rect = rect; |
| |
| /* Add toolinfo structure to the tooltip control */ |
| SendMessageA(hwndTT, TTM_ADDTOOLA, 0, (LPARAM)&ti); |
| |
| return hwndTT; |
| } |
| |
| static void test_tab(INT nMinTabWidth) |
| { |
| HWND hwTab; |
| RECT rTab; |
| HIMAGELIST himl = ImageList_Create(21, 21, ILC_COLOR, 3, 4); |
| SIZE size; |
| HDC hdc; |
| HFONT hOldFont; |
| INT i, dpi, exp; |
| |
| hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE); |
| SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); |
| /* Get System default MinTabWidth */ |
| if (nMinTabWidth < 0) |
| nMinTabWidth = SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); |
| |
| hdc = GetDC(hwTab); |
| dpi = GetDeviceCaps(hdc, LOGPIXELSX); |
| hOldFont = SelectObject(hdc, (HFONT)SendMessageA(hwTab, WM_GETFONT, 0, 0)); |
| GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size); |
| trace("Tab1 text size: size.cx=%d size.cy=%d\n", size.cx, size.cy); |
| SelectObject(hdc, hOldFont); |
| ReleaseDC(hwTab, hdc); |
| |
| trace (" TCS_FIXEDWIDTH tabs no icon...\n"); |
| CHECKSIZE(hwTab, dpi, -1, "default width"); |
| TABCHECKSETSIZE(hwTab, 50, 20, 50, 20, "set size"); |
| TABCHECKSETSIZE(hwTab, 0, 1, 0, 1, "min size"); |
| |
| SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); |
| |
| trace (" TCS_FIXEDWIDTH tabs with icon...\n"); |
| TABCHECKSETSIZE(hwTab, 50, 30, 50, 30, "set size > icon"); |
| TABCHECKSETSIZE(hwTab, 20, 20, 25, 20, "set size < icon"); |
| TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "min size"); |
| |
| DestroyWindow (hwTab); |
| |
| hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE); |
| SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); |
| |
| hdc = GetDC(hwTab); |
| dpi = GetDeviceCaps(hdc, LOGPIXELSX); |
| ReleaseDC(hwTab, hdc); |
| trace (" TCS_FIXEDWIDTH buttons no icon...\n"); |
| CHECKSIZE(hwTab, dpi, -1, "default width"); |
| TABCHECKSETSIZE(hwTab, 20, 20, 20, 20, "set size 1"); |
| TABCHECKSETSIZE(hwTab, 10, 50, 10, 50, "set size 2"); |
| TABCHECKSETSIZE(hwTab, 0, 1, 0, 1, "min size"); |
| |
| SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); |
| |
| trace (" TCS_FIXEDWIDTH buttons with icon...\n"); |
| TABCHECKSETSIZE(hwTab, 50, 30, 50, 30, "set size > icon"); |
| TABCHECKSETSIZE(hwTab, 20, 20, 25, 20, "set size < icon"); |
| TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "min size"); |
| SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4, 4)); |
| TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "set padding, min size"); |
| |
| DestroyWindow (hwTab); |
| |
| hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM, TCIF_TEXT|TCIF_IMAGE); |
| SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); |
| |
| hdc = GetDC(hwTab); |
| dpi = GetDeviceCaps(hdc, LOGPIXELSX); |
| ReleaseDC(hwTab, hdc); |
| trace (" TCS_FIXEDWIDTH | TCS_BOTTOM tabs...\n"); |
| CHECKSIZE(hwTab, dpi, -1, "no icon, default width"); |
| |
| TABCHECKSETSIZE(hwTab, 20, 20, 20, 20, "no icon, set size 1"); |
| TABCHECKSETSIZE(hwTab, 10, 50, 10, 50, "no icon, set size 2"); |
| TABCHECKSETSIZE(hwTab, 0, 1, 0, 1, "no icon, min size"); |
| |
| SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); |
| |
| TABCHECKSETSIZE(hwTab, 50, 30, 50, 30, "with icon, set size > icon"); |
| TABCHECKSETSIZE(hwTab, 20, 20, 25, 20, "with icon, set size < icon"); |
| TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "with icon, min size"); |
| SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4, 4)); |
| TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "set padding, min size"); |
| |
| DestroyWindow (hwTab); |
| |
| hwTab = create_tabcontrol(0, TCIF_TEXT|TCIF_IMAGE); |
| SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); |
| |
| trace (" non fixed width, with text...\n"); |
| exp = max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth); |
| SendMessageA( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab ); |
| ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == DEFAULT_MIN_TAB_WIDTH), |
| "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left ); |
| |
| for (i=0; i<8; i++) |
| { |
| INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth; |
| |
| SendMessageA(hwTab, TCM_SETIMAGELIST, 0, 0); |
| SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i, i)); |
| |
| TABCHECKSETSIZE(hwTab, 50, 20, max(size.cx + i*2, nTabWidth), 20, "no icon, set size"); |
| TABCHECKSETSIZE(hwTab, 0, 1, max(size.cx + i*2, nTabWidth), 1, "no icon, min size"); |
| |
| SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); |
| nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth; |
| |
| TABCHECKSETSIZE(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon"); |
| TABCHECKSETSIZE(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon"); |
| TABCHECKSETSIZE(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size"); |
| } |
| DestroyWindow (hwTab); |
| |
| hwTab = create_tabcontrol(0, TCIF_IMAGE); |
| SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth); |
| |
| trace (" non fixed width, no text...\n"); |
| exp = (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth; |
| SendMessageA( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab ); |
| ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == DEFAULT_MIN_TAB_WIDTH), |
| "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left ); |
| |
| for (i=0; i<8; i++) |
| { |
| INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth; |
| |
| SendMessageA(hwTab, TCM_SETIMAGELIST, 0, 0); |
| SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i, i)); |
| |
| TABCHECKSETSIZE(hwTab, 50, 20, nTabWidth, 20, "no icon, set size"); |
| TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "no icon, min size"); |
| |
| SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); |
| if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < DEFAULT_MIN_TAB_WIDTH) |
| nTabWidth += EXTRA_ICON_PADDING *(i-1); |
| |
| TABCHECKSETSIZE(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon"); |
| TABCHECKSETSIZE(hwTab, 20, 20, nTabWidth, 20, "with icon, set size < icon"); |
| TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "with icon, min size"); |
| } |
| |
| DestroyWindow (hwTab); |
| |
| ImageList_Destroy(himl); |
| } |
| |
| static void test_width(void) |
| { |
| trace ("Testing with default MinWidth\n"); |
| test_tab(-1); |
| trace ("Testing with MinWidth set to -3\n"); |
| test_tab(-3); |
| trace ("Testing with MinWidth set to 24\n"); |
| test_tab(24); |
| trace ("Testing with MinWidth set to 54\n"); |
| test_tab(54); |
| trace ("Testing with MinWidth set to 94\n"); |
| test_tab(94); |
| } |
| |
| static void test_curfocus(void) |
| { |
| const INT nTabs = 5; |
| INT focusIndex; |
| HWND hTab; |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| /* Testing CurFocus with largest appropriate value */ |
| SendMessageA(hTab, TCM_SETCURFOCUS, nTabs - 1, 0); |
| focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(nTabs-1, focusIndex); |
| |
| /* Testing CurFocus with negative value */ |
| SendMessageA(hTab, TCM_SETCURFOCUS, -10, 0); |
| focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(-1, focusIndex); |
| |
| /* Testing CurFocus with value larger than number of tabs */ |
| focusIndex = SendMessageA(hTab, TCM_SETCURSEL, 1, 0); |
| expect(-1, focusIndex); |
| |
| SendMessageA(hTab, TCM_SETCURFOCUS, nTabs + 1, 0); |
| focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(1, focusIndex); |
| |
| ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_seq, "Getset curFoc test sequence", FALSE); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_cursel(void) |
| { |
| const INT nTabs = 5; |
| INT selectionIndex; |
| INT focusIndex; |
| TCITEMA tcItem; |
| HWND hTab; |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| /* Testing CurSel with largest appropriate value */ |
| selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, nTabs - 1, 0); |
| expect(0, selectionIndex); |
| selectionIndex = SendMessageA(hTab, TCM_GETCURSEL, 0, 0); |
| expect(nTabs-1, selectionIndex); |
| |
| /* Focus should switch with selection */ |
| focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(nTabs-1, focusIndex); |
| |
| /* Testing CurSel with negative value */ |
| SendMessageA(hTab, TCM_SETCURSEL, -10, 0); |
| selectionIndex = SendMessageA(hTab, TCM_GETCURSEL, 0, 0); |
| expect(-1, selectionIndex); |
| |
| /* Testing CurSel with value larger than number of tabs */ |
| selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, 1, 0); |
| expect(-1, selectionIndex); |
| |
| selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, nTabs + 1, 0); |
| expect(-1, selectionIndex); |
| selectionIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(1, selectionIndex); |
| |
| ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_sel_seq, "Getset curSel test sequence", FALSE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset curSel test parent sequence", FALSE); |
| |
| /* selected item should have TCIS_BUTTONPRESSED state |
| It doesn't depend on button state */ |
| memset(&tcItem, 0, sizeof(TCITEMA)); |
| tcItem.mask = TCIF_STATE; |
| tcItem.dwStateMask = TCIS_BUTTONPRESSED; |
| selectionIndex = SendMessageA(hTab, TCM_GETCURSEL, 0, 0); |
| SendMessageA(hTab, TCM_GETITEMA, selectionIndex, (LPARAM)&tcItem); |
| ok (tcItem.dwState & TCIS_BUTTONPRESSED || broken(tcItem.dwState == 0), /* older comctl32 */ |
| "Selected item should have TCIS_BUTTONPRESSED\n"); |
| |
| /* now deselect all and check previously selected item state */ |
| focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| ok(focusIndex == 1, "got %d\n", focusIndex); |
| |
| selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, -1, 0); |
| ok(selectionIndex == 1, "got %d\n", selectionIndex); |
| |
| memset(&tcItem, 0, sizeof(TCITEMA)); |
| |
| /* focus is reset too */ |
| focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| ok(focusIndex == -1, "got %d\n", focusIndex); |
| |
| tcItem.mask = TCIF_STATE; |
| tcItem.dwStateMask = TCIS_BUTTONPRESSED; |
| SendMessageA(hTab, TCM_GETITEMA, selectionIndex, (LPARAM)&tcItem); |
| ok(tcItem.dwState == 0, "got state %d\n", tcItem.dwState); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_extendedstyle(void) |
| { |
| const INT nTabs = 5; |
| DWORD prevExtendedStyle; |
| DWORD extendedStyle; |
| HWND hTab; |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| /* Testing Flat Separators */ |
| extendedStyle = SendMessageA(hTab, TCM_GETEXTENDEDSTYLE, 0, 0); |
| prevExtendedStyle = SendMessageA(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_FLATSEPARATORS); |
| expect(extendedStyle, prevExtendedStyle); |
| |
| extendedStyle = SendMessageA(hTab, TCM_GETEXTENDEDSTYLE, 0, 0); |
| expect(TCS_EX_FLATSEPARATORS, extendedStyle); |
| |
| /* Testing Register Drop */ |
| prevExtendedStyle = SendMessageA(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_REGISTERDROP); |
| expect(extendedStyle, prevExtendedStyle); |
| |
| extendedStyle = SendMessageA(hTab, TCM_GETEXTENDEDSTYLE, 0, 0); |
| todo_wine{ |
| expect(TCS_EX_REGISTERDROP, extendedStyle); |
| } |
| |
| ok_sequence(sequences, TAB_SEQ_INDEX, getset_extended_style_seq, "Getset extendedStyle test sequence", FALSE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset extendedStyle test parent sequence", FALSE); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_unicodeformat(void) |
| { |
| const INT nTabs = 5; |
| INT unicodeFormat; |
| HWND hTab; |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| unicodeFormat = SendMessageA(hTab, TCM_SETUNICODEFORMAT, TRUE, 0); |
| todo_wine{ |
| expect(0, unicodeFormat); |
| } |
| unicodeFormat = SendMessageA(hTab, TCM_GETUNICODEFORMAT, 0, 0); |
| expect(1, unicodeFormat); |
| |
| unicodeFormat = SendMessageA(hTab, TCM_SETUNICODEFORMAT, FALSE, 0); |
| expect(1, unicodeFormat); |
| unicodeFormat = SendMessageA(hTab, TCM_GETUNICODEFORMAT, 0, 0); |
| expect(0, unicodeFormat); |
| |
| unicodeFormat = SendMessageA(hTab, TCM_SETUNICODEFORMAT, TRUE, 0); |
| expect(0, unicodeFormat); |
| |
| ok_sequence(sequences, TAB_SEQ_INDEX, getset_unicode_format_seq, "Getset unicodeFormat test sequence", FALSE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset unicodeFormat test parent sequence", FALSE); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_getset_item(void) |
| { |
| char szText[32] = "New Label"; |
| const INT nTabs = 5; |
| TCITEMA tcItem; |
| LPARAM lparam; |
| DWORD ret; |
| HWND hTab; |
| |
| hTab = CreateWindowA( |
| WC_TABCONTROLA, |
| "TestTab", |
| WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED, |
| 10, 10, 300, 100, |
| parent_wnd, NULL, NULL, 0); |
| |
| ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab)); |
| |
| ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0); |
| ok(ret == TRUE, "got %d\n", ret); |
| |
| /* set some item data */ |
| tcItem.lParam = ~0; |
| tcItem.mask = TCIF_PARAM; |
| |
| ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&tcItem); |
| ok(ret == 0, "got %d\n", ret); |
| |
| /* all sizeof(LPARAM) returned anyway when using sizeof(LPARAM)-1 size */ |
| memset(&lparam, 0xaa, sizeof(lparam)); |
| tcItem.lParam = lparam; |
| tcItem.mask = TCIF_PARAM; |
| ret = SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem); |
| expect(TRUE, ret); |
| /* everything higher specified size is preserved */ |
| memset(&lparam, 0xff, sizeof(lparam)-1); |
| ok(tcItem.lParam == lparam, "Expected 0x%lx, got 0x%lx\n", lparam, tcItem.lParam); |
| |
| DestroyWindow(hTab); |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| /* passing invalid index should result in initialization to zero |
| for members mentioned in mask requested */ |
| |
| /* valid range here is [0,4] */ |
| memset(&tcItem, 0xcc, sizeof(tcItem)); |
| tcItem.mask = TCIF_PARAM; |
| ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem); |
| expect(FALSE, ret); |
| ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam); |
| |
| memset(&tcItem, 0xcc, sizeof(tcItem)); |
| tcItem.mask = TCIF_IMAGE; |
| ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem); |
| expect(FALSE, ret); |
| expect(0, tcItem.iImage); |
| |
| memset(&tcItem, 0xcc, sizeof(tcItem)); |
| tcItem.mask = TCIF_TEXT; |
| tcItem.pszText = szText; |
| szText[0] = 'a'; |
| ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem); |
| expect(FALSE, ret); |
| expect('a', szText[0]); |
| |
| memset(&tcItem, 0xcc, sizeof(tcItem)); |
| tcItem.mask = TCIF_STATE; |
| tcItem.dwStateMask = 0; |
| tcItem.dwState = TCIS_BUTTONPRESSED; |
| ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem); |
| expect(FALSE, ret); |
| ok(tcItem.dwState == 0, "Expected zero dwState, got %u\n", tcItem.dwState); |
| |
| memset(&tcItem, 0xcc, sizeof(tcItem)); |
| tcItem.mask = TCIF_STATE; |
| tcItem.dwStateMask = TCIS_BUTTONPRESSED; |
| tcItem.dwState = TCIS_BUTTONPRESSED; |
| ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem); |
| expect(FALSE, ret); |
| ok(tcItem.dwState == 0, "Expected zero dwState\n"); |
| |
| /* check with negative index to be sure */ |
| memset(&tcItem, 0xcc, sizeof(tcItem)); |
| tcItem.mask = TCIF_PARAM; |
| ret = SendMessageA(hTab, TCM_GETITEMA, -1, (LPARAM)&tcItem); |
| expect(FALSE, ret); |
| ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam); |
| |
| memset(&tcItem, 0xcc, sizeof(tcItem)); |
| tcItem.mask = TCIF_PARAM; |
| ret = SendMessageA(hTab, TCM_GETITEMA, -2, (LPARAM)&tcItem); |
| expect(FALSE, ret); |
| ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| tcItem.mask = TCIF_TEXT; |
| tcItem.pszText = &szText[0]; |
| tcItem.cchTextMax = sizeof(szText); |
| |
| strcpy(szText, "New Label"); |
| ok(SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&tcItem), "Setting new item failed.\n"); |
| ok(SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem), "Getting item failed.\n"); |
| expect_str("New Label", tcItem.pszText); |
| |
| ok(SendMessageA(hTab, TCM_GETITEMA, 1, (LPARAM)&tcItem), "Getting item failed.\n"); |
| expect_str("Tab 2", tcItem.pszText); |
| |
| ok_sequence(sequences, TAB_SEQ_INDEX, getset_item_seq, "Getset item test sequence", FALSE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset item test parent sequence", FALSE); |
| |
| /* TCIS_BUTTONPRESSED doesn't depend on tab style */ |
| memset(&tcItem, 0, sizeof(tcItem)); |
| tcItem.mask = TCIF_STATE; |
| tcItem.dwStateMask = TCIS_BUTTONPRESSED; |
| tcItem.dwState = TCIS_BUTTONPRESSED; |
| ok(SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&tcItem), "Setting new item failed.\n"); |
| tcItem.dwState = 0; |
| ok(SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem), "Getting item failed.\n"); |
| if (tcItem.dwState) |
| { |
| ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n"); |
| /* next highlight item, test that dwStateMask actually masks */ |
| tcItem.mask = TCIF_STATE; |
| tcItem.dwStateMask = TCIS_HIGHLIGHTED; |
| tcItem.dwState = TCIS_HIGHLIGHTED; |
| ok(SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&tcItem), "Setting new item failed.\n"); |
| tcItem.dwState = 0; |
| ok(SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem), "Getting item failed.\n"); |
| ok (tcItem.dwState == TCIS_HIGHLIGHTED, "TCIS_HIGHLIGHTED should be set.\n"); |
| tcItem.mask = TCIF_STATE; |
| tcItem.dwStateMask = TCIS_BUTTONPRESSED; |
| tcItem.dwState = 0; |
| ok(SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem), "Getting item failed.\n"); |
| ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n"); |
| } |
| else win_skip( "Item state mask not supported\n" ); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_getset_tooltips(void) |
| { |
| char toolTipText[32] = "ToolTip Text Test"; |
| const INT nTabs = 5; |
| HWND hTab, toolTip; |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| toolTip = create_tooltip(hTab, toolTipText); |
| SendMessageA(hTab, TCM_SETTOOLTIPS, (LPARAM)toolTip, 0); |
| ok(toolTip == (HWND)SendMessageA(hTab, TCM_GETTOOLTIPS, 0,0), "ToolTip was set incorrectly.\n"); |
| |
| SendMessageA(hTab, TCM_SETTOOLTIPS, 0, 0); |
| ok(!SendMessageA(hTab, TCM_GETTOOLTIPS, 0,0), "ToolTip was set incorrectly.\n"); |
| |
| ok_sequence(sequences, TAB_SEQ_INDEX, getset_tooltip_seq, "Getset tooltip test sequence", TRUE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, getset_tooltip_parent_seq, "Getset tooltip test parent sequence", TRUE); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_misc(void) |
| { |
| const INT nTabs = 5; |
| HWND hTab; |
| RECT rTab; |
| INT nTabsRetrieved; |
| INT rowCount; |
| INT dpi; |
| HDC hdc; |
| |
| ok(parent_wnd != NULL, "no parent window!\n"); |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| if(!winetest_interactive) |
| ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent, |
| "Tab sequence, after adding tab control to parent", TRUE); |
| else |
| ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent_interactive, |
| "Tab sequence, after adding tab control to parent", TRUE); |
| |
| if(!winetest_interactive) |
| ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq, |
| "Parent after sequence, adding tab control to parent", TRUE); |
| else |
| ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq_interactive, |
| "Parent after sequence, adding tab control to parent", TRUE); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| ok(SendMessageA(hTab, TCM_SETMINTABWIDTH, 0, -1) > 0, "TCM_SETMINTABWIDTH returned < 0\n"); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Set minTabWidth test parent sequence", FALSE); |
| |
| /* Testing GetItemCount */ |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0); |
| expect(nTabs, nTabsRetrieved); |
| ok_sequence(sequences, TAB_SEQ_INDEX, get_item_count_seq, "Get itemCount test sequence", FALSE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset itemCount test parent sequence", FALSE); |
| |
| /* Testing GetRowCount */ |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| rowCount = SendMessageA(hTab, TCM_GETROWCOUNT, 0, 0); |
| expect(1, rowCount); |
| ok_sequence(sequences, TAB_SEQ_INDEX, get_row_count_seq, "Get rowCount test sequence", FALSE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get rowCount test parent sequence", FALSE); |
| |
| /* Testing GetItemRect */ |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| ok(SendMessageA(hTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab), "GetItemRect failed.\n"); |
| |
| hdc = GetDC(hTab); |
| dpi = GetDeviceCaps(hdc, LOGPIXELSX); |
| ReleaseDC(hTab, hdc); |
| CHECKSIZE(hTab, dpi, -1 , "Default Width"); |
| ok_sequence(sequences, TAB_SEQ_INDEX, get_item_rect_seq, "Get itemRect test sequence", FALSE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get itemRect test parent sequence", FALSE); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_adjustrect(void) |
| { |
| HWND hTab; |
| INT r; |
| |
| ok(parent_wnd != NULL, "no parent window!\n"); |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, 0, 0); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| r = SendMessageA(hTab, TCM_ADJUSTRECT, FALSE, 0); |
| expect(-1, r); |
| |
| r = SendMessageA(hTab, TCM_ADJUSTRECT, TRUE, 0); |
| expect(-1, r); |
| } |
| |
| static void test_insert_focus(void) |
| { |
| HWND hTab; |
| INT nTabsRetrieved; |
| INT r; |
| TCITEMA tcNewTab; |
| DWORD mask = TCIF_TEXT|TCIF_IMAGE; |
| static char tabName[] = "TAB"; |
| tcNewTab.mask = mask; |
| tcNewTab.pszText = tabName; |
| |
| ok(parent_wnd != NULL, "no parent window!\n"); |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, mask, 0); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| r = SendMessageA(hTab, TCM_GETCURSEL, 0, 0); |
| expect(-1, r); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0); |
| expect(0, nTabsRetrieved); |
| |
| r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(-1, r); |
| |
| tcNewTab.iImage = 1; |
| r = SendMessageA(hTab, TCM_INSERTITEMA, 1, (LPARAM)&tcNewTab); |
| expect(0, r); |
| |
| nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0); |
| expect(1, nTabsRetrieved); |
| |
| r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(0, r); |
| |
| tcNewTab.iImage = 2; |
| r = SendMessageA(hTab, TCM_INSERTITEMA, 2, (LPARAM)&tcNewTab); |
| expect(1, r); |
| |
| nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0); |
| expect(2, nTabsRetrieved); |
| |
| r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(0, r); |
| |
| r = SendMessageA(hTab, TCM_SETCURFOCUS, -1, 0); |
| expect(0, r); |
| |
| r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(-1, r); |
| |
| tcNewTab.iImage = 3; |
| r = SendMessageA(hTab, TCM_INSERTITEMA, 3, (LPARAM)&tcNewTab); |
| expect(2, r); |
| |
| r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(2, r); |
| |
| ok_sequence(sequences, TAB_SEQ_INDEX, insert_focus_seq, "insert_focus test sequence", FALSE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "insert_focus parent test sequence", TRUE); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_delete_focus(void) |
| { |
| HWND hTab; |
| INT nTabsRetrieved; |
| INT r; |
| |
| ok(parent_wnd != NULL, "no parent window!\n"); |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 2); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0); |
| expect(2, nTabsRetrieved); |
| |
| r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(0, r); |
| |
| r = SendMessageA(hTab, TCM_DELETEITEM, 1, 0); |
| expect(1, r); |
| |
| nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0); |
| expect(1, nTabsRetrieved); |
| |
| r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(0, r); |
| |
| r = SendMessageA(hTab, TCM_SETCURFOCUS, -1, 0); |
| expect(0, r); |
| |
| r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(-1, r); |
| |
| r = SendMessageA(hTab, TCM_DELETEITEM, 0, 0); |
| expect(1, r); |
| |
| nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0); |
| expect(0, nTabsRetrieved); |
| |
| r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0); |
| expect(-1, r); |
| |
| ok_sequence(sequences, TAB_SEQ_INDEX, delete_focus_seq, "delete_focus test sequence", FALSE); |
| ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "delete_focus parent test sequence", TRUE); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_removeimage(void) |
| { |
| static const BYTE bits[32]; |
| HWND hwTab; |
| INT i; |
| TCITEMA item; |
| HICON hicon; |
| HIMAGELIST himl = ImageList_Create(16, 16, ILC_COLOR, 3, 4); |
| |
| hicon = CreateIcon(NULL, 16, 16, 1, 1, bits, bits); |
| ImageList_AddIcon(himl, hicon); |
| ImageList_AddIcon(himl, hicon); |
| ImageList_AddIcon(himl, hicon); |
| |
| hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE); |
| SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); |
| |
| memset(&item, 0, sizeof(TCITEMA)); |
| item.mask = TCIF_IMAGE; |
| |
| for(i = 0; i < 3; i++) { |
| SendMessageA(hwTab, TCM_GETITEMA, i, (LPARAM)&item); |
| expect(i, item.iImage); |
| } |
| |
| /* remove image middle image */ |
| SendMessageA(hwTab, TCM_REMOVEIMAGE, 1, 0); |
| expect(2, ImageList_GetImageCount(himl)); |
| item.iImage = -1; |
| SendMessageA(hwTab, TCM_GETITEMA, 0, (LPARAM)&item); |
| expect(0, item.iImage); |
| item.iImage = 0; |
| SendMessageA(hwTab, TCM_GETITEMA, 1, (LPARAM)&item); |
| expect(-1, item.iImage); |
| item.iImage = 0; |
| SendMessageA(hwTab, TCM_GETITEMA, 2, (LPARAM)&item); |
| expect(1, item.iImage); |
| /* remove first image */ |
| SendMessageA(hwTab, TCM_REMOVEIMAGE, 0, 0); |
| expect(1, ImageList_GetImageCount(himl)); |
| item.iImage = 0; |
| SendMessageA(hwTab, TCM_GETITEMA, 0, (LPARAM)&item); |
| expect(-1, item.iImage); |
| item.iImage = 0; |
| SendMessageA(hwTab, TCM_GETITEMA, 1, (LPARAM)&item); |
| expect(-1, item.iImage); |
| item.iImage = -1; |
| SendMessageA(hwTab, TCM_GETITEMA, 2, (LPARAM)&item); |
| expect(0, item.iImage); |
| /* remove the last one */ |
| SendMessageA(hwTab, TCM_REMOVEIMAGE, 0, 0); |
| expect(0, ImageList_GetImageCount(himl)); |
| for(i = 0; i < 3; i++) { |
| item.iImage = 0; |
| SendMessageA(hwTab, TCM_GETITEMA, i, (LPARAM)&item); |
| expect(-1, item.iImage); |
| } |
| |
| DestroyWindow(hwTab); |
| ImageList_Destroy(himl); |
| DestroyIcon(hicon); |
| } |
| |
| static void test_delete_selection(void) |
| { |
| HWND hTab; |
| INT ret; |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| ret = SendMessageA(hTab, TCM_SETCURSEL, 3, 0); |
| expect(0, ret); |
| ret = SendMessageA(hTab, TCM_GETCURSEL, 0, 0); |
| expect(3, ret); |
| /* delete selected item - selection goes to -1 */ |
| ret = SendMessageA(hTab, TCM_DELETEITEM, 3, 0); |
| expect(TRUE, ret); |
| |
| ret = SendMessageA(hTab, TCM_GETCURSEL, 0, 0); |
| expect(-1, ret); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_TCM_SETITEMEXTRA(void) |
| { |
| HWND hTab; |
| DWORD ret; |
| |
| hTab = CreateWindowA( |
| WC_TABCONTROLA, |
| "TestTab", |
| WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH, |
| 10, 10, 300, 100, |
| parent_wnd, NULL, NULL, 0); |
| |
| /* zero is valid size too */ |
| ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 0, 0); |
| if (ret == FALSE) |
| { |
| win_skip("TCM_SETITEMEXTRA not supported\n"); |
| DestroyWindow(hTab); |
| return; |
| } |
| |
| ret = SendMessageA(hTab, TCM_SETITEMEXTRA, -1, 0); |
| ok(ret == FALSE, "got %d\n", ret); |
| |
| ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0); |
| ok(ret == TRUE, "got %d\n", ret); |
| DestroyWindow(hTab); |
| |
| /* it's not possible to change extra data size for control with tabs */ |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0); |
| ok(ret == FALSE, "got %d\n", ret); |
| DestroyWindow(hTab); |
| } |
| |
| static void test_TCS_OWNERDRAWFIXED(void) |
| { |
| LPARAM lparam; |
| ULONG_PTR itemdata, itemdata2; |
| TCITEMA item; |
| HWND hTab; |
| BOOL ret; |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH|TCS_OWNERDRAWFIXED, TCIF_TEXT|TCIF_IMAGE, 4); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab)); |
| |
| /* set some item data */ |
| memset(&lparam, 0xde, sizeof(LPARAM)); |
| |
| item.mask = TCIF_PARAM; |
| item.lParam = lparam; |
| ret = SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&item); |
| ok(ret == TRUE, "got %d\n", ret); |
| |
| memset(&g_drawitem, 0, sizeof(g_drawitem)); |
| |
| ShowWindow(hTab, SW_SHOW); |
| RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW); |
| |
| itemdata = 0; |
| memset(&itemdata, 0xde, 4); |
| ok(g_drawitem.itemData == itemdata, "got 0x%lx, expected 0x%lx\n", g_drawitem.itemData, itemdata); |
| |
| DestroyWindow(hTab); |
| |
| /* now with custom extra data length */ |
| hTab = CreateWindowA( |
| WC_TABCONTROLA, |
| "TestTab", |
| WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED, |
| 10, 10, 300, 100, |
| parent_wnd, NULL, NULL, 0); |
| |
| ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab)); |
| |
| ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)+1, 0); |
| ok(ret == TRUE, "got %d\n", ret); |
| |
| /* set some item data */ |
| memset(&lparam, 0xde, sizeof(LPARAM)); |
| item.mask = TCIF_PARAM; |
| item.lParam = lparam; |
| |
| ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item); |
| ok(ret == 0, "got %d\n", ret); |
| |
| memset(&g_drawitem, 0, sizeof(g_drawitem)); |
| |
| ShowWindow(hTab, SW_SHOW); |
| RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW); |
| |
| memset(&itemdata, 0xde, sizeof(ULONG_PTR)); |
| ok(*(ULONG_PTR*)g_drawitem.itemData == itemdata, "got 0x%lx, expected 0x%lx\n", g_drawitem.itemData, itemdata); |
| |
| DestroyWindow(hTab); |
| |
| /* same thing, but size smaller than default */ |
| hTab = CreateWindowA( |
| WC_TABCONTROLA, |
| "TestTab", |
| WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED, |
| 10, 10, 300, 100, |
| parent_wnd, NULL, NULL, 0); |
| |
| ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab)); |
| |
| ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0); |
| ok(ret == TRUE, "got %d\n", ret); |
| |
| memset(&lparam, 0xde, sizeof(lparam)); |
| item.mask = TCIF_PARAM; |
| item.lParam = lparam; |
| |
| ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item); |
| ok(ret == 0, "got %d\n", ret); |
| |
| memset(&g_drawitem, 0, sizeof(g_drawitem)); |
| |
| ShowWindow(hTab, SW_SHOW); |
| RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW); |
| |
| itemdata = itemdata2 = 0; |
| memset(&itemdata, 0xde, 4); |
| memset(&itemdata2, 0xde, sizeof(LPARAM)-1); |
| ok(g_drawitem.itemData == itemdata || broken(g_drawitem.itemData == itemdata2) /* win98 */, |
| "got 0x%lx, expected 0x%lx\n", g_drawitem.itemData, itemdata); |
| |
| DestroyWindow(hTab); |
| } |
| |
| static void test_WM_CONTEXTMENU(void) |
| { |
| HWND hTab; |
| |
| hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4); |
| ok(hTab != NULL, "Failed to create tab control\n"); |
| |
| flush_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| SendMessageA(hTab, WM_RBUTTONUP, 0, 0); |
| |
| ok_sequence(sequences, TAB_SEQ_INDEX, rbuttonup_seq, "WM_RBUTTONUP response sequence", FALSE); |
| |
| DestroyWindow(hTab); |
| } |
| |
| struct tabcreate_style { |
| DWORD style; |
| DWORD act_style; |
| }; |
| |
| static const struct tabcreate_style create_styles[] = |
| { |
| { WS_CHILD|TCS_BOTTOM|TCS_VERTICAL, WS_CHILD|WS_CLIPSIBLINGS|TCS_BOTTOM|TCS_VERTICAL|TCS_MULTILINE }, |
| { WS_CHILD|TCS_VERTICAL, WS_CHILD|WS_CLIPSIBLINGS|TCS_VERTICAL|TCS_MULTILINE }, |
| { 0 } |
| }; |
| |
| static void test_create(void) |
| { |
| const struct tabcreate_style *ptr = create_styles; |
| DWORD style; |
| HWND hTab; |
| |
| while (ptr->style) |
| { |
| hTab = CreateWindowA(WC_TABCONTROLA, "TestTab", ptr->style, |
| 10, 10, 300, 100, parent_wnd, NULL, NULL, 0); |
| style = GetWindowLongA(hTab, GWL_STYLE); |
| ok(style == ptr->act_style, "expected style 0x%08x, got style 0x%08x\n", ptr->act_style, style); |
| |
| DestroyWindow(hTab); |
| ptr++; |
| } |
| } |
| |
| START_TEST(tab) |
| { |
| LOGFONTA logfont; |
| |
| lstrcpyA(logfont.lfFaceName, "Arial"); |
| memset(&logfont, 0, sizeof(logfont)); |
| logfont.lfHeight = -12; |
| logfont.lfWeight = FW_NORMAL; |
| logfont.lfCharSet = ANSI_CHARSET; |
| hFont = CreateFontIndirectA(&logfont); |
| |
| InitCommonControls(); |
| |
| test_width(); |
| |
| init_msg_sequences(sequences, NUM_MSG_SEQUENCES); |
| |
| parent_wnd = createParentWindow(); |
| ok(parent_wnd != NULL, "Failed to create parent window!\n"); |
| |
| test_curfocus(); |
| test_cursel(); |
| test_extendedstyle(); |
| test_unicodeformat(); |
| test_getset_item(); |
| test_getset_tooltips(); |
| test_misc(); |
| |
| test_adjustrect(); |
| |
| test_insert_focus(); |
| test_delete_focus(); |
| test_delete_selection(); |
| test_removeimage(); |
| test_TCM_SETITEMEXTRA(); |
| test_TCS_OWNERDRAWFIXED(); |
| test_WM_CONTEXTMENU(); |
| test_create(); |
| |
| DestroyWindow(parent_wnd); |
| } |