Release 1.5.29.
[wine] / dlls / comctl32 / tests / pager.c
1 /*
2  * Unit tests for the pager control
3  *
4  * Copyright 2012 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <windows.h>
22 #include <commctrl.h>
23
24 #include "wine/test.h"
25 #include "msg.h"
26
27 #define NUM_MSG_SEQUENCES   1
28 #define PAGER_SEQ_INDEX     0
29
30 static HWND parent_wnd;
31
32 static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR);
33
34 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
35
36 static const struct message set_child_seq[] = {
37     { PGM_SETCHILD, sent },
38     { WM_WINDOWPOSCHANGING, sent },
39     { WM_NCCALCSIZE, sent|wparam, TRUE },
40     { WM_NOTIFY, sent|id|parent, 0, 0, PGN_CALCSIZE },
41     { WM_WINDOWPOSCHANGED, sent },
42     { 0 }
43 };
44
45 static const struct message set_pos_seq[] = {
46     { PGM_SETPOS, sent },
47     { WM_WINDOWPOSCHANGING, sent },
48     { WM_NCCALCSIZE, sent|wparam, TRUE },
49     { WM_NOTIFY, sent|id|parent, 0, 0, PGN_CALCSIZE },
50     { WM_WINDOWPOSCHANGED, sent },
51     { WM_MOVE, sent|optional },
52     { WM_SIZE, sent|optional },
53     { 0 }
54 };
55
56 static const struct message set_pos_empty_seq[] = {
57     { PGM_SETPOS, sent },
58     { 0 }
59 };
60
61 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
62 {
63     static LONG defwndproc_counter = 0;
64     LRESULT ret;
65     struct message msg;
66
67     /* log system messages, except for painting */
68     if (message < WM_USER &&
69         message != WM_PAINT &&
70         message != WM_ERASEBKGND &&
71         message != WM_NCPAINT &&
72         message != WM_NCHITTEST &&
73         message != WM_GETTEXT &&
74         message != WM_GETICON &&
75         message != WM_DEVICECHANGE)
76     {
77         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
78
79         msg.message = message;
80         msg.flags = sent|wparam|lparam|parent;
81         if (defwndproc_counter) msg.flags |= defwinproc;
82         msg.wParam = wParam;
83         msg.lParam = lParam;
84         if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
85         add_message(sequences, PAGER_SEQ_INDEX, &msg);
86     }
87
88     defwndproc_counter++;
89     ret = DefWindowProcA(hwnd, message, wParam, lParam);
90     defwndproc_counter--;
91
92     return ret;
93 }
94
95 static BOOL register_parent_wnd_class(void)
96 {
97     WNDCLASSA cls;
98
99     cls.style = 0;
100     cls.lpfnWndProc = parent_wnd_proc;
101     cls.cbClsExtra = 0;
102     cls.cbWndExtra = 0;
103     cls.hInstance = GetModuleHandleA(NULL);
104     cls.hIcon = 0;
105     cls.hCursor = LoadCursorA(0, IDC_ARROW);
106     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
107     cls.lpszMenuName = NULL;
108     cls.lpszClassName = "Pager test parent class";
109     return RegisterClassA(&cls);
110 }
111
112 static HWND create_parent_window(void)
113 {
114     if (!register_parent_wnd_class())
115         return NULL;
116
117     return CreateWindow("Pager test parent class", "Pager test parent window",
118                         WS_OVERLAPPED | WS_VISIBLE,
119                         0, 0, 200, 200, 0, NULL, GetModuleHandleA(NULL), NULL );
120 }
121
122 static LRESULT WINAPI pager_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
123 {
124     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
125     struct message msg;
126
127     trace("pager: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
128
129     msg.message = message;
130     msg.flags = sent|wparam|lparam;
131     msg.wParam = wParam;
132     msg.lParam = lParam;
133     msg.id     = 0;
134     add_message(sequences, PAGER_SEQ_INDEX, &msg);
135     return CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
136 }
137
138 static HWND create_pager_control( DWORD style )
139 {
140     WNDPROC oldproc;
141     HWND hwnd;
142     RECT rect;
143
144     GetClientRect( parent_wnd, &rect );
145     hwnd = CreateWindowA( WC_PAGESCROLLERA, "pager", WS_CHILD | WS_BORDER | WS_VISIBLE | style,
146                           0, 0, 100, 100, parent_wnd, 0, GetModuleHandleA(0), 0 );
147     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)pager_subclass_proc);
148     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
149     return hwnd;
150 }
151
152 static void test_pager(void)
153 {
154     HWND pager, child;
155     RECT rect;
156
157     pager = create_pager_control( PGS_HORZ );
158     if (!pager)
159     {
160         win_skip( "Pager control not supported\n" );
161         return;
162     }
163     child = CreateWindowA( "BUTTON", "button", WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 300, 300,
164                            pager, 0, GetModuleHandleA(0), 0 );
165
166     flush_sequences( sequences, NUM_MSG_SEQUENCES );
167     SendMessageA( pager, PGM_SETCHILD, 0, (LPARAM)child );
168     ok_sequence(sequences, PAGER_SEQ_INDEX, set_child_seq, "set child", TRUE);
169     GetWindowRect( pager, &rect );
170     ok( rect.right - rect.left == 100 && rect.bottom - rect.top == 100,
171         "pager resized %dx%d\n", rect.right - rect.left, rect.bottom - rect.top );
172
173     flush_sequences( sequences, NUM_MSG_SEQUENCES );
174     SendMessageA( pager, PGM_SETPOS, 0, 10 );
175     ok_sequence(sequences, PAGER_SEQ_INDEX, set_pos_seq, "set pos", TRUE);
176     GetWindowRect( pager, &rect );
177     ok( rect.right - rect.left == 100 && rect.bottom - rect.top == 100,
178         "pager resized %dx%d\n", rect.right - rect.left, rect.bottom - rect.top );
179
180     flush_sequences( sequences, NUM_MSG_SEQUENCES );
181     SendMessageA( pager, PGM_SETPOS, 0, 10 );
182     ok_sequence(sequences, PAGER_SEQ_INDEX, set_pos_empty_seq, "set pos empty", TRUE);
183
184     flush_sequences( sequences, NUM_MSG_SEQUENCES );
185     SendMessageA( pager, PGM_SETPOS, 0, 9 );
186     ok_sequence(sequences, PAGER_SEQ_INDEX, set_pos_seq, "set pos", TRUE);
187
188     DestroyWindow( pager );
189 }
190
191 START_TEST(pager)
192 {
193     HMODULE mod = GetModuleHandleA("comctl32.dll");
194
195     pSetWindowSubclass = (void*)GetProcAddress(mod, (LPSTR)410);
196
197     InitCommonControls();
198     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
199
200     parent_wnd = create_parent_window();
201     ok(parent_wnd != NULL, "Failed to create parent window!\n");
202
203     test_pager();
204 }