Fixes for -Wmissing-declaration and -Wwrite-string warnings.
[wine] / dlls / user / tests / menu.c
1 /*
2  * Unit tests for menus
3  *
4  * Copyright 2005 Robert Shearman
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
23
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <assert.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32
33 #include "wine/test.h"
34
35 static ATOM atomMenuCheckClass;
36
37 static LRESULT WINAPI menu_check_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
38 {
39     switch (msg)
40     {
41     case WM_ENTERMENULOOP:
42         /* mark window as having entered menu loop */
43         SetWindowLongPtr(hwnd, GWLP_USERDATA, TRUE);
44         /* exit menu modal loop */
45         return SendMessage(hwnd, WM_CANCELMODE, 0, 0);
46     }
47     return DefWindowProc(hwnd, msg, wparam, lparam);
48 }
49
50 /* globals to communicate between test and wndproc */
51 unsigned int MOD_maxid;
52 RECT MOD_rc[4];
53 /* wndproc used by test_menu_ownerdraw() */
54 static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg,
55         WPARAM wparam, LPARAM lparam)
56 {
57     switch (msg)
58     {
59     case WM_MEASUREITEM:
60         if( winetest_debug)
61             trace("WM_MEASUREITEM received %d,%d\n",
62                         ((MEASUREITEMSTRUCT*)lparam)->itemWidth ,
63                         ((MEASUREITEMSTRUCT*)lparam)->itemHeight);
64         ((MEASUREITEMSTRUCT*)lparam)->itemWidth = 10;
65         ((MEASUREITEMSTRUCT*)lparam)->itemHeight = 10;
66         return TRUE;
67     case WM_DRAWITEM:
68         {
69         DRAWITEMSTRUCT * pdis;
70         HPEN oldpen;
71         pdis = (DRAWITEMSTRUCT *) lparam;
72         /* store the rectangl */
73         MOD_rc[pdis->itemID] = pdis->rcItem;
74         if( winetest_debug) {
75             trace("WM_DRAWITEM received item %d rc %ld,%ld-%ld,%ld \n",
76                     pdis->itemID, pdis->rcItem.left, pdis->rcItem.top,
77                     pdis->rcItem.right,pdis->rcItem.bottom );
78             oldpen=SelectObject( pdis->hDC, GetStockObject(
79                         pdis->itemState & ODS_SELECTED ? WHITE_PEN :BLACK_PEN));
80             Rectangle( pdis->hDC, pdis->rcItem.left,pdis->rcItem.top,
81                     pdis->rcItem.right,pdis->rcItem.bottom );
82             SelectObject( pdis->hDC, oldpen);
83         }
84         if( pdis->itemID == MOD_maxid) PostMessage(hwnd, WM_CANCELMODE, 0, 0);
85         return TRUE;
86         }
87
88     }
89     return DefWindowProc(hwnd, msg, wparam, lparam);
90 }
91
92 static void register_menu_check_class(void)
93 {
94     WNDCLASS wc =
95     {
96         0,
97         menu_check_wnd_proc,
98         0,
99         0,
100         GetModuleHandle(NULL),
101         NULL,
102         LoadCursor(NULL, IDC_ARROW),
103         (HBRUSH)(COLOR_BTNFACE+1),
104         NULL,
105         TEXT("WineMenuCheck"),
106     };
107     
108     atomMenuCheckClass = RegisterClass(&wc);
109 }
110
111 /* demonstrates that windows lock the menu object so that it is still valid
112  * even after a client calls DestroyMenu on it */
113 static void test_menu_locked_by_window()
114 {
115     BOOL ret;
116     HMENU hmenu;
117     HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
118         WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
119         NULL, NULL, NULL, NULL);
120     ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
121     hmenu = CreateMenu();
122     ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
123     ret = InsertMenu(hmenu, 0, MF_STRING, 0, TEXT("&Test"));
124     ok(ret, "InsertMenu failed with error %ld\n", GetLastError());
125     ret = SetMenu(hwnd, hmenu);
126     ok(ret, "SetMenu failed with error %ld\n", GetLastError());
127     ret = DestroyMenu(hmenu);
128     ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
129
130     ret = DrawMenuBar(hwnd);
131     todo_wine {
132     ok(ret, "DrawMenuBar failed with error %ld\n", GetLastError());
133     }
134     ret = IsMenu(GetMenu(hwnd));
135     ok(!ret, "Menu handle should have been destroyed\n");
136
137     SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
138     /* did we process the WM_INITMENU message? */
139     ret = GetWindowLongPtr(hwnd, GWLP_USERDATA);
140     todo_wine {
141     ok(ret, "WM_INITMENU should have been sent\n");
142     }
143
144     DestroyWindow(hwnd);
145 }
146
147 static void test_menu_ownerdraw()
148 {
149     int i,j,k;
150     BOOL ret;
151     HMENU hmenu;
152     LONG leftcol;
153     HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
154             WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
155             NULL, NULL, NULL, NULL);
156     ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
157     if( !hwnd) return;
158     SetWindowLong( hwnd, GWL_WNDPROC, (LONG)menu_ownerdraw_wnd_proc);
159     hmenu = CreatePopupMenu();
160     ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
161     if( !hmenu) { DestroyWindow(hwnd);return;}
162     k=0;
163     for( j=0;j<2;j++) /* create columns */
164         for(i=0;i<2;i++) { /* create rows */
165             ret = AppendMenu( hmenu, MF_OWNERDRAW | 
166                     (i==0 ? MF_MENUBREAK : 0), k++, 0);
167             ok( ret, "AppendMenu failed for %d\n", k-1);
168         }
169     MOD_maxid = k-1;
170     assert( k <= sizeof(MOD_rc)/sizeof(RECT));
171     /* display the menu */
172     ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
173
174     /* columns have a 4 pixel gap between them */
175     ok( MOD_rc[0].right + 4 ==  MOD_rc[2].left,
176             "item rectangles are not separated by 4 pixels space\n");
177     /* height should be what the MEASUREITEM message has returned */
178     ok( MOD_rc[0].bottom - MOD_rc[0].top == 10,
179             "menu item has wrong height: %ld should be %d\n",
180             MOD_rc[0].bottom - MOD_rc[0].top, 10);
181     /* no gaps between the rows */
182     ok( MOD_rc[0].bottom - MOD_rc[1].top == 0,
183             "There should not be a space between the rows, gap is %ld\n",
184             MOD_rc[0].bottom - MOD_rc[1].top);
185
186     leftcol= MOD_rc[0].left;
187     ModifyMenu( hmenu, 0, MF_BYCOMMAND| MF_OWNERDRAW, 0, 0); 
188     /* display the menu */
189     ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
190
191     /* left should be 4 pixels less now */
192     ok( leftcol == MOD_rc[0].left + 4, 
193             "columns should be 4 pixels to the left (actual %ld).\n",
194             leftcol - MOD_rc[0].left);
195
196     trace("done\n");
197     DestroyMenu( hmenu);
198     DestroyWindow(hwnd);
199 }
200
201 START_TEST(menu)
202 {
203     register_menu_check_class();
204
205     test_menu_locked_by_window();
206     test_menu_ownerdraw();
207 }