user32: Make GetMenuItemInfo tests pass under Wine.
[wine/winequartzdrv.git] / dlls / user / tests / menu.c
blobadc5e6572ca9c93cd975c794e31d5c514448c5b6
1 /*
2 * Unit tests for menus
4 * Copyright 2005 Robert Shearman
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.
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.
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
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <assert.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winuser.h"
33 #include "wine/test.h"
35 static ATOM atomMenuCheckClass;
37 static LRESULT WINAPI menu_check_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
39 switch (msg)
41 case WM_ENTERMENULOOP:
42 /* mark window as having entered menu loop */
43 SetWindowLongPtr(hwnd, GWLP_USERDATA, TRUE);
44 /* exit menu modal loop
45 * ( A SendMessage does not work on NT3.51 here ) */
46 return PostMessage(hwnd, WM_CANCELMODE, 0, 0);
48 return DefWindowProc(hwnd, msg, wparam, lparam);
51 /* globals to communicate between test and wndproc */
52 unsigned int MOD_maxid;
53 RECT MOD_rc[4];
54 int MOD_avec, MOD_hic;
55 int MOD_odheight;
56 #define MOD_SIZE 10
57 /* wndproc used by test_menu_ownerdraw() */
58 static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg,
59 WPARAM wparam, LPARAM lparam)
61 switch (msg)
63 case WM_MEASUREITEM:
65 MEASUREITEMSTRUCT* pmis = (MEASUREITEMSTRUCT*)lparam;
66 if( winetest_debug)
67 trace("WM_MEASUREITEM received %d,%d\n",
68 pmis->itemWidth, pmis->itemHeight);
69 MOD_odheight = pmis->itemHeight;
70 pmis->itemWidth = MOD_SIZE;
71 pmis->itemHeight = MOD_SIZE;
72 return TRUE;
74 case WM_DRAWITEM:
76 DRAWITEMSTRUCT * pdis;
77 TEXTMETRIC tm;
78 HPEN oldpen;
79 char chrs[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
80 SIZE sz;
81 pdis = (DRAWITEMSTRUCT *) lparam;
82 if( winetest_debug) {
83 trace("WM_DRAWITEM received itemdata %ld item %d rc %ld,%ld-%ld,%ld\n",
84 pdis->itemData,
85 pdis->itemID, pdis->rcItem.left, pdis->rcItem.top,
86 pdis->rcItem.right,pdis->rcItem.bottom );
87 oldpen=SelectObject( pdis->hDC, GetStockObject(
88 pdis->itemState & ODS_SELECTED ? WHITE_PEN :BLACK_PEN));
89 Rectangle( pdis->hDC, pdis->rcItem.left,pdis->rcItem.top,
90 pdis->rcItem.right,pdis->rcItem.bottom );
91 SelectObject( pdis->hDC, oldpen);
93 if( pdis->itemData > MOD_maxid) return TRUE;
94 /* store the rectangl */
95 MOD_rc[pdis->itemData] = pdis->rcItem;
96 /* calculate average character width */
97 GetTextExtentPoint( pdis->hDC, chrs, 52, &sz );
98 MOD_avec = (sz.cx + 26)/52;
99 GetTextMetrics( pdis->hDC, &tm);
100 MOD_hic = tm.tmHeight;
101 if( pdis->itemData == MOD_maxid) PostMessage(hwnd, WM_CANCELMODE, 0, 0);
102 return TRUE;
106 return DefWindowProc(hwnd, msg, wparam, lparam);
109 static void register_menu_check_class(void)
111 WNDCLASS wc =
114 menu_check_wnd_proc,
117 GetModuleHandle(NULL),
118 NULL,
119 LoadCursor(NULL, IDC_ARROW),
120 (HBRUSH)(COLOR_BTNFACE+1),
121 NULL,
122 TEXT("WineMenuCheck"),
125 atomMenuCheckClass = RegisterClass(&wc);
128 /* demonstrates that windows lock the menu object so that it is still valid
129 * even after a client calls DestroyMenu on it */
130 static void test_menu_locked_by_window(void)
132 BOOL ret;
133 HMENU hmenu;
134 HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
135 WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
136 NULL, NULL, NULL, NULL);
137 ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
138 hmenu = CreateMenu();
139 ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
140 ret = InsertMenu(hmenu, 0, MF_STRING, 0, TEXT("&Test"));
141 ok(ret, "InsertMenu failed with error %ld\n", GetLastError());
142 ret = SetMenu(hwnd, hmenu);
143 ok(ret, "SetMenu failed with error %ld\n", GetLastError());
144 ret = DestroyMenu(hmenu);
145 ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
147 ret = DrawMenuBar(hwnd);
148 todo_wine {
149 ok(ret, "DrawMenuBar failed with error %ld\n", GetLastError());
151 ret = IsMenu(GetMenu(hwnd));
152 ok(!ret, "Menu handle should have been destroyed\n");
154 SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
155 /* did we process the WM_INITMENU message? */
156 ret = GetWindowLongPtr(hwnd, GWLP_USERDATA);
157 todo_wine {
158 ok(ret, "WM_INITMENU should have been sent\n");
161 DestroyWindow(hwnd);
164 static void test_menu_ownerdraw(void)
166 int i,j,k;
167 BOOL ret;
168 HMENU hmenu;
169 LONG leftcol;
170 HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL,
171 WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
172 NULL, NULL, NULL, NULL);
173 ok(hwnd != NULL, "CreateWindowEx failed with error %ld\n", GetLastError());
174 if( !hwnd) return;
175 SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG)menu_ownerdraw_wnd_proc);
176 hmenu = CreatePopupMenu();
177 ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
178 if( !hmenu) { DestroyWindow(hwnd);return;}
179 k=0;
180 for( j=0;j<2;j++) /* create columns */
181 for(i=0;i<2;i++) { /* create rows */
182 ret = AppendMenu( hmenu, MF_OWNERDRAW |
183 (i==0 ? MF_MENUBREAK : 0), k, (LPCTSTR) k);
184 k++;
185 ok( ret, "AppendMenu failed for %d\n", k-1);
187 MOD_maxid = k-1;
188 assert( k <= sizeof(MOD_rc)/sizeof(RECT));
189 /* display the menu */
190 ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
192 /* columns have a 4 pixel gap between them */
193 ok( MOD_rc[0].right + 4 == MOD_rc[2].left,
194 "item rectangles are not separated by 4 pixels space\n");
195 /* height should be what the MEASUREITEM message has returned */
196 ok( MOD_rc[0].bottom - MOD_rc[0].top == MOD_SIZE,
197 "menu item has wrong height: %ld should be %d\n",
198 MOD_rc[0].bottom - MOD_rc[0].top, MOD_SIZE);
199 /* no gaps between the rows */
200 ok( MOD_rc[0].bottom - MOD_rc[1].top == 0,
201 "There should not be a space between the rows, gap is %ld\n",
202 MOD_rc[0].bottom - MOD_rc[1].top);
203 /* test the correct value of the item height that was sent
204 * by the WM_MEASUREITEM message */
205 ok( MOD_odheight == HIWORD( GetDialogBaseUnits()) || /* WinNT,2k,XP */
206 MOD_odheight == MOD_hic, /* Win95,98,ME */
207 "Wrong height field in MEASUREITEMSTRUCT, expected %d or %d actual %d\n",
208 HIWORD( GetDialogBaseUnits()), MOD_hic, MOD_odheight);
209 /* test what MF_MENUBREAK did at the first position. Also show
210 * that an MF_SEPARATOR is ignored in the height calculation. */
211 leftcol= MOD_rc[0].left;
212 ModifyMenu( hmenu, 0, MF_BYCOMMAND| MF_OWNERDRAW| MF_SEPARATOR, 0, 0);
213 /* display the menu */
214 ret = TrackPopupMenu( hmenu, 0x100, 100,100, 0, hwnd, NULL);
215 /* left should be 4 pixels less now */
216 ok( leftcol == MOD_rc[0].left + 4,
217 "columns should be 4 pixels to the left (actual %ld).\n",
218 leftcol - MOD_rc[0].left);
219 /* test width */
220 ok( MOD_rc[0].right - MOD_rc[0].left == 2 * MOD_avec + MOD_SIZE,
221 "width of owner drawn menu item is wrong. Got %ld expected %d\n",
222 MOD_rc[0].right - MOD_rc[0].left , 2*MOD_avec + MOD_SIZE);
223 /* and height */
224 ok( MOD_rc[0].bottom - MOD_rc[0].top == MOD_SIZE,
225 "Height is incorrect. Got %ld expected %d\n",
226 MOD_rc[0].bottom - MOD_rc[0].top, MOD_SIZE);
228 /* test width/height of a OD menu bar as well */
229 ret = DestroyMenu(hmenu);
230 ok(ret, "DestroyMenu failed with error %ld\n", GetLastError());
231 hmenu = CreateMenu();
232 ok(hmenu != NULL, "CreateMenu failed with error %ld\n", GetLastError());
233 if( !hmenu) { DestroyWindow(hwnd);return;}
234 MOD_maxid=1;
235 for(i=0;i<2;i++) {
236 ret = AppendMenu( hmenu, MF_OWNERDRAW , i, 0);
237 ok( ret, "AppendMenu failed for %d\n", i);
239 SetMenu( hwnd, hmenu);
240 UpdateWindow( hwnd); /* hack for wine to draw the window + menu */
241 ok(ret, "SetMenu failed with error %ld\n", GetLastError());
242 /* test width */
243 ok( MOD_rc[0].right - MOD_rc[0].left == 2 * MOD_avec + MOD_SIZE,
244 "width of owner drawn menu item is wrong. Got %ld expected %d\n",
245 MOD_rc[0].right - MOD_rc[0].left , 2*MOD_avec + MOD_SIZE);
246 /* test hight */
247 ok( MOD_rc[0].bottom - MOD_rc[0].top == GetSystemMetrics( SM_CYMENU) - 1,
248 "Height of owner drawn menu item is wrong. Got %ld expected %d\n",
249 MOD_rc[0].bottom - MOD_rc[0].top, GetSystemMetrics( SM_CYMENU) - 1);
250 /* clean up */
251 DestroyWindow(hwnd);
254 static void test_menu_add_string( void )
256 HMENU hmenu;
257 MENUITEMINFO info;
258 BOOL rc;
260 char string[0x80];
261 char string2[0x80];
263 char strback[0x80];
264 WCHAR strbackW[0x80];
265 static const WCHAR expectedString[] = {'D', 'u', 'm', 'm', 'y', ' ',
266 's', 't', 'r', 'i', 'n', 'g', 0};
268 hmenu = CreateMenu();
270 memset( &info, 0, sizeof info );
271 info.cbSize = sizeof info;
272 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_ID;
273 info.dwTypeData = "blah";
274 info.cch = 6;
275 info.dwItemData = 0;
276 info.wID = 1;
277 info.fState = 0;
278 InsertMenuItem(hmenu, 0, TRUE, &info );
280 memset( &info, 0, sizeof info );
281 info.cbSize = sizeof info;
282 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_DATA | MIIM_ID;
283 info.dwTypeData = string;
284 info.cch = sizeof string;
285 string[0] = 0;
286 GetMenuItemInfo( hmenu, 0, TRUE, &info );
288 ok( !strcmp( string, "blah" ), "menu item name differed\n");
290 /* Test combination of ownerdraw and strings with GetMenuItemString(A/W) */
291 strcpy(string, "Dummy string");
292 memset(&info, 0x00, sizeof(info));
293 info.cbSize= sizeof(MENUITEMINFO);
294 info.fMask= MIIM_FTYPE | MIIM_STRING; /* Set OwnerDraw + typeData */
295 info.fType= MFT_OWNERDRAW;
296 info.dwTypeData= string;
297 rc = InsertMenuItem( hmenu, 0, TRUE, &info );
298 ok (rc, "InsertMenuItem failed\n");
300 strcpy(string,"Garbage");
301 ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
302 ok (!strcmp( strback, "Dummy string" ), "Menu text from Ansi version incorrect\n");
304 ok (GetMenuStringW( hmenu, 0, (WCHAR *)strbackW, 99, MF_BYPOSITION), "GetMenuStringW on ownerdraw entry failed\n");
305 ok (!lstrcmpW( strbackW, expectedString ), "Menu text from Unicode version incorrect\n");
307 /* Just change ftype to string and see what text is stored */
308 memset(&info, 0x00, sizeof(info));
309 info.cbSize= sizeof(MENUITEMINFO);
310 info.fMask= MIIM_FTYPE; /* Set string type */
311 info.fType= MFT_STRING;
312 info.dwTypeData= (char *)0xdeadbeef;
313 rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
314 ok (rc, "SetMenuItemInfo failed\n");
316 /* Did we keep the old dwTypeData? */
317 ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
318 ok (!strcmp( strback, "Dummy string" ), "Menu text from Ansi version incorrect\n");
320 /* Ensure change to bitmap type fails */
321 memset(&info, 0x00, sizeof(info));
322 info.cbSize= sizeof(MENUITEMINFO);
323 info.fMask= MIIM_FTYPE; /* Set as bitmap type */
324 info.fType= MFT_BITMAP;
325 info.dwTypeData= (char *)0xdeadbee2;
326 rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
327 ok (!rc, "SetMenuItemInfo unexpectedly worked\n");
329 /* Just change ftype back and ensure data hasnt been freed */
330 info.fType= MFT_OWNERDRAW; /* Set as ownerdraw type */
331 info.dwTypeData= (char *)0xdeadbee3;
332 rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
333 ok (rc, "SetMenuItemInfo failed\n");
335 /* Did we keep the old dwTypeData? */
336 ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
337 ok (!strcmp( strback, "Dummy string" ), "Menu text from Ansi version incorrect\n");
339 /* Just change string value (not type) */
340 memset(&info, 0x00, sizeof(info));
341 info.cbSize= sizeof(MENUITEMINFO);
342 info.fMask= MIIM_STRING; /* Set typeData */
343 strcpy(string2, "string2");
344 info.dwTypeData= string2;
345 rc = SetMenuItemInfo( hmenu, 0, TRUE, &info );
346 ok (rc, "SetMenuItemInfo failed\n");
348 ok (GetMenuString( hmenu, 0, strback, 99, MF_BYPOSITION), "GetMenuString on ownerdraw entry failed\n");
349 ok (!strcmp( strback, "string2" ), "Menu text from Ansi version incorrect\n");
351 /* crashes with wine 0.9.5 */
352 memset(&info, 0x00, sizeof(info));
353 info.cbSize= sizeof(MENUITEMINFO);
354 info.fMask= MIIM_FTYPE | MIIM_STRING; /* Set OwnerDraw + typeData */
355 info.fType= MFT_OWNERDRAW;
356 rc = InsertMenuItem( hmenu, 0, TRUE, &info );
357 ok (rc, "InsertMenuItem failed\n");
358 ok (!GetMenuString( hmenu, 0, NULL, 0, MF_BYPOSITION),
359 "GetMenuString on ownerdraw entry succeeded.\n");
360 ok (!GetMenuStringW( hmenu, 0, NULL, 0, MF_BYPOSITION),
361 "GetMenuStringW on ownerdraw entry succeeded.\n");
364 DestroyMenu( hmenu );
367 /* define building blocks for the menu item info tests */
368 static int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
370 if (n <= 0) return 0;
371 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
372 return *str1 - *str2;
375 static WCHAR *strcpyW( WCHAR *dst, const WCHAR *src )
377 WCHAR *p = dst;
378 while ((*p++ = *src++));
379 return dst;
383 #define DMIINFF( i, e, field)\
384 ok((int)((i)->field)==(int)((e)->field) || (int)((i)->field)==(0xffff & (int)((e)->field)), \
385 "%s got 0x%x expected 0x%x\n", #field, (int)((i)->field), (int)((e)->field));
387 #define DUMPMIINF(s,i,e)\
389 DMIINFF( i, e, fMask)\
390 DMIINFF( i, e, fType)\
391 DMIINFF( i, e, fState)\
392 DMIINFF( i, e, wID)\
393 DMIINFF( i, e, hSubMenu)\
394 DMIINFF( i, e, hbmpChecked)\
395 DMIINFF( i, e, hbmpUnchecked)\
396 DMIINFF( i, e, dwItemData)\
397 DMIINFF( i, e, dwTypeData)\
398 DMIINFF( i, e, cch)\
399 if( s==sizeof(MENUITEMINFOA)) DMIINFF( i, e, hbmpItem)\
402 /* insert menu item */
403 #define TMII_INSMI( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
404 eret1)\
406 MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
407 HMENU hmenu = CreateMenu();\
408 BOOL ret, stop = FALSE;\
409 SetLastError( 0xdeadbeef);\
410 if(ansi)strcpy( string, init);\
411 else strcpyW( (WCHAR*)string, (WCHAR*)init);\
412 if( ansi) ret = InsertMenuItemA(hmenu, 0, TRUE, &info1 );\
413 else ret = InsertMenuItemW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
414 if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
415 stop = TRUE;\
416 } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
419 /* GetMenuItemInfo + GetMenuString */
420 #define TMII_GMII( a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,\
421 a3,b3,c3,d3,e3,f3,g3,h3,i3,j3,k3,l3,m3,n3,\
422 expname, eret2, eret3)\
424 MENUITEMINFOA info2A=a2 b2,c2,d2,e2,f2,(void*)g2,(void*)h2,(void*)i2,j2,(void*)k2,l2,(void*)m2 n2;\
425 MENUITEMINFOA einfoA=a3 b3,c3,d3,e3,f3,(void*)g3,(void*)h3,(void*)i3,j3,(void*)k3,l3,(void*)m3 n3;\
426 MENUITEMINFOA *info2 = &info2A;\
427 MENUITEMINFOA *einfo = &einfoA;\
428 MENUITEMINFOW *info2W = (MENUITEMINFOW *)&info2A;\
429 if( !stop) {\
430 ret = ansi ? GetMenuItemInfoA( hmenu, 0, TRUE, info2 ) :\
431 GetMenuItemInfoW( hmenu, 0, TRUE, info2W );\
432 if( !(eret2)) ok( (eret2)==ret,"GetMenuItemInfo should have failed.\n");\
433 else { \
434 ok( (eret2)==ret,"GetMenuItemInfo failed, err %ld\n",GetLastError());\
435 ret = memcmp( info2, einfo, sizeof einfoA);\
436 /* ok( ret==0, "Got wrong menu item info data\n");*/\
437 if( ret) DUMPMIINF(info2A.cbSize, &info2A, &einfoA)\
438 if( einfo->dwTypeData == string) {\
439 if(ansi) ok( !strncmp( expname, info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
440 einfo->dwTypeData ? einfo->dwTypeData: "");\
441 else ok( !strncmpW( (WCHAR*)expname, (WCHAR*)info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
442 einfo->dwTypeData ? einfo->dwTypeData: "");\
443 ret = ansi ? GetMenuStringA( hmenu, 0, string, 80, MF_BYPOSITION) :\
444 GetMenuStringW( hmenu, 0, string, 80, MF_BYPOSITION);\
445 if( (eret3)){\
446 ok( ret, "GetMenuString failed, err %ld\n",GetLastError());\
447 }else\
448 ok( !ret, "GetMenuString should have failed\n");\
454 #define TMII_DONE \
455 RemoveMenu(hmenu, 0, TRUE );\
456 DestroyMenu( hmenu );\
457 DestroyMenu( submenu );\
458 submenu = CreateMenu();\
460 /* modify menu */
461 #define TMII_MODM( flags, id, data, eret )\
462 if( !stop) {\
463 if(ansi)ret = ModifyMenuA( hmenu, 0, flags, (UINT_PTR)id, (char*)data);\
464 else ret = ModifyMenuW( hmenu, 0, flags, (UINT_PTR)id, (WCHAR*)data);\
465 if( !(eret)) ok( (eret)==ret,"ModifyMenuA should have failed.\n");\
466 else ok( (eret)==ret,"ModifyMenuA failed, err %ld\n",GetLastError());\
469 /* SetMenuItemInfo */
470 #define TMII_SMII( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
471 eret1)\
472 if( !stop) {\
473 MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
474 SetLastError( 0xdeadbeef);\
475 if(ansi)strcpy( string, init);\
476 else strcpyW( (WCHAR*)string, (WCHAR*)init);\
477 if( ansi) ret = SetMenuItemInfoA(hmenu, 0, TRUE, &info1 );\
478 else ret = SetMenuItemInfoW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
479 if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
480 stop = TRUE;\
481 } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
486 #define OK 1
487 #define ER 0
490 static void test_menu_iteminfo( )
492 int S=sizeof( MENUITEMINFOA);
493 int ansi = TRUE;
494 char txtA[]="wine";
495 char initA[]="XYZ";
496 char emptyA[]="";
497 WCHAR txtW[]={'W','i','n','e',0};
498 WCHAR initW[]={'X','Y','Z',0};
499 WCHAR emptyW[]={0};
500 void *txt, *init, *empty, *string;
501 HBITMAP hbm = CreateBitmap(1,1,1,1,NULL);
502 char stringA[0x80];
503 HMENU submenu=CreateMenu();
505 do {
506 if( ansi) {txt=txtA;init=initA;empty=emptyA;string=stringA;}
507 else {txt=txtW;init=initW;empty=emptyW;string=stringA;}
508 trace( "%s string %p hbm %p txt %p\n", ansi ? "ANSI tests: " : "Unicode tests:", string, hbm, txt);
509 /* test all combinations of MFT_STRING, MFT_OWNERDRAW and MFT_BITMAP */
510 /* (since MFT_STRING is zero, there are four of them) */
511 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, 0, 0, 0, 0, 0, 0, txt, 0, 0, }, OK)
512 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
513 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
514 txt, OK, OK )
515 TMII_DONE
516 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
517 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
518 {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
519 empty, OK, ER )
520 TMII_DONE
521 TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, 6, -1, }, OK)
522 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
523 {, S, MIIM_TYPE, MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
524 empty, OK, ER )
525 TMII_DONE
526 TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, hbm, 6, -1, }, OK)
527 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
528 {, S, MIIM_TYPE, MFT_BITMAP|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
529 empty, OK, ER )
530 TMII_DONE
531 /* not enough space for name*/
532 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
533 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, NULL, 0, -9, },
534 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, NULL, 4, 0, },
535 empty, OK, OK )
536 TMII_DONE
537 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
538 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 5, -9, },
539 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
540 txt, OK, OK )
541 TMII_DONE
542 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
543 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 4, -9, },
544 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 3, 0, },
545 txt, OK, OK )
546 TMII_DONE
547 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
548 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, NULL, 0, -9, },
549 {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 0, 0, },
550 empty, OK, ER )
551 TMII_DONE
552 /* can not combine MIIM_TYPE with some other flags */
553 TMII_INSMI( {, S, MIIM_TYPE|MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, ER)
554 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
555 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
556 empty, OK, OK )
557 TMII_DONE
558 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
559 TMII_GMII ( {, S, MIIM_TYPE|MIIM_STRING, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
560 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
561 empty, ER, OK )
562 TMII_DONE
563 TMII_INSMI( {, S, MIIM_TYPE|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, ER)
564 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
565 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
566 empty, OK, OK )
567 TMII_DONE
568 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
569 TMII_GMII ( {, S, MIIM_TYPE|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
570 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
571 empty, ER, OK )
572 TMII_DONE
573 TMII_INSMI( {, S, MIIM_TYPE|MIIM_BITMAP, MFT_BITMAP, -1, -1, -1, -1, -1, -1, hbm, 6, hbm, }, ER)
574 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
575 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
576 empty, OK, OK )
577 TMII_DONE
578 /* but succeeds with some others */
579 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
580 TMII_GMII ( {, S, MIIM_TYPE|MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
581 {, S, MIIM_TYPE|MIIM_SUBMENU, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
582 txt, OK, OK )
583 TMII_DONE
584 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
585 TMII_GMII ( {, S, MIIM_TYPE|MIIM_STATE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
586 {, S, MIIM_TYPE|MIIM_STATE, MFT_STRING, 0, -9, 0, -9, -9, -9, string, 4, 0, },
587 txt, OK, OK )
588 TMII_DONE
589 TMII_INSMI( {, S, MIIM_TYPE|MIIM_ID, MFT_STRING, -1, 888, -1, -1, -1, -1, txt, 6, -1, }, OK)
590 TMII_GMII ( {, S, MIIM_TYPE|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
591 {, S, MIIM_TYPE|MIIM_ID, MFT_STRING, -9, 888, 0, -9, -9, -9, string, 4, 0, },
592 txt, OK, OK )
593 TMII_DONE
594 TMII_INSMI( {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING, -1, -1, -1, -1, -1, 999, txt, 6, -1, }, OK)
595 TMII_GMII ( {, S, MIIM_TYPE|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
596 {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING, -9, -9, 0, -9, -9, 999, string, 4, 0, },
597 txt, OK, OK )
598 TMII_DONE
599 /* to be continued */
600 /* set text with MIIM_TYPE and retrieve with MIIM_STRING */
601 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
602 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
603 {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, -9, },
604 txt, OK, OK )
605 TMII_DONE
606 /* set text with MIIM_TYPE and retrieve with MIIM_STRING; MFT_OWNERDRAW causes an empty string */
607 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
608 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
609 {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 0, -9, },
610 empty, OK, ER )
611 TMII_DONE
612 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
613 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
614 {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 0, -9, },
615 empty, OK, ER )
616 TMII_DONE
617 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
618 TMII_GMII ( {, S, MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
619 {, S, MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 80, -9, },
620 init, OK, ER )
621 TMII_DONE
622 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
623 TMII_GMII ( {, S, 0, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
624 {, S, 0, -9, -9, -9, 0, -9, -9, -9, string, 80, -9, },
625 init, OK, OK )
626 TMII_DONE
627 /* contrary to MIIM_TYPE,you can set the text for an owner draw menu */
628 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
629 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
630 {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 4, -9, },
631 txt, OK, OK )
632 TMII_DONE
633 /* same but retrieve with MIIM_TYPE */
634 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
635 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
636 {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
637 txt, OK, OK )
638 TMII_DONE
639 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
640 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
641 {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 0, -9, },
642 empty, OK, ER )
643 TMII_DONE
644 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING, -1, -1, -1, -1, -1, -1, NULL, 0, -1, }, OK)
645 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
646 {, S, MIIM_STRING|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 0, -9, },
647 empty, OK, ER )
648 TMII_DONE
650 /* How is that with bitmaps? */
651 TMII_INSMI( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
652 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
653 {, S, MIIM_TYPE, MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
654 empty, OK, ER )
655 TMII_DONE
656 TMII_INSMI( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
657 TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
658 {, S, MIIM_BITMAP|MIIM_FTYPE, 0, -9, -9, 0, -9, -9, -9, string, 80, hbm, },
659 init, OK, ER )
660 TMII_DONE
661 /* MIIM_BITMAP does not like MFT_BITMAP */
662 TMII_INSMI( {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, ER)
663 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
664 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
665 init, OK, OK )
666 TMII_DONE
667 /* no problem with OWNERDRAWN */
668 TMII_INSMI( {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
669 TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
670 {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 80, hbm, },
671 init, OK, ER )
672 TMII_DONE
673 /* setting MFT_BITMAP with MFT_FTYPE fails anyway */
674 TMII_INSMI( {, S, MIIM_FTYPE, MFT_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, ER)
675 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
676 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
677 empty, OK, OK )
678 TMII_DONE
680 /* menu with submenu */
681 TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, submenu, -1, -1, -1, txt, 0, -1, }, OK)
682 TMII_GMII ( {, S, MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
683 {, S, MIIM_SUBMENU, -9, -9, -9, submenu, -9, -9, -9, string, 80, -9, },
684 init, OK, ER )
685 TMII_DONE
686 TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, submenu, -1, -1, -1, empty, 0, -1, }, OK)
687 TMII_GMII ( {, S, MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
688 {, S, MIIM_SUBMENU, -9, -9, -9, submenu, -9, -9, -9, string, 80, -9, },
689 init, OK, ER )
690 TMII_DONE
691 /* menu with submenu, without MIIM_SUBMENU the submenufield is cleared */
692 TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, submenu, -1, -1, -1, txt, 0, -1, }, OK)
693 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
694 {, S, MIIM_STRING|MIIM_FTYPE, MFT_STRING|MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 0, -9, },
695 empty, OK, ER )
696 TMII_GMII ( {, S, MIIM_SUBMENU|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
697 {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, submenu, -9, -9, -9, string, 80, -9, },
698 empty, OK, ER )
699 TMII_DONE
700 /* menu with invalid submenu */
701 TMII_INSMI( {, S, MIIM_SUBMENU|MIIM_FTYPE, MFT_STRING, -1, -1, 999, -1, -1, -1, txt, 0, -1, }, ER)
702 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
703 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
704 init, OK, ER )
705 TMII_DONE
707 TMII_INSMI( {, S, MIIM_TYPE, MFT_SEPARATOR, 0, 0, 0, 0, 0, 0, txt, 0, 0, }, OK)
708 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
709 {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
710 empty, OK, ER )
711 TMII_DONE
712 TMII_INSMI( {, S, MIIM_TYPE, MFT_BITMAP|MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, hbm, 6, -1, }, OK)
713 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
714 {, S, MIIM_TYPE, MFT_BITMAP|MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, hbm, 0, hbm, },
715 empty, OK, ER )
716 TMII_DONE
717 /* SEPARATOR and STRING go well together */
718 /* BITMAP and STRING go well together */
719 TMII_INSMI( {, S, MIIM_STRING|MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
720 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
721 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, hbm, },
722 txt, OK, OK )
723 TMII_DONE
724 /* BITMAP, SEPARATOR and STRING go well together */
725 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
726 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
727 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 4, hbm, },
728 txt, OK, OK )
729 TMII_DONE
730 /* last two tests, but use MIIM_TYPE to retrieve info */
731 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
732 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
733 {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
734 txt, OK, OK )
735 TMII_DONE
736 TMII_INSMI( {, S, MIIM_STRING|MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
737 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
738 {, S, MIIM_TYPE, MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
739 txt, OK, OK )
740 TMII_DONE
741 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
742 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
743 {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_BITMAP, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
744 txt, OK, OK )
745 TMII_DONE
746 /* same three with MFT_OWNERDRAW */
747 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING, MFT_SEPARATOR|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, -1, }, OK)
748 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
749 {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
750 txt, OK, OK )
751 TMII_DONE
752 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
753 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
754 {, S, MIIM_TYPE, MFT_BITMAP|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
755 txt, OK, OK )
756 TMII_DONE
757 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
758 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
759 {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_BITMAP|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, hbm, 4, hbm, },
760 txt, OK, OK )
761 TMII_DONE
763 TMII_INSMI( {, S, MIIM_STRING|MIIM_FTYPE|MIIM_ID, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
764 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
765 {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
766 txt, OK, OK )
767 TMII_DONE
768 /* test with modifymenu: string is preserved after seting OWNERDRAW */
769 TMII_INSMI( {, S, MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
770 TMII_MODM( MFT_OWNERDRAW, -1, 787, OK)
771 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
772 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_DATA, MFT_OWNERDRAW, -9, -9, 0, -9, -9, 787, string, 4, -9, },
773 txt, OK, OK )
774 TMII_DONE
775 /* same with bitmap: now the text is cleared */
776 TMII_INSMI( {, S, MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
777 TMII_MODM( MFT_BITMAP, 545, hbm, OK)
778 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
779 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_BITMAP, -9, 545, 0, -9, -9, -9, string, 0, hbm, },
780 empty, OK, ER )
781 TMII_DONE
782 /* start with bitmap: now setting text clears it (though he flag is raised) */
783 TMII_INSMI( {, S, MIIM_BITMAP, MFT_STRING, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
784 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
785 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_STRING, -9, 0, 0, -9, -9, -9, string, 0, hbm, },
786 empty, OK, ER )
787 TMII_MODM( MFT_STRING, 545, txt, OK)
788 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
789 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_STRING, -9, 545, 0, -9, -9, -9, string, 4, 0, },
790 txt, OK, OK )
791 TMII_DONE
792 /*repeat with text NULL */
793 TMII_INSMI( {, S, MIIM_BITMAP, MFT_STRING, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
794 TMII_MODM( MFT_STRING, 545, NULL, OK)
795 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
796 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_SEPARATOR, -9, 545, 0, -9, -9, -9, string, 0, 0, },
797 empty, OK, ER )
798 TMII_DONE
799 /* repeat with text "" */
800 TMII_INSMI( {, S, MIIM_BITMAP, -1 , -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
801 TMII_MODM( MFT_STRING, 545, empty, OK)
802 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
803 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_ID, MFT_STRING, -9, 545, 0, -9, -9, -9, string, 0, 0, },
804 empty, OK, ER )
805 TMII_DONE
806 /* start with bitmap: set ownerdraw */
807 TMII_INSMI( {, S, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
808 TMII_MODM( MFT_OWNERDRAW, -1, 232, OK)
809 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
810 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP|MIIM_DATA, MFT_OWNERDRAW, -9, -9, 0, -9, -9, 232, string, 0, hbm, },
811 empty, OK, ER )
812 TMII_DONE
813 /* ask nothing */
814 TMII_INSMI( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
815 TMII_GMII ( {, S, 0, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
816 {, S, 0, -9, -9, -9, 0, -9, -9, -9, string, 80, -9, },
817 init, OK, OK )
818 TMII_DONE
819 /* some tests with small cbSize: the hbmpItem is to be ignored */
820 TMII_INSMI( {, S - 4, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
821 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
822 {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, NULL, 0, NULL, },
823 empty, OK, ER )
824 TMII_DONE
825 TMII_INSMI( {, S - 4, MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm, }, OK)
826 TMII_GMII ( {, S, MIIM_BITMAP|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
827 {, S, MIIM_BITMAP|MIIM_FTYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, string, 80, NULL, },
828 init, OK, ER )
829 TMII_DONE
830 TMII_INSMI( {, S - 4, MIIM_STRING|MIIM_BITMAP, -1, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
831 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
832 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, NULL, },
833 txt, OK, OK )
834 TMII_DONE
835 TMII_INSMI( {, S - 4, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
836 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
837 {, S, MIIM_TYPE, MFT_SEPARATOR, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
838 txt, OK, OK )
839 TMII_DONE
840 TMII_INSMI( {, S - 4, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
841 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
842 {, S, MIIM_TYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
843 txt, OK, OK )
844 TMII_DONE
845 TMII_INSMI( {, S - 4, MIIM_FTYPE|MIIM_STRING|MIIM_BITMAP, MFT_SEPARATOR|MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, txt, 6, hbm, }, OK)
846 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
847 {, S, MIIM_TYPE, MFT_SEPARATOR|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, NULL, 4, NULL, },
848 txt, OK, OK )
849 TMII_DONE
850 /* MIIM_TYPE by itself does not get/set the dwItemData for OwnerDrawn menus */
851 TMII_INSMI( {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, 343, txt, 0, -1, }, OK)
852 TMII_GMII ( {, S, MIIM_TYPE|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
853 {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, 343, 0, 0, 0, },
854 empty, OK, ER )
855 TMII_DONE
856 TMII_INSMI( {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, 343, txt, 0, -1, }, OK)
857 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
858 {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
859 empty, OK, ER )
860 TMII_DONE
861 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING|MFT_OWNERDRAW, -1, -1, -1, -1, -1, 343, txt, 0, -1, }, OK)
862 TMII_GMII ( {, S, MIIM_TYPE|MIIM_DATA, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
863 {, S, MIIM_TYPE|MIIM_DATA, MFT_STRING|MFT_OWNERDRAW, -9, -9, 0, -9, -9, 0, 0, 0, 0, },
864 empty, OK, ER )
865 TMII_DONE
866 /* set a string menu to ownerdraw with MIIM_TYPE */
867 TMII_INSMI( {, S, MIIM_TYPE, MFT_STRING, -2, -2, -2, -2, -2, -2, txt, -2, -2, }, OK)
868 TMII_SMII( {, S, MIIM_TYPE, MFT_OWNERDRAW, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, OK)
869 TMII_GMII ( {, S, MIIM_STRING|MIIM_FTYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
870 {, S, MIIM_STRING|MIIM_FTYPE, MFT_OWNERDRAW, -9, -9, 0, -9, -9, -9, string, 4, -9, },
871 txt, OK, OK )
872 TMII_DONE
873 /* test with modifymenu add submenu */
874 TMII_INSMI( {, S, MIIM_STRING, MFT_STRING, -1, -1, -1, -1, -1, -1, txt, 0, -1, }, OK)
875 TMII_MODM( MF_POPUP, submenu, txt, OK)
876 TMII_GMII ( {, S, MIIM_FTYPE|MIIM_STRING|MIIM_SUBMENU, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
877 {, S, MIIM_FTYPE|MIIM_STRING|MIIM_SUBMENU, MFT_STRING, -9, -9, submenu, -9, -9, -9, string, 4, -9, },
878 txt, OK, OK )
879 TMII_GMII ( {, S, MIIM_TYPE, -9, -9, -9, -9, -9, -9, -9, string, 80, -9, },
880 {, S, MIIM_TYPE, MFT_STRING, -9, -9, 0, -9, -9, -9, string, 4, 0, },
881 txt, OK, OK )
882 TMII_DONE
884 ansi = !ansi;
885 } while( !ansi);
886 DeleteObject( hbm);
890 The following tests try to confirm the algorithum used to return the menu items
891 when there is a collision between a menu item and a popup menu
893 void test_menu_search_bycommand( void )
895 HMENU hmenu, hmenuSub, hmenuSub2;
896 MENUITEMINFO info;
897 BOOL rc;
898 UINT id;
899 char strback[0x80];
900 char strIn[0x80];
902 /* Case 1: Menu containing a menu item */
903 hmenu = CreateMenu();
905 memset( &info, 0, sizeof info );
906 info.cbSize = sizeof info;
907 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
908 info.fType = MFT_STRING;
909 strcpy(strIn, "Case 1 MenuItem");
910 info.dwTypeData = strIn;
911 info.wID = (UINT) 0x1234;
913 rc = InsertMenuItem(hmenu, 0, TRUE, &info );
914 ok (rc, "Inserting the menuitem failed\n");
916 id = GetMenuItemID(hmenu, 0);
917 ok (id == 0x1234, "Getting the menuitem id failed(gave %x)\n", id);
919 /* Confirm the menuitem was given the id supplied (getting by position) */
920 memset( &info, 0, sizeof info );
921 strback[0] = 0x00;
922 info.cbSize = sizeof(MENUITEMINFO);
923 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
924 info.dwTypeData = strback;
925 info.cch = sizeof(strback);
927 rc = GetMenuItemInfo(hmenu, 0, TRUE, &info); /* Get by position */
928 ok (rc, "Getting the menu items info failed\n");
929 ok (info.wID == 0x1234, "IDs differ for the menuitem\n");
930 ok (!strcmp(info.dwTypeData, "Case 1 MenuItem"), "Returned item has wrong label\n");
932 /* Search by id - Should return the item */
933 memset( &info, 0, sizeof info );
934 strback[0] = 0x00;
935 info.cbSize = sizeof(MENUITEMINFO);
936 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
937 info.dwTypeData = strback;
938 info.cch = sizeof(strback);
939 rc = GetMenuItemInfo(hmenu, 0x1234, FALSE, &info); /* Get by ID */
941 ok (rc, "Getting the menu items info failed\n");
942 ok (info.wID == 0x1234, "IDs differ for the menuitem\n");
943 ok (!strcmp(info.dwTypeData, "Case 1 MenuItem"), "Returned item has wrong label\n");
945 DestroyMenu( hmenu );
947 /* Case 2: Menu containing a popup menu */
948 hmenu = CreateMenu();
949 hmenuSub = CreateMenu();
951 strcpy(strIn, "Case 2 SubMenu");
952 rc = InsertMenu(hmenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub, strIn);
953 ok (rc, "Inserting the popup menu into the main menu failed\n");
955 id = GetMenuItemID(hmenu, 0);
956 ok (id == -1, "Getting the menuitem id unexpectedly worked (gave %x)\n", id);
958 /* Confirm the menuitem itself was given an id the same as the HMENU, (getting by position) */
959 memset( &info, 0, sizeof info );
960 strback[0] = 0x00;
961 info.cbSize = sizeof(MENUITEMINFO);
962 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
963 info.dwTypeData = strback;
964 info.cch = sizeof(strback);
965 info.wID = 0xdeadbeef;
967 rc = GetMenuItemInfo(hmenu, 0, TRUE, &info); /* Get by position */
968 ok (rc, "Getting the menu items info failed\n");
969 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the menuitem\n");
970 ok (!strcmp(info.dwTypeData, "Case 2 SubMenu"), "Returned item has wrong label\n");
972 /* Search by id - returns the popup menu itself */
973 memset( &info, 0, sizeof info );
974 strback[0] = 0x00;
975 info.cbSize = sizeof(MENUITEMINFO);
976 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
977 info.dwTypeData = strback;
978 info.cch = sizeof(strback);
979 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info); /* Get by ID */
981 ok (rc, "Getting the menu items info failed\n");
982 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the popup menu\n");
983 ok (!strcmp(info.dwTypeData, "Case 2 SubMenu"), "Returned item has wrong label\n");
986 Now add an item after it with the same id
988 memset( &info, 0, sizeof info );
989 info.cbSize = sizeof info;
990 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
991 info.fType = MFT_STRING;
992 strcpy(strIn, "Case 2 MenuItem 1");
993 info.dwTypeData = strIn;
994 info.wID = (UINT_PTR) hmenuSub;
995 rc = InsertMenuItem(hmenu, -1, TRUE, &info );
996 ok (rc, "Inserting the menuitem failed\n");
998 /* Search by id - returns the item which follows the popup menu */
999 memset( &info, 0, sizeof info );
1000 strback[0] = 0x00;
1001 info.cbSize = sizeof(MENUITEMINFO);
1002 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
1003 info.dwTypeData = strback;
1004 info.cch = sizeof(strback);
1005 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info); /* Get by ID */
1007 ok (rc, "Getting the menu items info failed\n");
1008 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the popup menu\n");
1009 ok (!strcmp(info.dwTypeData, "Case 2 MenuItem 1"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1012 Now add an item before the popup (with the same id)
1014 memset( &info, 0, sizeof info );
1015 info.cbSize = sizeof info;
1016 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1017 info.fType = MFT_STRING;
1018 strcpy(strIn, "Case 2 MenuItem 2");
1019 info.dwTypeData = strIn;
1020 info.wID = (UINT_PTR) hmenuSub;
1021 rc = InsertMenuItem(hmenu, 0, TRUE, &info );
1022 ok (rc, "Inserting the menuitem failed\n");
1024 /* Search by id - returns the item which preceeds the popup menu */
1025 memset( &info, 0, sizeof info );
1026 strback[0] = 0x00;
1027 info.cbSize = sizeof(MENUITEMINFO);
1028 info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING;
1029 info.dwTypeData = strback;
1030 info.cch = sizeof(strback);
1031 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info); /* Get by ID */
1033 ok (rc, "Getting the menu items info failed\n");
1034 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for the popup menu\n");
1035 ok (!strcmp(info.dwTypeData, "Case 2 MenuItem 2"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1037 DestroyMenu( hmenu );
1038 DestroyMenu( hmenuSub );
1041 Case 3: Menu containing a popup menu which in turn
1042 contains 2 items with the same id as the popup itself
1045 hmenu = CreateMenu();
1046 hmenuSub = CreateMenu();
1048 memset( &info, 0, sizeof info );
1049 info.cbSize = sizeof info;
1050 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1051 info.fType = MFT_STRING;
1052 info.dwTypeData = "MenuItem";
1053 info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
1055 rc = InsertMenu(hmenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub, "Submenu");
1056 ok (rc, "Inserting the popup menu into the main menu failed\n");
1058 rc = InsertMenuItem(hmenuSub, 0, TRUE, &info );
1059 ok (rc, "Inserting the sub menu menuitem failed\n");
1061 memset( &info, 0, sizeof info );
1062 info.cbSize = sizeof info;
1063 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1064 info.fType = MFT_STRING;
1065 info.dwTypeData = "MenuItem 2";
1066 info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
1068 rc = InsertMenuItem(hmenuSub, 1, TRUE, &info );
1069 ok (rc, "Inserting the sub menu menuitem 2 failed\n");
1071 /* Prove that you cant query the id of a popup directly (By position) */
1072 id = GetMenuItemID(hmenu, 0);
1073 ok (id == -1, "Getting the sub menu id should have failed because its a popup (gave %x)\n", id);
1075 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
1076 memset( &info, 0, sizeof info );
1077 strback[0] = 0x00;
1078 info.cbSize = sizeof(MENUITEMINFO);
1079 info.fMask = MIIM_STRING | MIIM_ID;
1080 info.dwTypeData = strback;
1081 info.cch = sizeof(strback);
1083 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info);
1084 ok (rc, "Getting the menus info failed\n");
1085 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for popup menu\n");
1086 ok (!strcmp(info.dwTypeData, "MenuItem"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1087 DestroyMenu( hmenu );
1088 DestroyMenu( hmenuSub );
1091 Case 4: Menu containing 2 popup menus, the second
1092 contains 2 items with the same id as the first popup menu
1094 hmenu = CreateMenu();
1095 hmenuSub = CreateMenu();
1096 hmenuSub2 = CreateMenu();
1098 rc = InsertMenu(hmenu, 0, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub, "Submenu");
1099 ok (rc, "Inserting the popup menu into the main menu failed\n");
1101 rc = InsertMenu(hmenu, 1, MF_BYPOSITION | MF_POPUP | MF_STRING, (UINT_PTR)hmenuSub2, "Submenu2");
1102 ok (rc, "Inserting the popup menu into the main menu failed\n");
1104 memset( &info, 0, sizeof info );
1105 info.cbSize = sizeof info;
1106 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1107 info.fType = MFT_STRING;
1108 info.dwTypeData = "MenuItem";
1109 info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
1111 rc = InsertMenuItem(hmenuSub2, 0, TRUE, &info );
1112 ok (rc, "Inserting the sub menu menuitem failed\n");
1114 memset( &info, 0, sizeof info );
1115 info.cbSize = sizeof info;
1116 info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_ID;
1117 info.fType = MFT_STRING;
1118 info.dwTypeData = "MenuItem 2";
1119 info.wID = (UINT_PTR) hmenuSub; /* Enforce id collisions with the hmenu of the popup submenu*/
1121 rc = InsertMenuItem(hmenuSub2, 1, TRUE, &info );
1122 ok (rc, "Inserting the sub menu menuitem 2 failed\n");
1124 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
1125 memset( &info, 0, sizeof info );
1126 strback[0] = 0x00;
1127 info.cbSize = sizeof(MENUITEMINFO);
1128 info.fMask = MIIM_STRING | MIIM_ID;
1129 info.dwTypeData = strback;
1130 info.cch = sizeof(strback);
1132 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub, FALSE, &info);
1133 ok (rc, "Getting the menus info failed\n");
1134 ok (info.wID == (UINT_PTR)hmenuSub, "IDs differ for popup menu\n");
1135 ok (!strcmp(info.dwTypeData, "MenuItem"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1137 memset( &info, 0, sizeof info );
1138 strback[0] = 0x00;
1139 info.cbSize = sizeof(MENUITEMINFO);
1140 info.fMask = MIIM_STRING | MIIM_ID;
1141 info.dwTypeData = strback;
1142 info.cch = sizeof(strback);
1144 rc = GetMenuItemInfo(hmenu, (UINT_PTR)hmenuSub2, FALSE, &info);
1145 ok (rc, "Getting the menus info failed\n");
1146 ok (info.wID == (UINT)hmenuSub2, "IDs differ for popup menu\n");
1147 ok (!strcmp(info.dwTypeData, "Submenu2"), "Returned item has wrong label (%s)\n", info.dwTypeData);
1150 START_TEST(menu)
1152 register_menu_check_class();
1154 test_menu_locked_by_window();
1155 test_menu_ownerdraw();
1156 test_menu_add_string();
1157 test_menu_iteminfo();
1158 test_menu_search_bycommand();