4 * Copyright 2005 Robert Shearman
5 * Copyright 2007 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define _WIN32_WINNT 0x0501
29 #define OEMRESOURCE /* For OBM_MNARROW */
36 #include "wine/test.h"
38 static ATOM atomMenuCheckClass
;
40 static BOOL (WINAPI
*pSetMenuInfo
)(HMENU
,LPCMENUINFO
);
41 static BOOL (WINAPI
*pGetMenuInfo
)(HMENU
,LPCMENUINFO
);
43 static LRESULT WINAPI
menu_check_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
47 case WM_ENTERMENULOOP
:
48 /* mark window as having entered menu loop */
49 SetWindowLongPtr(hwnd
, GWLP_USERDATA
, TRUE
);
50 /* exit menu modal loop
51 * ( A SendMessage does not work on NT3.51 here ) */
52 return PostMessage(hwnd
, WM_CANCELMODE
, 0, 0);
54 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
57 /* The MSVC headers ignore our NONAMELESSUNION requests so we have to define
70 /* globals to communicate between test and wndproc */
72 static BOOL bMenuVisible
;
73 static HMENU hMenus
[4];
78 /* menu texts with their sizes */
81 SIZE size
; /* size of text up to any \t */
82 SIZE sc_size
; /* size of the short-cut */
91 static unsigned int MOD_maxid
;
92 static RECT MOD_rc
[MOD_NRMENUS
];
93 static int MOD_avec
, MOD_hic
;
94 static int MOD_odheight
;
95 static SIZE MODsizes
[MOD_NRMENUS
]= { {MOD_SIZE
, MOD_SIZE
},{MOD_SIZE
, MOD_SIZE
},
96 {MOD_SIZE
, MOD_SIZE
},{MOD_SIZE
, MOD_SIZE
}};
97 static int MOD_GotDrawItemMsg
= FALSE
;
98 /* wndproc used by test_menu_ownerdraw() */
99 static LRESULT WINAPI
menu_ownerdraw_wnd_proc(HWND hwnd
, UINT msg
,
100 WPARAM wparam
, LPARAM lparam
)
106 MEASUREITEMSTRUCT
* pmis
= (MEASUREITEMSTRUCT
*)lparam
;
108 trace("WM_MEASUREITEM received data %lx size %dx%d\n",
109 pmis
->itemData
, pmis
->itemWidth
, pmis
->itemHeight
);
110 MOD_odheight
= pmis
->itemHeight
;
111 pmis
->itemWidth
= MODsizes
[pmis
->itemData
].cx
;
112 pmis
->itemHeight
= MODsizes
[pmis
->itemData
].cy
;
117 DRAWITEMSTRUCT
* pdis
;
120 char chrs
[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
123 pdis
= (DRAWITEMSTRUCT
*) lparam
;
124 if( winetest_debug
) {
126 GetMenuItemRect( hwnd
, (HMENU
)pdis
->hwndItem
, pdis
->itemData
,&rc
);
127 trace("WM_DRAWITEM received hwnd %p hmenu %p itemdata %ld item %d rc %d,%d-%d,%d itemrc: %d,%d-%d,%d\n",
128 hwnd
, (HMENU
)pdis
->hwndItem
, pdis
->itemData
,
129 pdis
->itemID
, pdis
->rcItem
.left
, pdis
->rcItem
.top
,
130 pdis
->rcItem
.right
,pdis
->rcItem
.bottom
,
131 rc
.left
,rc
.top
,rc
.right
,rc
.bottom
);
132 oldpen
=SelectObject( pdis
->hDC
, GetStockObject(
133 pdis
->itemState
& ODS_SELECTED
? WHITE_PEN
:BLACK_PEN
));
134 Rectangle( pdis
->hDC
, pdis
->rcItem
.left
,pdis
->rcItem
.top
,
135 pdis
->rcItem
.right
,pdis
->rcItem
.bottom
);
136 SelectObject( pdis
->hDC
, oldpen
);
138 /* calculate widths of some menu texts */
139 if( ! MOD_txtsizes
[0].size
.cx
)
140 for(i
= 0; MOD_txtsizes
[i
].text
; i
++) {
143 strcpy( buf
, MOD_txtsizes
[i
].text
);
144 if( ( p
= strchr( buf
, '\t'))) {
146 DrawText( pdis
->hDC
, p
+ 1, -1, &rc
,
147 DT_SINGLELINE
|DT_CALCRECT
);
148 MOD_txtsizes
[i
].sc_size
.cx
= rc
.right
- rc
.left
;
149 MOD_txtsizes
[i
].sc_size
.cy
= rc
.bottom
- rc
.top
;
151 DrawText( pdis
->hDC
, buf
, -1, &rc
,
152 DT_SINGLELINE
|DT_CALCRECT
);
153 MOD_txtsizes
[i
].size
.cx
= rc
.right
- rc
.left
;
154 MOD_txtsizes
[i
].size
.cy
= rc
.bottom
- rc
.top
;
157 if( pdis
->itemData
> MOD_maxid
) return TRUE
;
158 /* store the rectangl */
159 MOD_rc
[pdis
->itemData
] = pdis
->rcItem
;
160 /* calculate average character width */
161 GetTextExtentPoint( pdis
->hDC
, chrs
, 52, &sz
);
162 MOD_avec
= (sz
.cx
+ 26)/52;
163 GetTextMetrics( pdis
->hDC
, &tm
);
164 MOD_hic
= tm
.tmHeight
;
165 MOD_GotDrawItemMsg
= TRUE
;
170 PostMessage(hwnd
, WM_CANCELMODE
, 0, 0);
175 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
178 static void register_menu_check_class(void)
186 GetModuleHandle(NULL
),
188 LoadCursor(NULL
, IDC_ARROW
),
189 (HBRUSH
)(COLOR_BTNFACE
+1),
191 TEXT("WineMenuCheck"),
194 atomMenuCheckClass
= RegisterClass(&wc
);
197 /* demonstrates that windows locks the menu object so that it is still valid
198 * even after a client calls DestroyMenu on it */
199 static void test_menu_locked_by_window(void)
203 HWND hwnd
= CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass
), NULL
,
204 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
205 NULL
, NULL
, NULL
, NULL
);
206 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
207 hmenu
= CreateMenu();
208 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
209 ret
= InsertMenu(hmenu
, 0, MF_STRING
, 0, TEXT("&Test"));
210 ok(ret
, "InsertMenu failed with error %d\n", GetLastError());
211 ret
= SetMenu(hwnd
, hmenu
);
212 ok(ret
, "SetMenu failed with error %d\n", GetLastError());
213 ret
= DestroyMenu(hmenu
);
214 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
216 ret
= DrawMenuBar(hwnd
);
218 ok(ret
, "DrawMenuBar failed with error %d\n", GetLastError());
220 ret
= IsMenu(GetMenu(hwnd
));
221 ok(!ret
, "Menu handle should have been destroyed\n");
223 SendMessage(hwnd
, WM_SYSCOMMAND
, SC_KEYMENU
, 0);
224 /* did we process the WM_INITMENU message? */
225 ret
= GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
227 ok(ret
, "WM_INITMENU should have been sent\n");
233 static void test_menu_ownerdraw(void)
239 HWND hwnd
= CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass
), NULL
,
240 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
241 NULL
, NULL
, NULL
, NULL
);
242 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
244 SetWindowLongPtr( hwnd
, GWLP_WNDPROC
, (LONG
)menu_ownerdraw_wnd_proc
);
245 hmenu
= CreatePopupMenu();
246 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
247 if( !hmenu
) { DestroyWindow(hwnd
);return;}
249 for( j
=0;j
<2;j
++) /* create columns */
250 for(i
=0;i
<2;i
++) { /* create rows */
251 ret
= AppendMenu( hmenu
, MF_OWNERDRAW
|
252 (i
==0 ? MF_MENUBREAK
: 0), k
, (LPCTSTR
) k
);
254 ok( ret
, "AppendMenu failed for %d\n", k
-1);
257 assert( k
<= sizeof(MOD_rc
)/sizeof(RECT
));
258 /* display the menu */
259 ret
= TrackPopupMenu( hmenu
, 0x100, 100,100, 0, hwnd
, NULL
);
261 /* columns have a 4 pixel gap between them */
262 ok( MOD_rc
[0].right
+ 4 == MOD_rc
[2].left
,
263 "item rectangles are not separated by 4 pixels space\n");
264 /* height should be what the MEASUREITEM message has returned */
265 ok( MOD_rc
[0].bottom
- MOD_rc
[0].top
== MOD_SIZE
,
266 "menu item has wrong height: %d should be %d\n",
267 MOD_rc
[0].bottom
- MOD_rc
[0].top
, MOD_SIZE
);
268 /* no gaps between the rows */
269 ok( MOD_rc
[0].bottom
- MOD_rc
[1].top
== 0,
270 "There should not be a space between the rows, gap is %d\n",
271 MOD_rc
[0].bottom
- MOD_rc
[1].top
);
272 /* test the correct value of the item height that was sent
273 * by the WM_MEASUREITEM message */
274 ok( MOD_odheight
== HIWORD( GetDialogBaseUnits()) || /* WinNT,2k,XP */
275 MOD_odheight
== MOD_hic
, /* Win95,98,ME */
276 "Wrong height field in MEASUREITEMSTRUCT, expected %d or %d actual %d\n",
277 HIWORD( GetDialogBaseUnits()), MOD_hic
, MOD_odheight
);
278 /* test what MF_MENUBREAK did at the first position. Also show
279 * that an MF_SEPARATOR is ignored in the height calculation. */
280 leftcol
= MOD_rc
[0].left
;
281 ModifyMenu( hmenu
, 0, MF_BYCOMMAND
| MF_OWNERDRAW
| MF_SEPARATOR
, 0, 0);
282 /* display the menu */
283 ret
= TrackPopupMenu( hmenu
, 0x100, 100,100, 0, hwnd
, NULL
);
284 /* left should be 4 pixels less now */
285 ok( leftcol
== MOD_rc
[0].left
+ 4,
286 "columns should be 4 pixels to the left (actual %d).\n",
287 leftcol
- MOD_rc
[0].left
);
289 ok( MOD_rc
[0].right
- MOD_rc
[0].left
== 2 * MOD_avec
+ MOD_SIZE
,
290 "width of owner drawn menu item is wrong. Got %d expected %d\n",
291 MOD_rc
[0].right
- MOD_rc
[0].left
, 2*MOD_avec
+ MOD_SIZE
);
293 ok( MOD_rc
[0].bottom
- MOD_rc
[0].top
== MOD_SIZE
,
294 "Height is incorrect. Got %d expected %d\n",
295 MOD_rc
[0].bottom
- MOD_rc
[0].top
, MOD_SIZE
);
297 /* test width/height of an ownerdraw menu bar as well */
298 ret
= DestroyMenu(hmenu
);
299 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
300 hmenu
= CreateMenu();
301 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
302 if( !hmenu
) { DestroyWindow(hwnd
);return;}
305 ret
= AppendMenu( hmenu
, MF_OWNERDRAW
, i
, 0);
306 ok( ret
, "AppendMenu failed for %d\n", i
);
308 ret
= SetMenu( hwnd
, hmenu
);
309 UpdateWindow( hwnd
); /* hack for wine to draw the window + menu */
310 ok(ret
, "SetMenu failed with error %d\n", GetLastError());
312 ok( MOD_rc
[0].right
- MOD_rc
[0].left
== 2 * MOD_avec
+ MOD_SIZE
,
313 "width of owner drawn menu item is wrong. Got %d expected %d\n",
314 MOD_rc
[0].right
- MOD_rc
[0].left
, 2*MOD_avec
+ MOD_SIZE
);
316 ok( MOD_rc
[0].bottom
- MOD_rc
[0].top
== GetSystemMetrics( SM_CYMENU
) - 1,
317 "Height of owner drawn menu item is wrong. Got %d expected %d\n",
318 MOD_rc
[0].bottom
- MOD_rc
[0].top
, GetSystemMetrics( SM_CYMENU
) - 1);
321 ret
= DestroyMenu(hmenu
);
322 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
326 /* helper for test_menu_bmp_and_string() */
327 static void test_mbs_help( int ispop
, int hassub
, int mnuopt
,
328 HWND hwnd
, int arrowwidth
, int count
, HBITMAP hbmp
,
329 SIZE bmpsize
, LPCSTR text
, SIZE size
, SIZE sc_size
)
332 HMENU hmenu
, submenu
;
333 MENUITEMINFO mii
={ sizeof( MENUITEMINFO
)};
340 MOD_GotDrawItemMsg
= FALSE
;
341 mii
.fMask
= MIIM_FTYPE
| MIIM_DATA
| MIIM_STATE
;
343 mii
.fState
= MF_CHECKED
;
345 MODsizes
[0] = bmpsize
;
349 mii
.fMask
|= MIIM_STRING
;
350 strcpy(text_copy
, text
);
351 mii
.dwTypeData
= text_copy
; /* structure member declared non-const */
352 if( ( p
= strchr( text
, '\t'))) {
353 hastab
= *(p
+ 1) ? 2 : 1;
356 /* tabs don't make sense in menubars */
357 if(hastab
&& !ispop
) return;
359 mii
.fMask
|= MIIM_BITMAP
;
362 submenu
= CreateMenu();
363 ok( submenu
!= 0, "CreateMenu failed with error %d\n", GetLastError());
365 hmenu
= CreatePopupMenu();
367 hmenu
= CreateMenu();
368 ok( hmenu
!= 0, "Create{Popup}Menu failed with error %d\n", GetLastError());
370 mii
.fMask
|= MIIM_SUBMENU
;
371 mii
.hSubMenu
= submenu
;
374 mi
.cbSize
= sizeof(mi
);
375 mi
.fMask
= MIM_STYLE
;
376 pGetMenuInfo( hmenu
, &mi
);
377 mi
.dwStyle
|= mnuopt
== 1 ? MNS_NOCHECK
: MNS_CHECKORBMP
;
378 ret
= pSetMenuInfo( hmenu
, &mi
);
379 ok( ret
, "SetMenuInfo failed with error %d\n", GetLastError());
381 ret
= InsertMenuItem( hmenu
, 0, FALSE
, &mii
);
382 ok( ret
, "InsertMenuItem failed with error %d\n", GetLastError());
384 if( winetest_debug
) {
386 RECT rc
= {100, 50, 400, 70};
389 sprintf( buf
,"%d text \"%s\" mnuopt %d", count
, text
? text
: "(nil)", mnuopt
);
390 FillRect( hdc
, &rc
, (HBRUSH
) COLOR_WINDOW
);
391 TextOut( hdc
, 100, 50, buf
, strlen( buf
));
392 ReleaseDC( hwnd
, hdc
);
395 ret
= TrackPopupMenu( hmenu
, 0x100, 100,100, 0, hwnd
, NULL
);
397 ret
= SetMenu( hwnd
, hmenu
);
398 ok(ret
, "SetMenu failed with error %d\n", GetLastError());
401 ret
= GetMenuItemRect( hwnd
, hmenu
, 0, &rc
);
402 /* check menu width */
404 expect
= ( text
|| hbmp
?
405 4 + (mnuopt
!= 1 ? GetSystemMetrics(SM_CXMENUCHECK
) : 0)
407 arrowwidth
+ MOD_avec
+ (hbmp
? bmpsize
.cx
+ 2 : 0) +
408 (text
&& hastab
? /* TAB space */
409 MOD_avec
+ ( hastab
==2 ? sc_size
.cx
: 0) : 0) +
410 (text
? 2 + (text
[0] ? size
.cx
:0): 0) ;
412 expect
= !(text
|| hbmp
) ? 0 :
413 ( hbmp
? (text
? 2:0) + bmpsize
.cx
: 0 ) +
414 (text
? 2 * MOD_avec
+ (text
[0] ? size
.cx
:0): 0) ;
415 ok( rc
.right
- rc
.left
== expect
,
416 "menu width wrong, got %d expected %d\n", rc
.right
- rc
.left
, expect
);
417 failed
= failed
|| !(rc
.right
- rc
.left
== expect
);
418 /* check menu height */
420 expect
= max( ( !(text
|| hbmp
) ? GetSystemMetrics( SM_CYMENUSIZE
)/2 : 0),
421 max( (text
? max( 2 + size
.cy
, MOD_hic
+ 4) : 0),
422 (hbmp
? bmpsize
.cy
+ 2 : 0)));
424 expect
= ( !(text
|| hbmp
) ? GetSystemMetrics( SM_CYMENUSIZE
)/2 :
425 max( GetSystemMetrics( SM_CYMENU
) - 1, (hbmp
? bmpsize
.cy
: 0)));
426 ok( rc
.bottom
- rc
.top
== expect
,
427 "menu height wrong, got %d expected %d (%d)\n",
428 rc
.bottom
- rc
.top
, expect
, GetSystemMetrics( SM_CYMENU
));
429 failed
= failed
|| !(rc
.bottom
- rc
.top
== expect
);
430 if( hbmp
== HBMMENU_CALLBACK
&& MOD_GotDrawItemMsg
) {
431 /* check the position of the bitmap */
433 expect
= ispop
? (4 + ( mnuopt
? 0 : GetSystemMetrics(SM_CXMENUCHECK
)))
435 ok( expect
== MOD_rc
[0].left
,
436 "bitmap left is %d expected %d\n", MOD_rc
[0].left
, expect
);
437 failed
= failed
|| !(expect
== MOD_rc
[0].left
);
439 expect
= (rc
.bottom
- rc
.top
- MOD_rc
[0].bottom
+ MOD_rc
[0].top
) / 2;
440 ok( expect
== MOD_rc
[0].top
,
441 "bitmap top is %d expected %d\n", MOD_rc
[0].top
, expect
);
442 failed
= failed
|| !(expect
== MOD_rc
[0].top
);
444 /* if there was a failure, report details */
446 trace("*** count %d text \"%s\" bitmap %p bmsize %d,%d textsize %d+%d,%d mnuopt %d hastab %d\n",
447 count
, text
? text
: "(nil)", hbmp
, bmpsize
.cx
, bmpsize
.cy
,
448 size
.cx
, size
.cy
, sc_size
.cx
, mnuopt
, hastab
);
449 trace(" check %d,%d arrow %d avechar %d\n",
450 GetSystemMetrics(SM_CXMENUCHECK
),
451 GetSystemMetrics(SM_CYMENUCHECK
),arrowwidth
, MOD_avec
);
452 if( hbmp
== HBMMENU_CALLBACK
)
453 trace( " rc %d,%d-%d,%d bmp.rc %d,%d-%d,%d\n",
454 rc
.left
, rc
.top
, rc
.top
, rc
.bottom
, MOD_rc
[0].left
,
455 MOD_rc
[0].top
,MOD_rc
[0].right
, MOD_rc
[0].bottom
);
458 ret
= DestroyMenu(submenu
);
459 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
460 ret
= DestroyMenu(hmenu
);
461 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
465 static void test_menu_bmp_and_string(void)
472 int count
, szidx
, txtidx
, bmpidx
, hassub
, mnuopt
, ispop
;
474 if( !pGetMenuInfo
) return;
476 memset( bmfill
, 0x55, sizeof( bmfill
));
477 hwnd
= CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass
), NULL
,
478 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
479 NULL
, NULL
, NULL
, NULL
);
480 hbm_arrow
=LoadBitmap( 0, (CHAR
*)OBM_MNARROW
);
481 GetObject( hbm_arrow
, sizeof(bm
), &bm
);
482 arrowwidth
= bm
.bmWidth
;
484 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
486 SetWindowLongPtr( hwnd
, GWLP_WNDPROC
, (LONG
)menu_ownerdraw_wnd_proc
);
489 trace(" check %d,%d arrow %d avechar %d\n",
490 GetSystemMetrics(SM_CXMENUCHECK
),
491 GetSystemMetrics(SM_CYMENUCHECK
),arrowwidth
, MOD_avec
);
494 for( ispop
=1; ispop
>= 0; ispop
--){
495 static SIZE bmsizes
[]= {
496 {10,10},{38,38},{1,30},{55,5}};
497 for( szidx
=0; szidx
< sizeof( bmsizes
) / sizeof( SIZE
); szidx
++) {
498 HBITMAP hbm
= CreateBitmap( bmsizes
[szidx
].cx
, bmsizes
[szidx
].cy
,1,1,bmfill
);
499 HBITMAP bitmaps
[] = { HBMMENU_CALLBACK
, hbm
, NULL
};
500 ok( (int)hbm
, "CreateBitmap failed err %d\n", GetLastError());
501 for( txtidx
= 0; txtidx
< sizeof(MOD_txtsizes
)/sizeof(MOD_txtsizes
[0]); txtidx
++) {
502 for( hassub
= 0; hassub
< 2 ; hassub
++) { /* add submenu item */
503 for( mnuopt
= 0; mnuopt
< 3 ; mnuopt
++){ /* test MNS_NOCHECK/MNS_CHECKORBMP */
504 for( bmpidx
= 0; bmpidx
<sizeof(bitmaps
)/sizeof(HBITMAP
); bmpidx
++) {
505 /* no need to test NULL bitmaps of several sizes */
506 if( !bitmaps
[bmpidx
] && szidx
> 0) continue;
507 if( !ispop
&& hassub
) continue;
508 test_mbs_help( ispop
, hassub
, mnuopt
,
509 hwnd
, arrowwidth
, ++count
,
512 MOD_txtsizes
[txtidx
].text
,
513 MOD_txtsizes
[txtidx
].size
,
514 MOD_txtsizes
[txtidx
].sc_size
);
526 static void test_menu_add_string( void )
537 WCHAR strbackW
[0x80];
538 static CHAR blah
[] = "blah";
539 static const WCHAR expectedString
[] = {'D','u','m','m','y',' ','s','t','r','i','n','g', 0};
541 hmenu
= CreateMenu();
543 memset( &info
, 0, sizeof info
);
544 info
.cbSize
= sizeof info
;
545 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_ID
;
546 info
.dwTypeData
= blah
;
551 InsertMenuItem(hmenu
, 0, TRUE
, &info
);
553 memset( &info
, 0, sizeof info
);
554 info
.cbSize
= sizeof info
;
555 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_DATA
| MIIM_ID
;
556 info
.dwTypeData
= string
;
557 info
.cch
= sizeof string
;
559 GetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
561 ok( !strcmp( string
, "blah" ), "menu item name differed\n");
563 /* Test combination of ownerdraw and strings with GetMenuItemString(A/W) */
564 strcpy(string
, "Dummy string");
565 memset(&info
, 0x00, sizeof(info
));
566 info
.cbSize
= sizeof(MENUITEMINFO
);
567 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
; /* Set OwnerDraw + typeData */
568 info
.fType
= MFT_OWNERDRAW
;
569 info
.dwTypeData
= string
;
570 rc
= InsertMenuItem( hmenu
, 0, TRUE
, &info
);
571 ok (rc
, "InsertMenuItem failed\n");
573 strcpy(string
,"Garbage");
574 ok (GetMenuString( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
575 ok (!strcmp( strback
, "Dummy string" ), "Menu text from Ansi version incorrect\n");
577 SetLastError(0xdeadbeef);
578 ret
= GetMenuStringW( hmenu
, 0, (WCHAR
*)strbackW
, 99, MF_BYPOSITION
);
579 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
580 skip("GetMenuStringW is not implemented\n");
583 ok (ret
, "GetMenuStringW on ownerdraw entry failed\n");
584 ok (!lstrcmpW( strbackW
, expectedString
), "Menu text from Unicode version incorrect\n");
587 /* Just change ftype to string and see what text is stored */
588 memset(&info
, 0x00, sizeof(info
));
589 info
.cbSize
= sizeof(MENUITEMINFO
);
590 info
.fMask
= MIIM_FTYPE
; /* Set string type */
591 info
.fType
= MFT_STRING
;
592 info
.dwTypeData
= (char *)0xdeadbeef;
593 rc
= SetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
594 ok (rc
, "SetMenuItemInfo failed\n");
596 /* Did we keep the old dwTypeData? */
597 ok (GetMenuString( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
598 ok (!strcmp( strback
, "Dummy string" ), "Menu text from Ansi version incorrect\n");
600 /* Ensure change to bitmap type fails */
601 memset(&info
, 0x00, sizeof(info
));
602 info
.cbSize
= sizeof(MENUITEMINFO
);
603 info
.fMask
= MIIM_FTYPE
; /* Set as bitmap type */
604 info
.fType
= MFT_BITMAP
;
605 info
.dwTypeData
= (char *)0xdeadbee2;
606 rc
= SetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
607 ok (!rc
, "SetMenuItemInfo unexpectedly worked\n");
609 /* Just change ftype back and ensure data hasn't been freed */
610 info
.fType
= MFT_OWNERDRAW
; /* Set as ownerdraw type */
611 info
.dwTypeData
= (char *)0xdeadbee3;
612 rc
= SetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
613 ok (rc
, "SetMenuItemInfo failed\n");
615 /* Did we keep the old dwTypeData? */
616 ok (GetMenuString( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
617 ok (!strcmp( strback
, "Dummy string" ), "Menu text from Ansi version incorrect\n");
619 /* Just change string value (not type) */
620 memset(&info
, 0x00, sizeof(info
));
621 info
.cbSize
= sizeof(MENUITEMINFO
);
622 info
.fMask
= MIIM_STRING
; /* Set typeData */
623 strcpy(string2
, "string2");
624 info
.dwTypeData
= string2
;
625 rc
= SetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
626 ok (rc
, "SetMenuItemInfo failed\n");
628 ok (GetMenuString( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
629 ok (!strcmp( strback
, "string2" ), "Menu text from Ansi version incorrect\n");
631 /* crashes with wine 0.9.5 */
632 memset(&info
, 0x00, sizeof(info
));
633 info
.cbSize
= sizeof(MENUITEMINFO
);
634 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
; /* Set OwnerDraw + typeData */
635 info
.fType
= MFT_OWNERDRAW
;
636 rc
= InsertMenuItem( hmenu
, 0, TRUE
, &info
);
637 ok (rc
, "InsertMenuItem failed\n");
638 ok (!GetMenuString( hmenu
, 0, NULL
, 0, MF_BYPOSITION
),
639 "GetMenuString on ownerdraw entry succeeded.\n");
640 SetLastError(0xdeadbeef);
641 ret
= GetMenuStringW( hmenu
, 0, NULL
, 0, MF_BYPOSITION
);
642 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
643 skip("GetMenuStringW is not implemented\n");
645 ok (!ret
, "GetMenuStringW on ownerdraw entry succeeded.\n");
647 DestroyMenu( hmenu
);
650 /* define building blocks for the menu item info tests */
651 static int strncmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
653 if (n
<= 0) return 0;
654 while ((--n
> 0) && *str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
655 return *str1
- *str2
;
658 static WCHAR
*strcpyW( WCHAR
*dst
, const WCHAR
*src
)
661 while ((*p
++ = *src
++));
666 #define DMIINFF( i, e, field)\
667 ok((int)((i)->field)==(int)((e)->field) || (int)((i)->field)==(0xffff & (int)((e)->field)), \
668 "%s got 0x%x expected 0x%x\n", #field, (int)((i)->field), (int)((e)->field));
670 #define DUMPMIINF(s,i,e)\
672 DMIINFF( i, e, fMask)\
673 DMIINFF( i, e, fType)\
674 DMIINFF( i, e, fState)\
676 DMIINFF( i, e, hSubMenu)\
677 DMIINFF( i, e, hbmpChecked)\
678 DMIINFF( i, e, hbmpUnchecked)\
679 DMIINFF( i, e, dwItemData)\
680 DMIINFF( i, e, dwTypeData)\
682 if( s==sizeof(MENUITEMINFOA)) DMIINFF( i, e, hbmpItem)\
685 /* insert menu item */
686 #define TMII_INSMI( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
689 MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
690 HMENU hmenu = CreateMenu();\
691 BOOL ret, stop = FALSE;\
692 SetLastError( 0xdeadbeef);\
693 if(ansi)strcpy( string, init);\
694 else strcpyW( (WCHAR*)string, (WCHAR*)init);\
695 if( ansi) ret = InsertMenuItemA(hmenu, 0, TRUE, &info1 );\
696 else ret = InsertMenuItemW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
697 if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)\
699 skip("InsertMenuItem%s not implemented\n", ansi ? "A" : "W");\
702 if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
704 } else ok( (eret1)==ret,"InsertMenuItem failed, err %d\n",GetLastError());\
707 /* GetMenuItemInfo + GetMenuString */
708 #define TMII_GMII( a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,\
709 a3,b3,c3,d3,e3,f3,g3,h3,i3,j3,k3,l3,m3,n3,\
710 expname, eret2, eret3)\
712 MENUITEMINFOA info2A=a2 b2,c2,d2,e2,f2,(void*)g2,(void*)h2,(void*)i2,j2,(void*)k2,l2,(void*)m2 n2;\
713 MENUITEMINFOA einfoA=a3 b3,c3,d3,e3,f3,(void*)g3,(void*)h3,(void*)i3,j3,(void*)k3,l3,(void*)m3 n3;\
714 MENUITEMINFOA *info2 = &info2A;\
715 MENUITEMINFOA *einfo = &einfoA;\
716 MENUITEMINFOW *info2W = (MENUITEMINFOW *)&info2A;\
718 SetLastError( 0xdeadbeef);\
719 ret = ansi ? GetMenuItemInfoA( hmenu, 0, TRUE, info2 ) :\
720 GetMenuItemInfoW( hmenu, 0, TRUE, info2W );\
721 if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)\
723 skip("GetMenuItemInfo%s not implemented\n", ansi ? "A" : "W");\
726 if( !(eret2)) ok( (eret2)==ret,"GetMenuItemInfo should have failed.\n");\
728 ok( (eret2)==ret,"GetMenuItemInfo failed, err %d\n",GetLastError());\
729 ret = memcmp( info2, einfo, sizeof einfoA);\
730 /* ok( ret==0, "Got wrong menu item info data\n");*/\
731 if( ret) DUMPMIINF(info2A.cbSize, &info2A, &einfoA)\
732 if( einfo->dwTypeData == string) {\
733 if(ansi) ok( !strncmp( expname, info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
734 einfo->dwTypeData ? einfo->dwTypeData: "");\
735 else ok( !strncmpW( (WCHAR*)expname, (WCHAR*)info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
736 einfo->dwTypeData ? einfo->dwTypeData: "");\
737 ret = ansi ? GetMenuStringA( hmenu, 0, string, 80, MF_BYPOSITION) :\
738 GetMenuStringW( hmenu, 0, string, 80, MF_BYPOSITION);\
740 ok( ret, "GetMenuString failed, err %d\n",GetLastError());\
742 ok( !ret, "GetMenuString should have failed\n");\
749 RemoveMenu(hmenu, 0, TRUE );\
750 DestroyMenu( hmenu );\
751 DestroyMenu( submenu );\
752 submenu = CreateMenu();\
755 #define TMII_MODM( flags, id, data, eret )\
757 SetLastError( 0xdeadbeef);\
758 if(ansi)ret = ModifyMenuA( hmenu, 0, flags, (UINT_PTR)id, (char*)data);\
759 else ret = ModifyMenuW( hmenu, 0, flags, (UINT_PTR)id, (WCHAR*)data);\
760 if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)\
762 skip("ModifyMenu%s not implemented\n", ansi ? "A" : "W");\
765 if( !(eret)) ok( (eret)==ret,"ModifyMenuA should have failed.\n");\
766 else ok( (eret)==ret,"ModifyMenuA failed, err %d\n",GetLastError());\
769 /* SetMenuItemInfo */
770 #define TMII_SMII( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
773 MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
774 SetLastError( 0xdeadbeef);\
775 if(ansi)strcpy( string, init);\
776 else strcpyW( (WCHAR*)string, (WCHAR*)init);\
777 if( ansi) ret = SetMenuItemInfoA(hmenu, 0, TRUE, &info1 );\
778 else ret = SetMenuItemInfoW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
779 if( GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)\
781 skip("SetMenuItemInfo%s not implemented\n", ansi ? "A" : "W");\
784 if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
786 } else ok( (eret1)==ret,"InsertMenuItem failed, err %d\n",GetLastError());\
795 static void test_menu_iteminfo( void )
797 int S
=sizeof( MENUITEMINFOA
);
802 WCHAR txtW
[]={'W','i','n','e',0};
803 WCHAR initW
[]={'X','Y','Z',0};
805 void *txt
, *init
, *empty
, *string
;
806 HBITMAP hbm
= CreateBitmap(1,1,1,1,NULL
);
808 HMENU submenu
=CreateMenu();
811 if( ansi
) {txt
=txtA
;init
=initA
;empty
=emptyA
;string
=stringA
;}
812 else {txt
=txtW
;init
=initW
;empty
=emptyW
;string
=stringA
;}
813 trace( "%s string %p hbm %p txt %p\n", ansi
? "ANSI tests: " : "Unicode tests:", string
, hbm
, txt
);
814 /* test all combinations of MFT_STRING, MFT_OWNERDRAW and MFT_BITMAP */
815 /* (since MFT_STRING is zero, there are four of them) */
816 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, 0, 0, 0, 0, 0, 0, txt
, 0, 0, }, OK
)
817 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
818 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, 0, },
821 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
822 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
823 {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
826 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, 6, -1, }, OK
)
827 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
828 {, S
, MIIM_TYPE
, MFT_BITMAP
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
831 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, hbm
, 6, -1, }, OK
)
832 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
833 {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
836 /* not enough space for name*/
837 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
838 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, NULL
, 0, -9, },
839 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, NULL
, 4, 0, },
842 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
843 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 5, -9, },
844 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, 0, },
847 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
848 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 4, -9, },
849 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 3, 0, },
852 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
853 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, NULL
, 0, -9, },
854 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 0, 0, },
857 /* cannot combine MIIM_TYPE with some other flags */
858 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_STRING
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, ER
)
859 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
860 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
863 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
864 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_STRING
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
865 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
868 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_FTYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, ER
)
869 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
870 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
873 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
874 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
875 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
878 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_BITMAP
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, 6, hbm
, }, ER
)
879 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
880 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
883 /* but succeeds with some others */
884 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
885 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_SUBMENU
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
886 {, S
, MIIM_TYPE
|MIIM_SUBMENU
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, 0, },
889 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
890 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_STATE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
891 {, S
, MIIM_TYPE
|MIIM_STATE
, MFT_STRING
, 0, -9, 0, -9, -9, -9, string
, 4, 0, },
894 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_ID
, MFT_STRING
, -1, 888, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
895 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
896 {, S
, MIIM_TYPE
|MIIM_ID
, MFT_STRING
, -9, 888, 0, -9, -9, -9, string
, 4, 0, },
899 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
, -1, -1, -1, -1, -1, 999, txt
, 6, -1, }, OK
)
900 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
901 {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
, -9, -9, 0, -9, -9, 999, string
, 4, 0, },
904 /* to be continued */
905 /* set text with MIIM_TYPE and retrieve with MIIM_STRING */
906 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
907 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
908 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, -9, },
911 /* set text with MIIM_TYPE and retrieve with MIIM_STRING; MFT_OWNERDRAW causes an empty string */
912 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
913 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
914 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
917 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
918 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
919 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
922 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
923 TMII_GMII ( {, S
, MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
924 {, S
, MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 80, -9, },
927 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
928 TMII_GMII ( {, S
, 0, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
929 {, S
, 0, -9, -9, -9, 0, -9, -9, -9, string
, 80, -9, },
932 /* contrary to MIIM_TYPE,you can set the text for an owner draw menu */
933 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
934 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
935 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 4, -9, },
938 /* same but retrieve with MIIM_TYPE */
939 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
940 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
941 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
944 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
945 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
946 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
949 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
950 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
951 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
955 /* How is that with bitmaps? */
956 TMII_INSMI( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
957 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
958 {, S
, MIIM_TYPE
, MFT_BITMAP
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
961 TMII_INSMI( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
962 TMII_GMII ( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
963 {, S
, MIIM_BITMAP
|MIIM_FTYPE
, 0, -9, -9, 0, -9, -9, -9, string
, 80, hbm
, },
966 /* MIIM_BITMAP does not like MFT_BITMAP */
967 TMII_INSMI( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, ER
)
968 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
969 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
972 /* no problem with OWNERDRAWN */
973 TMII_INSMI( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
974 TMII_GMII ( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
975 {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 80, hbm
, },
978 /* setting MFT_BITMAP with MFT_FTYPE fails anyway */
979 TMII_INSMI( {, S
, MIIM_FTYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, ER
)
980 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
981 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
985 /* menu with submenu */
986 TMII_INSMI( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, submenu
, -1, -1, -1, txt
, 0, -1, }, OK
)
987 TMII_GMII ( {, S
, MIIM_SUBMENU
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
988 {, S
, MIIM_SUBMENU
, -9, -9, -9, submenu
, -9, -9, -9, string
, 80, -9, },
991 TMII_INSMI( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, submenu
, -1, -1, -1, empty
, 0, -1, }, OK
)
992 TMII_GMII ( {, S
, MIIM_SUBMENU
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
993 {, S
, MIIM_SUBMENU
, -9, -9, -9, submenu
, -9, -9, -9, string
, 80, -9, },
996 /* menu with submenu, without MIIM_SUBMENU the submenufield is cleared */
997 TMII_INSMI( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, submenu
, -1, -1, -1, txt
, 0, -1, }, OK
)
998 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
999 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
1001 TMII_GMII ( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1002 {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_SEPARATOR
, -9, -9, submenu
, -9, -9, -9, string
, 80, -9, },
1005 /* menu with invalid submenu */
1006 TMII_INSMI( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, 999, -1, -1, -1, txt
, 0, -1, }, ER
)
1007 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
1008 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
1012 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, txt
, 0, 0, }, OK
)
1013 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1014 {, S
, MIIM_TYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
1017 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, hbm
, 6, -1, }, OK
)
1018 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1019 {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
1022 /* SEPARATOR and STRING go well together */
1023 /* BITMAP and STRING go well together */
1024 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1025 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1026 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, hbm
, },
1029 /* BITMAP, SEPARATOR and STRING go well together */
1030 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1031 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1032 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 4, hbm
, },
1035 /* last two tests, but use MIIM_TYPE to retrieve info */
1036 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
1037 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1038 {, S
, MIIM_TYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1041 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1042 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1043 {, S
, MIIM_TYPE
, MFT_BITMAP
, -9, -9, 0, -9, -9, -9, hbm
, 4, hbm
, },
1046 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1047 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1048 {, S
, MIIM_TYPE
, MFT_SEPARATOR
|MFT_BITMAP
, -9, -9, 0, -9, -9, -9, hbm
, 4, hbm
, },
1051 /* same three with MFT_OWNERDRAW */
1052 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
1053 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1054 {, S
, MIIM_TYPE
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1057 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1058 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1059 {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, hbm
, 4, hbm
, },
1062 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1063 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1064 {, S
, MIIM_TYPE
, MFT_SEPARATOR
|MFT_BITMAP
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, hbm
, 4, hbm
, },
1068 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
|MIIM_ID
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
1069 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1070 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1073 /* test with modifymenu: string is preserved after seting OWNERDRAW */
1074 TMII_INSMI( {, S
, MIIM_STRING
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
1075 TMII_MODM( MFT_OWNERDRAW
, -1, 787, OK
)
1076 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1077 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_DATA
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, 787, string
, 4, -9, },
1080 /* same with bitmap: now the text is cleared */
1081 TMII_INSMI( {, S
, MIIM_STRING
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
1082 TMII_MODM( MFT_BITMAP
, 545, hbm
, OK
)
1083 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1084 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_BITMAP
, -9, 545, 0, -9, -9, -9, string
, 0, hbm
, },
1087 /* start with bitmap: now setting text clears it (though he flag is raised) */
1088 TMII_INSMI( {, S
, MIIM_BITMAP
, MFT_STRING
, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1089 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1090 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_STRING
, -9, 0, 0, -9, -9, -9, string
, 0, hbm
, },
1092 TMII_MODM( MFT_STRING
, 545, txt
, OK
)
1093 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1094 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_STRING
, -9, 545, 0, -9, -9, -9, string
, 4, 0, },
1097 /*repeat with text NULL */
1098 TMII_INSMI( {, S
, MIIM_BITMAP
, MFT_STRING
, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1099 TMII_MODM( MFT_STRING
, 545, NULL
, OK
)
1100 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1101 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_SEPARATOR
, -9, 545, 0, -9, -9, -9, string
, 0, 0, },
1104 /* repeat with text "" */
1105 TMII_INSMI( {, S
, MIIM_BITMAP
, -1 , -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1106 TMII_MODM( MFT_STRING
, 545, empty
, OK
)
1107 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1108 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_STRING
, -9, 545, 0, -9, -9, -9, string
, 0, 0, },
1111 /* start with bitmap: set ownerdraw */
1112 TMII_INSMI( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1113 TMII_MODM( MFT_OWNERDRAW
, -1, 232, OK
)
1114 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1115 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_DATA
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, 232, string
, 0, hbm
, },
1119 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1120 TMII_GMII ( {, S
, 0, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1121 {, S
, 0, -9, -9, -9, 0, -9, -9, -9, string
, 80, -9, },
1124 /* some tests with small cbSize: the hbmpItem is to be ignored */
1125 TMII_INSMI( {, S
- 4, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1126 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1127 {, S
, MIIM_TYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, NULL
, 0, NULL
, },
1130 TMII_INSMI( {, S
- 4, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1131 TMII_GMII ( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1132 {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 80, NULL
, },
1135 TMII_INSMI( {, S
- 4, MIIM_STRING
|MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1136 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1137 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, NULL
, },
1140 TMII_INSMI( {, S
- 4, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1141 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1142 {, S
, MIIM_TYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1145 TMII_INSMI( {, S
- 4, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1146 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1147 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1150 TMII_INSMI( {, S
- 4, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1151 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1152 {, S
, MIIM_TYPE
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1155 /* MIIM_TYPE by itself does not get/set the dwItemData for OwnerDrawn menus */
1156 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, 343, txt
, 0, -1, }, OK
)
1157 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1158 {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, 343, 0, 0, 0, },
1161 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, 343, txt
, 0, -1, }, OK
)
1162 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1163 {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
1166 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, 343, txt
, 0, -1, }, OK
)
1167 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1168 {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, 0, 0, 0, 0, },
1171 /* set a string menu to ownerdraw with MIIM_TYPE */
1172 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -2, -2, -2, -2, -2, -2, txt
, -2, -2, }, OK
)
1173 TMII_SMII( {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, OK
)
1174 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1175 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 4, -9, },
1178 /* test with modifymenu add submenu */
1179 TMII_INSMI( {, S
, MIIM_STRING
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
1180 TMII_MODM( MF_POPUP
, submenu
, txt
, OK
)
1181 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_SUBMENU
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1182 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_SUBMENU
, MFT_STRING
, -9, -9, submenu
, -9, -9, -9, string
, 4, -9, },
1184 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1185 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, 0, },
1188 /* MFT_SEPARATOR bit is kept when the text is added */
1189 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
1190 TMII_SMII( {, S
, MIIM_STRING
, -1, -1, -1, -1, -1, -1, -1, txt
, -1, -1, }, OK
)
1191 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1192 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 4, -9, },
1195 /* MFT_SEPARATOR bit is kept when bitmap is added */
1196 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
1197 TMII_SMII( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1198 TMII_GMII ( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1199 {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 80, hbm
, },
1202 /* Bitmaps inserted with MIIM_TYPE and MFT_BITMAP:
1203 Only the low word of the dwTypeData is used.
1204 Use a magic bitmap here (Word 95 uses this to create its MDI menu buttons) */
1205 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_RIGHTJUSTIFY
, -1, -1, -1, -1, -1, -1, MAKELONG(HBMMENU_MBAR_CLOSE
, 0x1234), -1, -1, }, OK
)
1206 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1207 {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_RIGHTJUSTIFY
, -9, -9, 0, -9, -9, -9, HBMMENU_MBAR_CLOSE
, 0, HBMMENU_MBAR_CLOSE
, },
1211 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_RIGHTORDER
, -1, -1, -1, -1, -1, -1, hbm
, -1, -1, }, OK
)
1212 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1213 {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_RIGHTORDER
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
1217 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, -1, -1, }, OK
)
1218 TMII_SMII( {, S
, MIIM_STATE
, -1, MFS_CHECKED
| MFS_DEFAULT
| MFS_GRAYED
| MFS_HILITE
, -1, -1, -1, -1, -1, -1, -1, -1, }, OK
)
1219 TMII_GMII ( {, S
, MIIM_STATE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1220 {, S
, MIIM_STATE
, -9, MFS_CHECKED
| MFS_DEFAULT
| MFS_GRAYED
| MFS_HILITE
, -9, 0, -9, -9, -9, -9, -9, -9, },
1223 /* The style MFT_RADIOCHECK cannot be set with MIIM_CHECKMARKS only */
1224 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, -1, -1, }, OK
)
1225 TMII_SMII( {, S
, MIIM_CHECKMARKS
, MFT_RADIOCHECK
, -1, -1, -1, hbm
, hbm
, -1, -1, -1, -1, }, OK
)
1226 TMII_GMII ( {, S
, MIIM_CHECKMARKS
| MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1227 {, S
, MIIM_CHECKMARKS
| MIIM_TYPE
, MFT_BITMAP
, -9, -9, 0, hbm
, hbm
, -9, hbm
, 0, hbm
, },
1230 /* MFT_BITMAP is added automatically by GetMenuItemInfo() for MIIM_TYPE */
1231 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, -1, -1, }, OK
)
1232 TMII_SMII( {, S
, MIIM_FTYPE
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, 0x1234, -1, -1, }, OK
)
1233 TMII_GMII ( {, S
, MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1234 {, S
, MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, -9, -9, -9, },
1236 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1237 {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
1239 TMII_GMII ( {, S
, MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1240 {, S
, MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, -9, -9, -9, },
1242 TMII_SMII( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, NULL
, }, OK
)
1243 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1244 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 0, NULL
, },
1247 /* Bitmaps inserted with MIIM_TYPE and MFT_BITMAP:
1248 Only the low word of the dwTypeData is used.
1249 Use a magic bitmap here (Word 95 uses this to create its MDI menu buttons) */
1250 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_RIGHTJUSTIFY
, -1, -1, -1, -1, -1, -1, MAKELONG(HBMMENU_MBAR_CLOSE
, 0x1234), -1, -1, }, OK
)
1251 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1252 {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_RIGHTJUSTIFY
, -9, -9, 0, -9, -9, -9, HBMMENU_MBAR_CLOSE
, 0, HBMMENU_MBAR_CLOSE
, },
1256 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_RIGHTORDER
, -1, -1, -1, -1, -1, -1, hbm
, -1, -1, }, OK
)
1257 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1258 {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_RIGHTORDER
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
1262 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, -1, -1, }, OK
)
1263 TMII_SMII( {, S
, MIIM_STATE
, -1, MFS_CHECKED
| MFS_DEFAULT
| MFS_GRAYED
| MFS_HILITE
, -1, -1, -1, -1, -1, -1, -1, -1, }, OK
)
1264 TMII_GMII ( {, S
, MIIM_STATE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1265 {, S
, MIIM_STATE
, -9, MFS_CHECKED
| MFS_DEFAULT
| MFS_GRAYED
| MFS_HILITE
, -9, 0, -9, -9, -9, -9, -9, -9, },
1268 /* The style MFT_RADIOCHECK cannot be set with MIIM_CHECKMARKS only */
1269 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, -1, -1, }, OK
)
1270 TMII_SMII( {, S
, MIIM_CHECKMARKS
, MFT_RADIOCHECK
, -1, -1, -1, hbm
, hbm
, -1, -1, -1, -1, }, OK
)
1271 TMII_GMII ( {, S
, MIIM_CHECKMARKS
| MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1272 {, S
, MIIM_CHECKMARKS
| MIIM_TYPE
, MFT_BITMAP
, -9, -9, 0, hbm
, hbm
, -9, hbm
, 0, hbm
, },
1275 /* MFT_BITMAP is added automatically by GetMenuItemInfo() for MIIM_TYPE */
1276 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, -1, -1, }, OK
)
1277 TMII_SMII( {, S
, MIIM_FTYPE
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, 0x1234, -1, -1, }, OK
)
1278 TMII_GMII ( {, S
, MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1279 {, S
, MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, -9, -9, -9, },
1281 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1282 {, S
, MIIM_TYPE
, MFT_BITMAP
| MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
1284 TMII_GMII ( {, S
, MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1285 {, S
, MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, -9, -9, -9, },
1287 TMII_SMII( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, NULL
, }, OK
)
1288 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, },
1289 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 0, NULL
, },
1292 } while( !(ansi
= !ansi
) );
1297 The following tests try to confirm the algorithm used to return the menu items
1298 when there is a collision between a menu item and a popup menu
1300 static void test_menu_search_bycommand( void )
1302 HMENU hmenu
, hmenuSub
, hmenuSub2
;
1308 static CHAR menuitem
[] = "MenuItem",
1309 menuitem2
[] = "MenuItem 2";
1311 /* Case 1: Menu containing a menu item */
1312 hmenu
= CreateMenu();
1314 memset( &info
, 0, sizeof info
);
1315 info
.cbSize
= sizeof info
;
1316 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1317 info
.fType
= MFT_STRING
;
1318 strcpy(strIn
, "Case 1 MenuItem");
1319 info
.dwTypeData
= strIn
;
1320 info
.wID
= (UINT
) 0x1234;
1322 rc
= InsertMenuItem(hmenu
, 0, TRUE
, &info
);
1323 ok (rc
, "Inserting the menuitem failed\n");
1325 id
= GetMenuItemID(hmenu
, 0);
1326 ok (id
== 0x1234, "Getting the menuitem id failed(gave %x)\n", id
);
1328 /* Confirm the menuitem was given the id supplied (getting by position) */
1329 memset( &info
, 0, sizeof info
);
1331 info
.cbSize
= sizeof(MENUITEMINFO
);
1332 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1333 info
.dwTypeData
= strback
;
1334 info
.cch
= sizeof(strback
);
1336 rc
= GetMenuItemInfo(hmenu
, 0, TRUE
, &info
); /* Get by position */
1337 ok (rc
, "Getting the menu items info failed\n");
1338 ok (info
.wID
== 0x1234, "IDs differ for the menuitem\n");
1339 ok (!strcmp(info
.dwTypeData
, "Case 1 MenuItem"), "Returned item has wrong label\n");
1341 /* Search by id - Should return the item */
1342 memset( &info
, 0, sizeof info
);
1344 info
.cbSize
= sizeof(MENUITEMINFO
);
1345 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1346 info
.dwTypeData
= strback
;
1347 info
.cch
= sizeof(strback
);
1348 rc
= GetMenuItemInfo(hmenu
, 0x1234, FALSE
, &info
); /* Get by ID */
1350 ok (rc
, "Getting the menu items info failed\n");
1351 ok (info
.wID
== 0x1234, "IDs differ for the menuitem\n");
1352 ok (!strcmp(info
.dwTypeData
, "Case 1 MenuItem"), "Returned item has wrong label\n");
1354 DestroyMenu( hmenu
);
1356 /* Case 2: Menu containing a popup menu */
1357 hmenu
= CreateMenu();
1358 hmenuSub
= CreateMenu();
1360 strcpy(strIn
, "Case 2 SubMenu");
1361 rc
= InsertMenu(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, strIn
);
1362 ok (rc
, "Inserting the popup menu into the main menu failed\n");
1364 id
= GetMenuItemID(hmenu
, 0);
1365 ok (id
== -1, "Getting the menuitem id unexpectedly worked (gave %x)\n", id
);
1367 /* Confirm the menuitem itself was given an id the same as the HMENU, (getting by position) */
1368 memset( &info
, 0, sizeof info
);
1370 info
.cbSize
= sizeof(MENUITEMINFO
);
1371 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1372 info
.dwTypeData
= strback
;
1373 info
.cch
= sizeof(strback
);
1374 info
.wID
= 0xdeadbeef;
1376 rc
= GetMenuItemInfo(hmenu
, 0, TRUE
, &info
); /* Get by position */
1377 ok (rc
, "Getting the menu items info failed\n");
1378 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the menuitem\n");
1379 ok (!strcmp(info
.dwTypeData
, "Case 2 SubMenu"), "Returned item has wrong label\n");
1381 /* Search by id - returns the popup menu itself */
1382 memset( &info
, 0, sizeof info
);
1384 info
.cbSize
= sizeof(MENUITEMINFO
);
1385 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1386 info
.dwTypeData
= strback
;
1387 info
.cch
= sizeof(strback
);
1388 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
); /* Get by ID */
1390 ok (rc
, "Getting the menu items info failed\n");
1391 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the popup menu\n");
1392 ok (!strcmp(info
.dwTypeData
, "Case 2 SubMenu"), "Returned item has wrong label\n");
1395 Now add an item after it with the same id
1397 memset( &info
, 0, sizeof info
);
1398 info
.cbSize
= sizeof info
;
1399 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1400 info
.fType
= MFT_STRING
;
1401 strcpy(strIn
, "Case 2 MenuItem 1");
1402 info
.dwTypeData
= strIn
;
1403 info
.wID
= (UINT_PTR
) hmenuSub
;
1404 rc
= InsertMenuItem(hmenu
, -1, TRUE
, &info
);
1405 ok (rc
, "Inserting the menuitem failed\n");
1407 /* Search by id - returns the item which follows the popup menu */
1408 memset( &info
, 0, sizeof info
);
1410 info
.cbSize
= sizeof(MENUITEMINFO
);
1411 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1412 info
.dwTypeData
= strback
;
1413 info
.cch
= sizeof(strback
);
1414 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
); /* Get by ID */
1416 ok (rc
, "Getting the menu items info failed\n");
1417 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the popup menu\n");
1418 ok (!strcmp(info
.dwTypeData
, "Case 2 MenuItem 1"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1421 Now add an item before the popup (with the same id)
1423 memset( &info
, 0, sizeof info
);
1424 info
.cbSize
= sizeof info
;
1425 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1426 info
.fType
= MFT_STRING
;
1427 strcpy(strIn
, "Case 2 MenuItem 2");
1428 info
.dwTypeData
= strIn
;
1429 info
.wID
= (UINT_PTR
) hmenuSub
;
1430 rc
= InsertMenuItem(hmenu
, 0, TRUE
, &info
);
1431 ok (rc
, "Inserting the menuitem failed\n");
1433 /* Search by id - returns the item which precedes the popup menu */
1434 memset( &info
, 0, sizeof info
);
1436 info
.cbSize
= sizeof(MENUITEMINFO
);
1437 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1438 info
.dwTypeData
= strback
;
1439 info
.cch
= sizeof(strback
);
1440 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
); /* Get by ID */
1442 ok (rc
, "Getting the menu items info failed\n");
1443 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the popup menu\n");
1444 ok (!strcmp(info
.dwTypeData
, "Case 2 MenuItem 2"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1446 DestroyMenu( hmenu
);
1447 DestroyMenu( hmenuSub
);
1450 Case 3: Menu containing a popup menu which in turn
1451 contains 2 items with the same id as the popup itself
1454 hmenu
= CreateMenu();
1455 hmenuSub
= CreateMenu();
1457 memset( &info
, 0, sizeof info
);
1458 info
.cbSize
= sizeof info
;
1459 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1460 info
.fType
= MFT_STRING
;
1461 info
.dwTypeData
= menuitem
;
1462 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
1464 rc
= InsertMenu(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, "Submenu");
1465 ok (rc
, "Inserting the popup menu into the main menu failed\n");
1467 rc
= InsertMenuItem(hmenuSub
, 0, TRUE
, &info
);
1468 ok (rc
, "Inserting the sub menu menuitem failed\n");
1470 memset( &info
, 0, sizeof info
);
1471 info
.cbSize
= sizeof info
;
1472 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1473 info
.fType
= MFT_STRING
;
1474 info
.dwTypeData
= menuitem2
;
1475 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
1477 rc
= InsertMenuItem(hmenuSub
, 1, TRUE
, &info
);
1478 ok (rc
, "Inserting the sub menu menuitem 2 failed\n");
1480 /* Prove that you can't query the id of a popup directly (By position) */
1481 id
= GetMenuItemID(hmenu
, 0);
1482 ok (id
== -1, "Getting the sub menu id should have failed because its a popup (gave %x)\n", id
);
1484 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
1485 memset( &info
, 0, sizeof info
);
1487 info
.cbSize
= sizeof(MENUITEMINFO
);
1488 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1489 info
.dwTypeData
= strback
;
1490 info
.cch
= sizeof(strback
);
1492 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
);
1493 ok (rc
, "Getting the menus info failed\n");
1494 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for popup menu\n");
1495 ok (!strcmp(info
.dwTypeData
, "MenuItem"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1496 DestroyMenu( hmenu
);
1497 DestroyMenu( hmenuSub
);
1500 Case 4: Menu containing 2 popup menus, the second
1501 contains 2 items with the same id as the first popup menu
1503 hmenu
= CreateMenu();
1504 hmenuSub
= CreateMenu();
1505 hmenuSub2
= CreateMenu();
1507 rc
= InsertMenu(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, "Submenu");
1508 ok (rc
, "Inserting the popup menu into the main menu failed\n");
1510 rc
= InsertMenu(hmenu
, 1, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub2
, "Submenu2");
1511 ok (rc
, "Inserting the popup menu into the main menu failed\n");
1513 memset( &info
, 0, sizeof info
);
1514 info
.cbSize
= sizeof info
;
1515 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1516 info
.fType
= MFT_STRING
;
1517 info
.dwTypeData
= menuitem
;
1518 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
1520 rc
= InsertMenuItem(hmenuSub2
, 0, TRUE
, &info
);
1521 ok (rc
, "Inserting the sub menu menuitem failed\n");
1523 memset( &info
, 0, sizeof info
);
1524 info
.cbSize
= sizeof info
;
1525 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1526 info
.fType
= MFT_STRING
;
1527 info
.dwTypeData
= menuitem2
;
1528 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
1530 rc
= InsertMenuItem(hmenuSub2
, 1, TRUE
, &info
);
1531 ok (rc
, "Inserting the sub menu menuitem 2 failed\n");
1533 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
1534 memset( &info
, 0, sizeof info
);
1536 info
.cbSize
= sizeof(MENUITEMINFO
);
1537 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1538 info
.dwTypeData
= strback
;
1539 info
.cch
= sizeof(strback
);
1541 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
);
1542 ok (rc
, "Getting the menus info failed\n");
1543 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for popup menu\n");
1544 ok (!strcmp(info
.dwTypeData
, "MenuItem"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1546 memset( &info
, 0, sizeof info
);
1548 info
.cbSize
= sizeof(MENUITEMINFO
);
1549 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1550 info
.dwTypeData
= strback
;
1551 info
.cch
= sizeof(strback
);
1553 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub2
, FALSE
, &info
);
1554 ok (rc
, "Getting the menus info failed\n");
1555 ok (info
.wID
== (UINT
)hmenuSub2
, "IDs differ for popup menu\n");
1556 ok (!strcmp(info
.dwTypeData
, "Submenu2"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1558 DestroyMenu( hmenu
);
1559 DestroyMenu( hmenuSub
);
1560 DestroyMenu( hmenuSub2
);
1564 Case 5: Menu containing a popup menu which in turn
1565 contains an item with a different id than the popup menu.
1566 This tests the fallback to a popup menu ID.
1569 hmenu
= CreateMenu();
1570 hmenuSub
= CreateMenu();
1572 rc
= AppendMenu(hmenu
, MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, "Submenu");
1573 ok (rc
, "Appending the popup menu to the main menu failed\n");
1575 rc
= AppendMenu(hmenuSub
, MF_STRING
, 102, "Item");
1576 ok (rc
, "Appending the item to the popup menu failed\n");
1578 /* Set the ID for hmenuSub */
1579 info
.cbSize
= sizeof(info
);
1580 info
.fMask
= MIIM_ID
;
1583 rc
= SetMenuItemInfo(hmenu
, 0, TRUE
, &info
);
1584 ok(rc
, "Setting the ID for the popup menu failed\n");
1586 /* Check if the ID has been set */
1588 rc
= GetMenuItemInfo(hmenu
, 0, TRUE
, &info
);
1589 ok(rc
, "Getting the ID for the popup menu failed\n");
1590 ok(info
.wID
== 101, "The ID for the popup menu has not been set\n");
1592 /* Prove getting the item info via ID returns the popup menu */
1593 memset( &info
, 0, sizeof(info
));
1595 info
.cbSize
= sizeof(MENUITEMINFO
);
1596 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1597 info
.dwTypeData
= strback
;
1598 info
.cch
= sizeof(strback
);
1600 rc
= GetMenuItemInfo(hmenu
, 101, FALSE
, &info
);
1601 ok (rc
, "Getting the menu info failed\n");
1602 ok (info
.wID
== 101, "IDs differ\n");
1603 ok (!strcmp(info
.dwTypeData
, "Submenu"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1605 /* Also look for the menu item */
1606 memset( &info
, 0, sizeof(info
));
1608 info
.cbSize
= sizeof(MENUITEMINFO
);
1609 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1610 info
.dwTypeData
= strback
;
1611 info
.cch
= sizeof(strback
);
1613 rc
= GetMenuItemInfo(hmenu
, 102, FALSE
, &info
);
1614 ok (rc
, "Getting the menu info failed\n");
1615 ok (info
.wID
== 102, "IDs differ\n");
1616 ok (!strcmp(info
.dwTypeData
, "Item"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1619 DestroyMenu(hmenuSub
);
1622 struct menu_item_pair_s
{
1623 UINT uMenu
; /* 1 - top level menu, [0-Menu 1-Enabled 2-Disabled]
1624 * 2 - 2nd level menu, [0-Popup 1-Enabled 2-Disabled]
1625 * 3 - 3rd level menu, [0-Enabled 1-Disabled] */
1629 static struct menu_mouse_tests_s
{
1631 struct menu_item_pair_s menu_item_pairs
[5]; /* for mousing */
1632 WORD wVk
[5]; /* keys */
1636 /* for each test, send keys or clicks and check for menu visibility */
1637 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 0}, TRUE
, FALSE
}, /* test 0 */
1638 { INPUT_KEYBOARD
, {{0}}, {VK_ESCAPE
, 0}, FALSE
, FALSE
},
1639 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 0}, TRUE
, FALSE
},
1640 { INPUT_KEYBOARD
, {{0}}, {'D', 0}, FALSE
, FALSE
},
1641 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 0}, TRUE
, FALSE
},
1642 { INPUT_KEYBOARD
, {{0}}, {'E', 0}, FALSE
, FALSE
},
1643 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 0}, TRUE
, FALSE
},
1644 { INPUT_KEYBOARD
, {{0}}, {VK_ESCAPE
, VK_ESCAPE
, 0}, FALSE
, FALSE
},
1645 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', VK_ESCAPE
, 0}, TRUE
, FALSE
},
1646 { INPUT_KEYBOARD
, {{0}}, {VK_ESCAPE
, 0}, FALSE
, FALSE
},
1647 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 0}, TRUE
, FALSE
},
1648 { INPUT_KEYBOARD
, {{0}}, {'D', 0}, FALSE
, FALSE
},
1649 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 0}, TRUE
, FALSE
},
1650 { INPUT_KEYBOARD
, {{0}}, {'E', 0}, FALSE
, FALSE
},
1651 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 'P', 0}, TRUE
, FALSE
},
1652 { INPUT_KEYBOARD
, {{0}}, {'D', 0}, FALSE
, FALSE
},
1653 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 'P', 0}, TRUE
, FALSE
},
1654 { INPUT_KEYBOARD
, {{0}}, {'E', 0}, FALSE
, FALSE
},
1656 { INPUT_MOUSE
, {{1, 2}, {0}}, {0}, TRUE
, TRUE
}, /* test 18 */
1657 { INPUT_MOUSE
, {{1, 1}, {0}}, {0}, FALSE
, FALSE
},
1658 { INPUT_MOUSE
, {{1, 0}, {0}}, {0}, TRUE
, TRUE
},
1659 { INPUT_MOUSE
, {{1, 1}, {0}}, {0}, FALSE
, FALSE
},
1660 { INPUT_MOUSE
, {{1, 0}, {2, 2}, {0}}, {0}, TRUE
, TRUE
},
1661 { INPUT_MOUSE
, {{2, 1}, {0}}, {0}, FALSE
, FALSE
},
1662 { INPUT_MOUSE
, {{1, 0}, {2, 0}, {0}}, {0}, TRUE
, TRUE
},
1663 { INPUT_MOUSE
, {{3, 0}, {0}}, {0}, FALSE
, FALSE
},
1664 { INPUT_MOUSE
, {{1, 0}, {2, 0}, {0}}, {0}, TRUE
, TRUE
},
1665 { INPUT_MOUSE
, {{3, 1}, {0}}, {0}, TRUE
, TRUE
},
1666 { INPUT_MOUSE
, {{1, 1}, {0}}, {0}, FALSE
, FALSE
},
1670 static void send_key(WORD wVk
)
1673 memset(&i
, 0, 2*sizeof(INPUT
));
1674 i
[0].type
= i
[1].type
= INPUT_KEYBOARD
;
1675 i
[0].u
.ki
.wVk
= i
[1].u
.ki
.wVk
= wVk
;
1676 i
[1].u
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
1677 SendInput(2, (INPUT
*) i
, sizeof(INPUT
));
1680 static void click_menu(HANDLE hWnd
, struct menu_item_pair_s
*mi
)
1682 HMENU hMenu
= hMenus
[mi
->uMenu
];
1686 int screen_w
= GetSystemMetrics(SM_CXSCREEN
);
1687 int screen_h
= GetSystemMetrics(SM_CYSCREEN
);
1689 GetMenuItemRect(mi
->uMenu
> 2 ? NULL
: hWnd
, hMenu
, mi
->uItem
, &r
);
1691 memset(&i
, 0, 3*sizeof(INPUT
));
1692 i
[0].type
= i
[1].type
= i
[2].type
= INPUT_MOUSE
;
1693 i
[0].u
.mi
.dx
= i
[1].u
.mi
.dx
= i
[2].u
.mi
.dx
1694 = ((r
.left
+ 5) * 65535) / screen_w
;
1695 i
[0].u
.mi
.dy
= i
[1].u
.mi
.dy
= i
[2].u
.mi
.dy
1696 = ((r
.top
+ 5) * 65535) / screen_h
;
1697 i
[0].u
.mi
.dwFlags
= i
[1].u
.mi
.dwFlags
= i
[2].u
.mi
.dwFlags
1698 = MOUSEEVENTF_ABSOLUTE
;
1699 i
[0].u
.mi
.dwFlags
|= MOUSEEVENTF_MOVE
;
1700 i
[1].u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTDOWN
;
1701 i
[2].u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTUP
;
1702 SendInput(3, (INPUT
*) i
, sizeof(INPUT
));
1704 /* hack to prevent mouse message buildup in Wine */
1705 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
1708 static DWORD WINAPI
test_menu_input_thread(LPVOID lpParameter
)
1711 HANDLE hWnd
= lpParameter
;
1714 /* mixed keyboard/mouse test */
1715 for (i
= 0; menu_tests
[i
].type
!= -1; i
++)
1719 if (menu_tests
[i
].type
== INPUT_KEYBOARD
)
1720 for (j
= 0; menu_tests
[i
].wVk
[j
] != 0; j
++)
1721 send_key(menu_tests
[i
].wVk
[j
]);
1723 for (j
= 0; menu_tests
[i
].menu_item_pairs
[j
].uMenu
!= 0; j
++)
1724 click_menu(hWnd
, &menu_tests
[i
].menu_item_pairs
[j
]);
1726 while (menu_tests
[i
].bMenuVisible
!= bMenuVisible
)
1734 if (menu_tests
[i
]._todo_wine
)
1737 ok(menu_tests
[i
].bMenuVisible
== bMenuVisible
, "test %d\n", i
);
1741 ok(menu_tests
[i
].bMenuVisible
== bMenuVisible
, "test %d\n", i
);
1746 static LRESULT CALLBACK
WndProc(HWND hWnd
, UINT msg
, WPARAM wParam
,
1750 case WM_ENTERMENULOOP
:
1751 bMenuVisible
= TRUE
;
1753 case WM_EXITMENULOOP
:
1754 bMenuVisible
= FALSE
;
1757 return( DefWindowProcA( hWnd
, msg
, wParam
, lParam
) );
1762 static void test_menu_input(void) {
1765 HINSTANCE hInstance
= GetModuleHandleA( NULL
);
1766 HANDLE hThread
, hWnd
;
1768 wclass
.lpszClassName
= "MenuTestClass";
1769 wclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
1770 wclass
.lpfnWndProc
= WndProc
;
1771 wclass
.hInstance
= hInstance
;
1772 wclass
.hIcon
= LoadIconA( 0, (LPSTR
)IDI_APPLICATION
);
1773 wclass
.hCursor
= LoadCursorA( NULL
, (LPSTR
)IDC_ARROW
);
1774 wclass
.hbrBackground
= (HBRUSH
)( COLOR_WINDOW
+ 1);
1775 wclass
.lpszMenuName
= 0;
1776 wclass
.cbClsExtra
= 0;
1777 wclass
.cbWndExtra
= 0;
1778 assert (RegisterClassA( &wclass
));
1779 assert (hWnd
= CreateWindowA( wclass
.lpszClassName
, "MenuTest",
1780 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, 0,
1781 400, 200, NULL
, NULL
, hInstance
, NULL
) );
1784 hMenus
[3] = CreatePopupMenu();
1785 AppendMenu(hMenus
[3], MF_STRING
, 0, "&Enabled");
1786 AppendMenu(hMenus
[3], MF_STRING
|MF_DISABLED
, 0, "&Disabled");
1788 hMenus
[2] = CreatePopupMenu();
1789 AppendMenu(hMenus
[2], MF_STRING
|MF_POPUP
, (UINT_PTR
) hMenus
[3], "&Popup");
1790 AppendMenu(hMenus
[2], MF_STRING
, 0, "&Enabled");
1791 AppendMenu(hMenus
[2], MF_STRING
|MF_DISABLED
, 0, "&Disabled");
1793 hMenus
[1] = CreateMenu();
1794 AppendMenu(hMenus
[1], MF_STRING
|MF_POPUP
, (UINT_PTR
) hMenus
[2], "&Menu");
1795 AppendMenu(hMenus
[1], MF_STRING
, 0, "&Enabled");
1796 AppendMenu(hMenus
[1], MF_STRING
|MF_DISABLED
, 0, "&Disabled");
1798 SetMenu(hWnd
, hMenus
[1]);
1799 ShowWindow(hWnd
, SW_SHOW
);
1802 hThread
= CreateThread(NULL
, 0, test_menu_input_thread
, hWnd
, 0, NULL
);
1805 if (WAIT_TIMEOUT
!= WaitForSingleObject(hThread
, 50))
1807 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
1809 DestroyWindow(hWnd
);
1812 static void test_menu_flags( void )
1814 HMENU hMenu
, hPopupMenu
;
1816 hMenu
= CreateMenu();
1817 hPopupMenu
= CreatePopupMenu();
1819 AppendMenu(hMenu
, MF_POPUP
| MF_STRING
, (UINT
)hPopupMenu
, "Popup");
1821 AppendMenu(hPopupMenu
, MF_STRING
| MF_HILITE
| MF_DEFAULT
, 101, "Item 1");
1822 InsertMenu(hPopupMenu
, 1, MF_BYPOSITION
| MF_STRING
| MF_HILITE
| MF_DEFAULT
, 102, "Item 2");
1823 AppendMenu(hPopupMenu
, MF_STRING
, 103, "Item 3");
1824 ModifyMenu(hPopupMenu
, 2, MF_BYPOSITION
| MF_STRING
| MF_HILITE
| MF_DEFAULT
, 103, "Item 3");
1826 ok(GetMenuState(hPopupMenu
, 0, MF_BYPOSITION
) & MF_HILITE
,
1827 "AppendMenu should accept MF_HILITE\n");
1828 ok(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_HILITE
,
1829 "InsertMenu should accept MF_HILITE\n");
1830 ok(GetMenuState(hPopupMenu
, 2, MF_BYPOSITION
) & MF_HILITE
,
1831 "ModifyMenu should accept MF_HILITE\n");
1833 ok(!(GetMenuState(hPopupMenu
, 0, MF_BYPOSITION
) & MF_DEFAULT
),
1834 "AppendMenu must not accept MF_DEFAULT\n");
1835 ok(!(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_DEFAULT
),
1836 "InsertMenu must not accept MF_DEFAULT\n");
1837 ok(!(GetMenuState(hPopupMenu
, 2, MF_BYPOSITION
) & MF_DEFAULT
),
1838 "ModifyMenu must not accept MF_DEFAULT\n");
1843 static void test_menu_hilitemenuitem( void )
1845 HMENU hMenu
, hPopupMenu
;
1847 hMenu
= CreateMenu();
1848 hPopupMenu
= CreatePopupMenu();
1850 AppendMenu(hMenu
, MF_POPUP
| MF_STRING
, (UINT
)hPopupMenu
, "Popup");
1852 AppendMenu(hPopupMenu
, MF_STRING
, 101, "Item 1");
1853 AppendMenu(hPopupMenu
, MF_STRING
, 102, "Item 2");
1854 AppendMenu(hPopupMenu
, MF_STRING
, 103, "Item 3");
1856 HiliteMenuItem(NULL
, hPopupMenu
, 0, MF_HILITE
);
1857 HiliteMenuItem(NULL
, hPopupMenu
, 1, MF_HILITE
);
1858 HiliteMenuItem(NULL
, hPopupMenu
, 2, MF_HILITE
);
1859 HiliteMenuItem(NULL
, hPopupMenu
, 1, MF_UNHILITE
);
1863 ok(GetMenuState(hPopupMenu
, 0, MF_BYPOSITION
) & MF_HILITE
,
1864 "HiliteMenuItem: Item 1 is not hilited\n");
1866 ok(!(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_HILITE
),
1867 "HiliteMenuItem: Item 2 is hilited\n");
1870 ok(GetMenuState(hPopupMenu
, 2, MF_BYPOSITION
) & MF_HILITE
,
1871 "HiliteMenuItem: Item 3 is not hilited\n");
1877 static void check_menu_items(HMENU hmenu
, UINT checked_cmd
, UINT checked_type
,
1882 count
= GetMenuItemCount(hmenu
);
1884 for (i
= 0; i
< count
; i
++)
1889 memset(&mii
, 0, sizeof(mii
));
1890 mii
.cbSize
= sizeof(mii
);
1891 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
| MIIM_SUBMENU
;
1892 ret
= GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
);
1893 ok(ret
, "GetMenuItemInfo(%u) failed\n", i
);
1895 trace("item #%u: fType %04x, fState %04x, wID %u, hSubMenu %p\n",
1896 i
, mii
.fType
, mii
.fState
, mii
.wID
, mii
.hSubMenu
);
1900 ok((HMENU
)mii
.wID
== mii
.hSubMenu
, "id %u: wID should be equal to hSubMenu\n", checked_cmd
);
1901 check_menu_items(mii
.hSubMenu
, checked_cmd
, checked_type
, checked_state
);
1905 if (mii
.wID
== checked_cmd
)
1907 ok(mii
.fType
== checked_type
, "id %u: expected fType %04x, got %04x\n", checked_cmd
, checked_type
, mii
.fType
);
1908 ok(mii
.fState
== checked_state
, "id %u: expected fState %04x, got %04x\n", checked_cmd
, checked_state
, mii
.fState
);
1909 ok(mii
.wID
!= 0, "id %u: not expected wID 0\n", checked_cmd
);
1913 ok(mii
.fType
!= MFT_RADIOCHECK
, "id %u: not expected fType MFT_RADIOCHECK on cmd %u\n", checked_cmd
, mii
.wID
);
1915 if (mii
.fType
== MFT_SEPARATOR
)
1917 ok(mii
.fState
== MFS_GRAYED
, "id %u: expected fState MFS_GRAYED, got %04x\n", checked_cmd
, mii
.fState
);
1918 ok(mii
.wID
== 0, "id %u: expected wID 0, got %u\n", checked_cmd
, mii
.wID
);
1922 ok(mii
.fState
== 0, "id %u: expected fState 0, got %04x\n", checked_cmd
, mii
.fState
);
1923 ok(mii
.wID
!= 0, "id %u: not expected wID 0\n", checked_cmd
);
1930 static void clear_ftype_and_state(HMENU hmenu
, UINT id
, UINT flags
)
1935 memset(&mii
, 0, sizeof(mii
));
1936 mii
.cbSize
= sizeof(mii
);
1937 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
;
1938 ret
= SetMenuItemInfo(hmenu
, id
, (flags
& MF_BYPOSITION
) != 0, &mii
);
1939 ok(ret
, "SetMenuItemInfo(%u) failed\n", id
);
1942 static void test_CheckMenuRadioItem(void)
1947 hmenu
= LoadMenu(GetModuleHandle(0), MAKEINTRESOURCE(1));
1950 check_menu_items(hmenu
, -1, 0, 0);
1952 ret
= CheckMenuRadioItem(hmenu
, 100, 100, 100, MF_BYCOMMAND
);
1953 ok(ret
, "CheckMenuRadioItem failed\n");
1954 check_menu_items(hmenu
, 100, MFT_RADIOCHECK
, MFS_CHECKED
);
1956 /* MSDN is wrong, Windows does not remove MFT_RADIOCHECK */
1957 ret
= CheckMenuRadioItem(hmenu
, 100, 100, -1, MF_BYCOMMAND
);
1958 ok(!ret
, "CheckMenuRadioItem should return FALSE\n");
1959 check_menu_items(hmenu
, 100, MFT_RADIOCHECK
, 0);
1962 clear_ftype_and_state(hmenu
, 100, MF_BYCOMMAND
);
1963 check_menu_items(hmenu
, -1, 0, 0);
1965 /* first and checked items are on different menus */
1966 ret
= CheckMenuRadioItem(hmenu
, 0, 300, 202, MF_BYCOMMAND
);
1967 ok(!ret
, "CheckMenuRadioItem should return FALSE\n");
1968 check_menu_items(hmenu
, -1, 0, 0);
1970 ret
= CheckMenuRadioItem(hmenu
, 200, 300, 202, MF_BYCOMMAND
);
1971 ok(ret
, "CheckMenuRadioItem failed\n");
1972 check_menu_items(hmenu
, 202, MFT_RADIOCHECK
, MFS_CHECKED
);
1974 /* MSDN is wrong, Windows does not remove MFT_RADIOCHECK */
1975 ret
= CheckMenuRadioItem(hmenu
, 202, 202, -1, MF_BYCOMMAND
);
1976 ok(!ret
, "CheckMenuRadioItem should return FALSE\n");
1977 check_menu_items(hmenu
, 202, MFT_RADIOCHECK
, 0);
1980 clear_ftype_and_state(hmenu
, 202, MF_BYCOMMAND
);
1981 check_menu_items(hmenu
, -1, 0, 0);
1983 /* just for fun, try to check separator */
1984 ret
= CheckMenuRadioItem(hmenu
, 0, 300, 0, MF_BYCOMMAND
);
1985 ok(!ret
, "CheckMenuRadioItem should return FALSE\n");
1986 check_menu_items(hmenu
, -1, 0, 0);
1989 static void test_menu_resource_layout(void)
1993 MENUITEMTEMPLATEHEADER mith
;
1997 { 0, 0 }, /* versionNumber, offset */
1999 /* mtOption, mtID, mtString[] '\0' terminated */
2000 MF_STRING
, 1, 'F', 0,
2003 /* MF_SEPARATOR, 4, 'S', 0, FIXME: Wine ignores 'S' */
2004 MF_STRING
|MF_GRAYED
|MF_END
, 5, 'E', 0
2009 UINT type
, state
, id
;
2013 { MF_STRING
, MF_ENABLED
, 1, "F" },
2014 { MF_SEPARATOR
, MF_GRAYED
|MF_DISABLED
, 2, "" },
2015 { MF_SEPARATOR
, MF_GRAYED
|MF_DISABLED
, 3, "" },
2016 /*{ MF_SEPARATOR, MF_GRAYED|MF_DISABLED, 4, "S" }, FIXME: Wine ignores 'S'*/
2017 { MF_STRING
, MF_GRAYED
, 5, "E" },
2018 { MF_SEPARATOR
, MF_GRAYED
|MF_DISABLED
, 6, "" },
2019 { MF_STRING
, MF_ENABLED
, 7, "" },
2020 { MF_SEPARATOR
, MF_GRAYED
|MF_DISABLED
, 8, "" }
2026 hmenu
= LoadMenuIndirect(&menu_template
);
2027 ok(hmenu
!= 0, "LoadMenuIndirect error %u\n", GetLastError());
2029 ret
= AppendMenu(hmenu
, MF_STRING
, 6, NULL
);
2030 ok(ret
, "AppendMenu failed\n");
2031 ret
= AppendMenu(hmenu
, MF_STRING
, 7, "\0");
2032 ok(ret
, "AppendMenu failed\n");
2033 ret
= AppendMenu(hmenu
, MF_SEPARATOR
, 8, "separator");
2034 ok(ret
, "AppendMenu failed\n");
2036 count
= GetMenuItemCount(hmenu
);
2037 ok(count
== sizeof(menu_data
)/sizeof(menu_data
[0]),
2038 "expected %u menu items, got %u\n",
2039 (UINT
)sizeof(menu_data
)/sizeof(menu_data
[0]), count
);
2041 for (i
= 0; i
< count
; i
++)
2046 memset(&mii
, 0, sizeof(mii
));
2047 mii
.cbSize
= sizeof(mii
);
2048 mii
.dwTypeData
= buf
;
2049 mii
.cch
= sizeof(buf
);
2050 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
| MIIM_STRING
;
2051 ret
= GetMenuItemInfo(hmenu
, i
, TRUE
, &mii
);
2052 ok(ret
, "GetMenuItemInfo(%u) failed\n", i
);
2054 trace("item #%u: fType %04x, fState %04x, wID %u, dwTypeData %s\n",
2055 i
, mii
.fType
, mii
.fState
, mii
.wID
, (LPCSTR
)mii
.dwTypeData
);
2057 ok(mii
.fType
== menu_data
[i
].type
,
2058 "%u: expected fType %04x, got %04x\n", i
, menu_data
[i
].type
, mii
.fType
);
2059 ok(mii
.fState
== menu_data
[i
].state
,
2060 "%u: expected fState %04x, got %04x\n", i
, menu_data
[i
].state
, mii
.fState
);
2061 ok(mii
.wID
== menu_data
[i
].id
,
2062 "%u: expected wID %04x, got %04x\n", i
, menu_data
[i
].id
, mii
.wID
);
2063 ok(mii
.cch
== strlen(menu_data
[i
].str
),
2064 "%u: expected cch %u, got %u\n", i
, (UINT
)strlen(menu_data
[i
].str
), mii
.cch
);
2065 ok(!strcmp((LPCSTR
)mii
.dwTypeData
, menu_data
[i
].str
),
2066 "%u: expected dwTypeData %s, got %s\n", i
, menu_data
[i
].str
, (LPCSTR
)mii
.dwTypeData
);
2075 (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "SetMenuInfo" );
2077 (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetMenuInfo" );
2079 register_menu_check_class();
2081 test_menu_locked_by_window();
2082 test_menu_ownerdraw();
2083 test_menu_add_string();
2084 test_menu_iteminfo();
2085 test_menu_search_bycommand();
2086 test_menu_bmp_and_string();
2089 test_menu_hilitemenuitem();
2090 test_CheckMenuRadioItem();
2091 test_menu_resource_layout();