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
34 #include "wine/test.h"
36 static ATOM atomMenuCheckClass
;
38 static BOOL (WINAPI
*pSetMenuInfo
)(HMENU
,LPCMENUINFO
);
39 static BOOL (WINAPI
*pGetMenuInfo
)(HMENU
,LPCMENUINFO
);
41 static LRESULT WINAPI
menu_check_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
45 case WM_ENTERMENULOOP
:
46 /* mark window as having entered menu loop */
47 SetWindowLongPtr(hwnd
, GWLP_USERDATA
, TRUE
);
48 /* exit menu modal loop
49 * ( A SendMessage does not work on NT3.51 here ) */
50 return PostMessage(hwnd
, WM_CANCELMODE
, 0, 0);
52 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
55 /* The MSVC headers ignore our NONAMELESSUNION requests so we have to define
68 /* globals to communicate between test and wndproc */
70 static BOOL bMenuVisible
;
71 static HMENU hMenus
[4];
76 /* menu texts with their sizes */
79 SIZE size
; /* size of text up to any \t */
80 SIZE sc_size
; /* size of the short-cut */
89 unsigned int MOD_maxid
;
90 RECT MOD_rc
[MOD_NRMENUS
];
91 int MOD_avec
, MOD_hic
;
93 SIZE MODsizes
[MOD_NRMENUS
]= { {MOD_SIZE
, MOD_SIZE
},{MOD_SIZE
, MOD_SIZE
},
94 {MOD_SIZE
, MOD_SIZE
},{MOD_SIZE
, MOD_SIZE
}};
95 int MOD_GotDrawItemMsg
= FALSE
;
96 /* wndproc used by test_menu_ownerdraw() */
97 static LRESULT WINAPI
menu_ownerdraw_wnd_proc(HWND hwnd
, UINT msg
,
98 WPARAM wparam
, LPARAM lparam
)
104 MEASUREITEMSTRUCT
* pmis
= (MEASUREITEMSTRUCT
*)lparam
;
106 trace("WM_MEASUREITEM received data %lx size %dx%d\n",
107 pmis
->itemData
, pmis
->itemWidth
, pmis
->itemHeight
);
108 MOD_odheight
= pmis
->itemHeight
;
109 pmis
->itemWidth
= MODsizes
[pmis
->itemData
].cx
;
110 pmis
->itemHeight
= MODsizes
[pmis
->itemData
].cy
;
115 DRAWITEMSTRUCT
* pdis
;
118 char chrs
[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
121 pdis
= (DRAWITEMSTRUCT
*) lparam
;
122 if( winetest_debug
) {
124 GetMenuItemRect( hwnd
, (HMENU
)pdis
->hwndItem
, pdis
->itemData
,&rc
);
125 trace("WM_DRAWITEM received hwnd %p hmenu %p itemdata %ld item %d rc %ld,%ld-%ld,%ld itemrc: %ld,%ld-%ld,%ld\n",
126 hwnd
, (HMENU
)pdis
->hwndItem
, pdis
->itemData
,
127 pdis
->itemID
, pdis
->rcItem
.left
, pdis
->rcItem
.top
,
128 pdis
->rcItem
.right
,pdis
->rcItem
.bottom
,
129 rc
.left
,rc
.top
,rc
.right
,rc
.bottom
);
130 oldpen
=SelectObject( pdis
->hDC
, GetStockObject(
131 pdis
->itemState
& ODS_SELECTED
? WHITE_PEN
:BLACK_PEN
));
132 Rectangle( pdis
->hDC
, pdis
->rcItem
.left
,pdis
->rcItem
.top
,
133 pdis
->rcItem
.right
,pdis
->rcItem
.bottom
);
134 SelectObject( pdis
->hDC
, oldpen
);
136 /* calculate widths of some menu texts */
137 if( ! MOD_txtsizes
[0].size
.cx
)
138 for(i
= 0; MOD_txtsizes
[i
].text
; i
++) {
141 strcpy( buf
, MOD_txtsizes
[i
].text
);
142 if( ( p
= strchr( buf
, '\t'))) {
144 DrawText( pdis
->hDC
, p
+ 1, -1, &rc
,
145 DT_SINGLELINE
|DT_CALCRECT
);
146 MOD_txtsizes
[i
].sc_size
.cx
= rc
.right
- rc
.left
;
147 MOD_txtsizes
[i
].sc_size
.cy
= rc
.bottom
- rc
.top
;
149 DrawText( pdis
->hDC
, buf
, -1, &rc
,
150 DT_SINGLELINE
|DT_CALCRECT
);
151 MOD_txtsizes
[i
].size
.cx
= rc
.right
- rc
.left
;
152 MOD_txtsizes
[i
].size
.cy
= rc
.bottom
- rc
.top
;
155 if( pdis
->itemData
> MOD_maxid
) return TRUE
;
156 /* store the rectangl */
157 MOD_rc
[pdis
->itemData
] = pdis
->rcItem
;
158 /* calculate average character width */
159 GetTextExtentPoint( pdis
->hDC
, chrs
, 52, &sz
);
160 MOD_avec
= (sz
.cx
+ 26)/52;
161 GetTextMetrics( pdis
->hDC
, &tm
);
162 MOD_hic
= tm
.tmHeight
;
163 MOD_GotDrawItemMsg
= TRUE
;
168 PostMessage(hwnd
, WM_CANCELMODE
, 0, 0);
173 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
176 static void register_menu_check_class(void)
184 GetModuleHandle(NULL
),
186 LoadCursor(NULL
, IDC_ARROW
),
187 (HBRUSH
)(COLOR_BTNFACE
+1),
189 TEXT("WineMenuCheck"),
192 atomMenuCheckClass
= RegisterClass(&wc
);
195 /* demonstrates that windows locks the menu object so that it is still valid
196 * even after a client calls DestroyMenu on it */
197 static void test_menu_locked_by_window(void)
201 HWND hwnd
= CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass
), NULL
,
202 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
203 NULL
, NULL
, NULL
, NULL
);
204 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %ld\n", GetLastError());
205 hmenu
= CreateMenu();
206 ok(hmenu
!= NULL
, "CreateMenu failed with error %ld\n", GetLastError());
207 ret
= InsertMenu(hmenu
, 0, MF_STRING
, 0, TEXT("&Test"));
208 ok(ret
, "InsertMenu failed with error %ld\n", GetLastError());
209 ret
= SetMenu(hwnd
, hmenu
);
210 ok(ret
, "SetMenu failed with error %ld\n", GetLastError());
211 ret
= DestroyMenu(hmenu
);
212 ok(ret
, "DestroyMenu failed with error %ld\n", GetLastError());
214 ret
= DrawMenuBar(hwnd
);
216 ok(ret
, "DrawMenuBar failed with error %ld\n", GetLastError());
218 ret
= IsMenu(GetMenu(hwnd
));
219 ok(!ret
, "Menu handle should have been destroyed\n");
221 SendMessage(hwnd
, WM_SYSCOMMAND
, SC_KEYMENU
, 0);
222 /* did we process the WM_INITMENU message? */
223 ret
= GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
225 ok(ret
, "WM_INITMENU should have been sent\n");
231 static void test_menu_ownerdraw(void)
237 HWND hwnd
= CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass
), NULL
,
238 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
239 NULL
, NULL
, NULL
, NULL
);
240 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %ld\n", GetLastError());
242 SetWindowLongPtr( hwnd
, GWLP_WNDPROC
, (LONG
)menu_ownerdraw_wnd_proc
);
243 hmenu
= CreatePopupMenu();
244 ok(hmenu
!= NULL
, "CreateMenu failed with error %ld\n", GetLastError());
245 if( !hmenu
) { DestroyWindow(hwnd
);return;}
247 for( j
=0;j
<2;j
++) /* create columns */
248 for(i
=0;i
<2;i
++) { /* create rows */
249 ret
= AppendMenu( hmenu
, MF_OWNERDRAW
|
250 (i
==0 ? MF_MENUBREAK
: 0), k
, (LPCTSTR
) k
);
252 ok( ret
, "AppendMenu failed for %d\n", k
-1);
255 assert( k
<= sizeof(MOD_rc
)/sizeof(RECT
));
256 /* display the menu */
257 ret
= TrackPopupMenu( hmenu
, 0x100, 100,100, 0, hwnd
, NULL
);
259 /* columns have a 4 pixel gap between them */
260 ok( MOD_rc
[0].right
+ 4 == MOD_rc
[2].left
,
261 "item rectangles are not separated by 4 pixels space\n");
262 /* height should be what the MEASUREITEM message has returned */
263 ok( MOD_rc
[0].bottom
- MOD_rc
[0].top
== MOD_SIZE
,
264 "menu item has wrong height: %ld should be %d\n",
265 MOD_rc
[0].bottom
- MOD_rc
[0].top
, MOD_SIZE
);
266 /* no gaps between the rows */
267 ok( MOD_rc
[0].bottom
- MOD_rc
[1].top
== 0,
268 "There should not be a space between the rows, gap is %ld\n",
269 MOD_rc
[0].bottom
- MOD_rc
[1].top
);
270 /* test the correct value of the item height that was sent
271 * by the WM_MEASUREITEM message */
272 ok( MOD_odheight
== HIWORD( GetDialogBaseUnits()) || /* WinNT,2k,XP */
273 MOD_odheight
== MOD_hic
, /* Win95,98,ME */
274 "Wrong height field in MEASUREITEMSTRUCT, expected %d or %d actual %d\n",
275 HIWORD( GetDialogBaseUnits()), MOD_hic
, MOD_odheight
);
276 /* test what MF_MENUBREAK did at the first position. Also show
277 * that an MF_SEPARATOR is ignored in the height calculation. */
278 leftcol
= MOD_rc
[0].left
;
279 ModifyMenu( hmenu
, 0, MF_BYCOMMAND
| MF_OWNERDRAW
| MF_SEPARATOR
, 0, 0);
280 /* display the menu */
281 ret
= TrackPopupMenu( hmenu
, 0x100, 100,100, 0, hwnd
, NULL
);
282 /* left should be 4 pixels less now */
283 ok( leftcol
== MOD_rc
[0].left
+ 4,
284 "columns should be 4 pixels to the left (actual %ld).\n",
285 leftcol
- MOD_rc
[0].left
);
287 ok( MOD_rc
[0].right
- MOD_rc
[0].left
== 2 * MOD_avec
+ MOD_SIZE
,
288 "width of owner drawn menu item is wrong. Got %ld expected %d\n",
289 MOD_rc
[0].right
- MOD_rc
[0].left
, 2*MOD_avec
+ MOD_SIZE
);
291 ok( MOD_rc
[0].bottom
- MOD_rc
[0].top
== MOD_SIZE
,
292 "Height is incorrect. Got %ld expected %d\n",
293 MOD_rc
[0].bottom
- MOD_rc
[0].top
, MOD_SIZE
);
295 /* test width/height of an ownerdraw menu bar as well */
296 ret
= DestroyMenu(hmenu
);
297 ok(ret
, "DestroyMenu failed with error %ld\n", GetLastError());
298 hmenu
= CreateMenu();
299 ok(hmenu
!= NULL
, "CreateMenu failed with error %ld\n", GetLastError());
300 if( !hmenu
) { DestroyWindow(hwnd
);return;}
303 ret
= AppendMenu( hmenu
, MF_OWNERDRAW
, i
, 0);
304 ok( ret
, "AppendMenu failed for %d\n", i
);
306 ret
= SetMenu( hwnd
, hmenu
);
307 UpdateWindow( hwnd
); /* hack for wine to draw the window + menu */
308 ok(ret
, "SetMenu failed with error %ld\n", GetLastError());
310 ok( MOD_rc
[0].right
- MOD_rc
[0].left
== 2 * MOD_avec
+ MOD_SIZE
,
311 "width of owner drawn menu item is wrong. Got %ld expected %d\n",
312 MOD_rc
[0].right
- MOD_rc
[0].left
, 2*MOD_avec
+ MOD_SIZE
);
314 ok( MOD_rc
[0].bottom
- MOD_rc
[0].top
== GetSystemMetrics( SM_CYMENU
) - 1,
315 "Height of owner drawn menu item is wrong. Got %ld expected %d\n",
316 MOD_rc
[0].bottom
- MOD_rc
[0].top
, GetSystemMetrics( SM_CYMENU
) - 1);
319 ret
= DestroyMenu(hmenu
);
320 ok(ret
, "DestroyMenu failed with error %ld\n", GetLastError());
324 /* helper for test_menu_bmp_and_string() */
325 static void test_mbs_help( int ispop
, int hassub
, int mnuopt
,
326 HWND hwnd
, int arrowwidth
, int count
, HBITMAP hbmp
,
327 SIZE bmpsize
, char *text
, SIZE size
, SIZE sc_size
)
330 HMENU hmenu
, submenu
;
331 MENUITEMINFO mii
={ sizeof( MENUITEMINFO
)};
337 MOD_GotDrawItemMsg
= FALSE
;
338 mii
.fMask
= MIIM_FTYPE
| MIIM_DATA
| MIIM_STATE
;
340 mii
.fState
= MF_CHECKED
;
342 MODsizes
[0] = bmpsize
;
346 mii
.fMask
|= MIIM_STRING
;
347 mii
.dwTypeData
= text
;
348 if( ( p
= strchr( text
, '\t'))) {
349 hastab
= *(p
+ 1) ? 2 : 1;
352 /* tabs don't make sense in menubars */
353 if(hastab
&& !ispop
) return;
355 mii
.fMask
|= MIIM_BITMAP
;
358 submenu
= CreateMenu();
359 ok( submenu
!= 0, "CreateMenu failed with error %ld\n", GetLastError());
361 hmenu
= CreatePopupMenu();
363 hmenu
= CreateMenu();
364 ok( hmenu
!= 0, "Create{Popup}Menu failed with error %ld\n", GetLastError());
366 mii
.fMask
|= MIIM_SUBMENU
;
367 mii
.hSubMenu
= submenu
;
370 mi
.cbSize
= sizeof(mi
);
371 mi
.fMask
= MIM_STYLE
;
372 pGetMenuInfo( hmenu
, &mi
);
373 mi
.dwStyle
|= mnuopt
== 1 ? MNS_NOCHECK
: MNS_CHECKORBMP
;
374 ret
= pSetMenuInfo( hmenu
, &mi
);
375 ok( ret
, "SetMenuInfo failed with error %ld\n", GetLastError());
377 ret
= InsertMenuItem( hmenu
, 0, FALSE
, &mii
);
378 ok( ret
, "InsertMenuItem failed with error %ld\n", GetLastError());
380 if( winetest_debug
) {
382 RECT rc
= {100, 50, 400, 70};
385 sprintf( buf
,"%d text \"%s\" mnuopt %d", count
, text
? text
: "(nil)", mnuopt
);
386 FillRect( hdc
, &rc
, (HBRUSH
) COLOR_WINDOW
);
387 TextOut( hdc
, 100, 50, buf
, strlen( buf
));
388 ReleaseDC( hwnd
, hdc
);
391 ret
= TrackPopupMenu( hmenu
, 0x100, 100,100, 0, hwnd
, NULL
);
393 ret
= SetMenu( hwnd
, hmenu
);
394 ok(ret
, "SetMenu failed with error %ld\n", GetLastError());
397 ret
= GetMenuItemRect( hwnd
, hmenu
, 0, &rc
);
398 /* check menu width */
400 expect
= ( text
|| hbmp
?
401 4 + (mnuopt
!= 1 ? GetSystemMetrics(SM_CXMENUCHECK
) : 0)
403 arrowwidth
+ MOD_avec
+ (hbmp
? bmpsize
.cx
+ 2 : 0) +
404 (text
&& hastab
? /* TAB space */
405 MOD_avec
+ ( hastab
==2 ? sc_size
.cx
: 0) : 0) +
406 (text
? 2 + (text
[0] ? size
.cx
:0): 0) ;
408 expect
= !(text
|| hbmp
) ? 0 :
409 ( hbmp
? (text
? 2:0) + bmpsize
.cx
: 0 ) +
410 (text
? 2 * MOD_avec
+ (text
[0] ? size
.cx
:0): 0) ;
411 ok( rc
.right
- rc
.left
== expect
,
412 "menu width wrong, got %ld expected %d\n", rc
.right
- rc
.left
, expect
);
413 failed
= failed
|| !(rc
.right
- rc
.left
== expect
);
414 /* check menu height */
416 expect
= max( ( !(text
|| hbmp
) ? GetSystemMetrics( SM_CYMENUSIZE
)/2 : 0),
417 max( (text
? max( 2 + size
.cy
, MOD_hic
+ 4) : 0),
418 (hbmp
? bmpsize
.cy
+ 2 : 0)));
420 expect
= ( !(text
|| hbmp
) ? GetSystemMetrics( SM_CYMENUSIZE
)/2 :
421 max( GetSystemMetrics( SM_CYMENU
) - 1, (hbmp
? bmpsize
.cy
: 0)));
422 ok( rc
.bottom
- rc
.top
== expect
,
423 "menu height wrong, got %ld expected %d (%d)\n",
424 rc
.bottom
- rc
.top
, expect
, GetSystemMetrics( SM_CYMENU
));
425 failed
= failed
|| !(rc
.bottom
- rc
.top
== expect
);
426 if( hbmp
== HBMMENU_CALLBACK
&& MOD_GotDrawItemMsg
) {
427 /* check the position of the bitmap */
429 expect
= ispop
? (4 + ( mnuopt
? 0 : GetSystemMetrics(SM_CXMENUCHECK
)))
431 ok( expect
== MOD_rc
[0].left
,
432 "bitmap left is %ld expected %d\n", MOD_rc
[0].left
, expect
);
433 failed
= failed
|| !(expect
== MOD_rc
[0].left
);
435 expect
= (rc
.bottom
- rc
.top
- MOD_rc
[0].bottom
+ MOD_rc
[0].top
) / 2;
436 ok( expect
== MOD_rc
[0].top
,
437 "bitmap top is %ld expected %d\n", MOD_rc
[0].top
, expect
);
438 failed
= failed
|| !(expect
== MOD_rc
[0].top
);
440 /* if there was a failure, report details */
442 trace("*** count %d text \"%s\" bitmap %p bmsize %ld,%ld textsize %ld+%ld,%ld mnuopt %d hastab %d\n",
443 count
, text
? text
: "(nil)", hbmp
, bmpsize
.cx
, bmpsize
.cy
,
444 size
.cx
, size
.cy
, sc_size
.cx
, mnuopt
, hastab
);
445 trace(" check %d,%d arrow %d avechar %d\n",
446 GetSystemMetrics(SM_CXMENUCHECK
),
447 GetSystemMetrics(SM_CYMENUCHECK
),arrowwidth
, MOD_avec
);
448 if( hbmp
== HBMMENU_CALLBACK
)
449 trace( " rc %ld,%ld-%ld,%ld bmp.rc %ld,%ld-%ld,%ld\n",
450 rc
.left
, rc
.top
, rc
.top
, rc
.bottom
, MOD_rc
[0].left
,
451 MOD_rc
[0].top
,MOD_rc
[0].right
, MOD_rc
[0].bottom
);
454 ret
= DestroyMenu(submenu
);
455 ok(ret
, "DestroyMenu failed with error %ld\n", GetLastError());
456 ret
= DestroyMenu(hmenu
);
457 ok(ret
, "DestroyMenu failed with error %ld\n", GetLastError());
461 static void test_menu_bmp_and_string(void)
468 int count
, szidx
, txtidx
, bmpidx
, hassub
, mnuopt
, ispop
;
470 if( !pGetMenuInfo
) return;
472 memset( bmfill
, 0x55, sizeof( bmfill
));
473 hwnd
= CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass
), NULL
,
474 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
475 NULL
, NULL
, NULL
, NULL
);
476 hbm_arrow
=LoadBitmap( 0, (CHAR
*)OBM_MNARROW
);
477 GetObject( hbm_arrow
, sizeof(bm
), &bm
);
478 arrowwidth
= bm
.bmWidth
;
480 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %ld\n", GetLastError());
482 SetWindowLongPtr( hwnd
, GWLP_WNDPROC
, (LONG
)menu_ownerdraw_wnd_proc
);
485 trace(" check %d,%d arrow %d avechar %d\n",
486 GetSystemMetrics(SM_CXMENUCHECK
),
487 GetSystemMetrics(SM_CYMENUCHECK
),arrowwidth
, MOD_avec
);
490 for( ispop
=1; ispop
>= 0; ispop
--){
491 static SIZE bmsizes
[]= {
492 {10,10},{38,38},{1,30},{55,5}};
493 for( szidx
=0; szidx
< sizeof( bmsizes
) / sizeof( SIZE
); szidx
++) {
494 HBITMAP hbm
= CreateBitmap( bmsizes
[szidx
].cx
, bmsizes
[szidx
].cy
,1,1,bmfill
);
495 HBITMAP bitmaps
[] = { HBMMENU_CALLBACK
, hbm
, NULL
};
496 ok( (int)hbm
, "CreateBitmap failed err %ld\n", GetLastError());
497 for( txtidx
= 0; txtidx
< sizeof(MOD_txtsizes
)/sizeof(MOD_txtsizes
[0]); txtidx
++) {
498 for( hassub
= 0; hassub
< 2 ; hassub
++) { /* add submenu item */
499 for( mnuopt
= 0; mnuopt
< 3 ; mnuopt
++){ /* test MNS_NOCHECK/MNS_CHECKORBMP */
500 for( bmpidx
= 0; bmpidx
<sizeof(bitmaps
)/sizeof(HBITMAP
); bmpidx
++) {
501 /* no need to test NULL bitmaps of several sizes */
502 if( !bitmaps
[bmpidx
] && szidx
> 0) continue;
503 if( !ispop
&& hassub
) continue;
504 test_mbs_help( ispop
, hassub
, mnuopt
,
505 hwnd
, arrowwidth
, ++count
,
508 MOD_txtsizes
[txtidx
].text
,
509 MOD_txtsizes
[txtidx
].size
,
510 MOD_txtsizes
[txtidx
].sc_size
);
522 static void test_menu_add_string( void )
532 WCHAR strbackW
[0x80];
533 static const WCHAR expectedString
[] = {'D', 'u', 'm', 'm', 'y', ' ',
534 's', 't', 'r', 'i', 'n', 'g', 0};
536 hmenu
= CreateMenu();
538 memset( &info
, 0, sizeof info
);
539 info
.cbSize
= sizeof info
;
540 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_ID
;
541 info
.dwTypeData
= "blah";
546 InsertMenuItem(hmenu
, 0, TRUE
, &info
);
548 memset( &info
, 0, sizeof info
);
549 info
.cbSize
= sizeof info
;
550 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_DATA
| MIIM_ID
;
551 info
.dwTypeData
= string
;
552 info
.cch
= sizeof string
;
554 GetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
556 ok( !strcmp( string
, "blah" ), "menu item name differed\n");
558 /* Test combination of ownerdraw and strings with GetMenuItemString(A/W) */
559 strcpy(string
, "Dummy string");
560 memset(&info
, 0x00, sizeof(info
));
561 info
.cbSize
= sizeof(MENUITEMINFO
);
562 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
; /* Set OwnerDraw + typeData */
563 info
.fType
= MFT_OWNERDRAW
;
564 info
.dwTypeData
= string
;
565 rc
= InsertMenuItem( hmenu
, 0, TRUE
, &info
);
566 ok (rc
, "InsertMenuItem failed\n");
568 strcpy(string
,"Garbage");
569 ok (GetMenuString( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
570 ok (!strcmp( strback
, "Dummy string" ), "Menu text from Ansi version incorrect\n");
572 ok (GetMenuStringW( hmenu
, 0, (WCHAR
*)strbackW
, 99, MF_BYPOSITION
), "GetMenuStringW on ownerdraw entry failed\n");
573 ok (!lstrcmpW( strbackW
, expectedString
), "Menu text from Unicode version incorrect\n");
575 /* Just change ftype to string and see what text is stored */
576 memset(&info
, 0x00, sizeof(info
));
577 info
.cbSize
= sizeof(MENUITEMINFO
);
578 info
.fMask
= MIIM_FTYPE
; /* Set string type */
579 info
.fType
= MFT_STRING
;
580 info
.dwTypeData
= (char *)0xdeadbeef;
581 rc
= SetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
582 ok (rc
, "SetMenuItemInfo failed\n");
584 /* Did we keep the old dwTypeData? */
585 ok (GetMenuString( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
586 ok (!strcmp( strback
, "Dummy string" ), "Menu text from Ansi version incorrect\n");
588 /* Ensure change to bitmap type fails */
589 memset(&info
, 0x00, sizeof(info
));
590 info
.cbSize
= sizeof(MENUITEMINFO
);
591 info
.fMask
= MIIM_FTYPE
; /* Set as bitmap type */
592 info
.fType
= MFT_BITMAP
;
593 info
.dwTypeData
= (char *)0xdeadbee2;
594 rc
= SetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
595 ok (!rc
, "SetMenuItemInfo unexpectedly worked\n");
597 /* Just change ftype back and ensure data hasn't been freed */
598 info
.fType
= MFT_OWNERDRAW
; /* Set as ownerdraw type */
599 info
.dwTypeData
= (char *)0xdeadbee3;
600 rc
= SetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
601 ok (rc
, "SetMenuItemInfo failed\n");
603 /* Did we keep the old dwTypeData? */
604 ok (GetMenuString( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
605 ok (!strcmp( strback
, "Dummy string" ), "Menu text from Ansi version incorrect\n");
607 /* Just change string value (not type) */
608 memset(&info
, 0x00, sizeof(info
));
609 info
.cbSize
= sizeof(MENUITEMINFO
);
610 info
.fMask
= MIIM_STRING
; /* Set typeData */
611 strcpy(string2
, "string2");
612 info
.dwTypeData
= string2
;
613 rc
= SetMenuItemInfo( hmenu
, 0, TRUE
, &info
);
614 ok (rc
, "SetMenuItemInfo failed\n");
616 ok (GetMenuString( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
617 ok (!strcmp( strback
, "string2" ), "Menu text from Ansi version incorrect\n");
619 /* crashes with wine 0.9.5 */
620 memset(&info
, 0x00, sizeof(info
));
621 info
.cbSize
= sizeof(MENUITEMINFO
);
622 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
; /* Set OwnerDraw + typeData */
623 info
.fType
= MFT_OWNERDRAW
;
624 rc
= InsertMenuItem( hmenu
, 0, TRUE
, &info
);
625 ok (rc
, "InsertMenuItem failed\n");
626 ok (!GetMenuString( hmenu
, 0, NULL
, 0, MF_BYPOSITION
),
627 "GetMenuString on ownerdraw entry succeeded.\n");
628 ok (!GetMenuStringW( hmenu
, 0, NULL
, 0, MF_BYPOSITION
),
629 "GetMenuStringW on ownerdraw entry succeeded.\n");
632 DestroyMenu( hmenu
);
635 /* define building blocks for the menu item info tests */
636 static int strncmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
638 if (n
<= 0) return 0;
639 while ((--n
> 0) && *str1
&& (*str1
== *str2
)) { str1
++; str2
++; }
640 return *str1
- *str2
;
643 static WCHAR
*strcpyW( WCHAR
*dst
, const WCHAR
*src
)
646 while ((*p
++ = *src
++));
651 #define DMIINFF( i, e, field)\
652 ok((int)((i)->field)==(int)((e)->field) || (int)((i)->field)==(0xffff & (int)((e)->field)), \
653 "%s got 0x%x expected 0x%x\n", #field, (int)((i)->field), (int)((e)->field));
655 #define DUMPMIINF(s,i,e)\
657 DMIINFF( i, e, fMask)\
658 DMIINFF( i, e, fType)\
659 DMIINFF( i, e, fState)\
661 DMIINFF( i, e, hSubMenu)\
662 DMIINFF( i, e, hbmpChecked)\
663 DMIINFF( i, e, hbmpUnchecked)\
664 DMIINFF( i, e, dwItemData)\
665 DMIINFF( i, e, dwTypeData)\
667 if( s==sizeof(MENUITEMINFOA)) DMIINFF( i, e, hbmpItem)\
670 /* insert menu item */
671 #define TMII_INSMI( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
674 MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
675 HMENU hmenu = CreateMenu();\
676 BOOL ret, stop = FALSE;\
677 SetLastError( 0xdeadbeef);\
678 if(ansi)strcpy( string, init);\
679 else strcpyW( (WCHAR*)string, (WCHAR*)init);\
680 if( ansi) ret = InsertMenuItemA(hmenu, 0, TRUE, &info1 );\
681 else ret = InsertMenuItemW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
682 if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
684 } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
687 /* GetMenuItemInfo + GetMenuString */
688 #define TMII_GMII( a2,b2,c2,d2,e2,f2,g2,h2,i2,j2,k2,l2,m2,n2,\
689 a3,b3,c3,d3,e3,f3,g3,h3,i3,j3,k3,l3,m3,n3,\
690 expname, eret2, eret3)\
692 MENUITEMINFOA info2A=a2 b2,c2,d2,e2,f2,(void*)g2,(void*)h2,(void*)i2,j2,(void*)k2,l2,(void*)m2 n2;\
693 MENUITEMINFOA einfoA=a3 b3,c3,d3,e3,f3,(void*)g3,(void*)h3,(void*)i3,j3,(void*)k3,l3,(void*)m3 n3;\
694 MENUITEMINFOA *info2 = &info2A;\
695 MENUITEMINFOA *einfo = &einfoA;\
696 MENUITEMINFOW *info2W = (MENUITEMINFOW *)&info2A;\
698 ret = ansi ? GetMenuItemInfoA( hmenu, 0, TRUE, info2 ) :\
699 GetMenuItemInfoW( hmenu, 0, TRUE, info2W );\
700 if( !(eret2)) ok( (eret2)==ret,"GetMenuItemInfo should have failed.\n");\
702 ok( (eret2)==ret,"GetMenuItemInfo failed, err %ld\n",GetLastError());\
703 ret = memcmp( info2, einfo, sizeof einfoA);\
704 /* ok( ret==0, "Got wrong menu item info data\n");*/\
705 if( ret) DUMPMIINF(info2A.cbSize, &info2A, &einfoA)\
706 if( einfo->dwTypeData == string) {\
707 if(ansi) ok( !strncmp( expname, info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
708 einfo->dwTypeData ? einfo->dwTypeData: "");\
709 else ok( !strncmpW( (WCHAR*)expname, (WCHAR*)info2->dwTypeData, einfo->cch ), "menu item name differed \"%s\"\n",\
710 einfo->dwTypeData ? einfo->dwTypeData: "");\
711 ret = ansi ? GetMenuStringA( hmenu, 0, string, 80, MF_BYPOSITION) :\
712 GetMenuStringW( hmenu, 0, string, 80, MF_BYPOSITION);\
714 ok( ret, "GetMenuString failed, err %ld\n",GetLastError());\
716 ok( !ret, "GetMenuString should have failed\n");\
723 RemoveMenu(hmenu, 0, TRUE );\
724 DestroyMenu( hmenu );\
725 DestroyMenu( submenu );\
726 submenu = CreateMenu();\
729 #define TMII_MODM( flags, id, data, eret )\
731 if(ansi)ret = ModifyMenuA( hmenu, 0, flags, (UINT_PTR)id, (char*)data);\
732 else ret = ModifyMenuW( hmenu, 0, flags, (UINT_PTR)id, (WCHAR*)data);\
733 if( !(eret)) ok( (eret)==ret,"ModifyMenuA should have failed.\n");\
734 else ok( (eret)==ret,"ModifyMenuA failed, err %ld\n",GetLastError());\
737 /* SetMenuItemInfo */
738 #define TMII_SMII( a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,\
741 MENUITEMINFOA info1=a1 b1,c1,d1,e1,f1,(void*)g1,(void*)h1,(void*)i1,j1,(void*)k1,l1,(void*)m1 n1;\
742 SetLastError( 0xdeadbeef);\
743 if(ansi)strcpy( string, init);\
744 else strcpyW( (WCHAR*)string, (WCHAR*)init);\
745 if( ansi) ret = SetMenuItemInfoA(hmenu, 0, TRUE, &info1 );\
746 else ret = SetMenuItemInfoW(hmenu, 0, TRUE, (MENUITEMINFOW*)&info1 );\
747 if( !(eret1)) { ok( (eret1)==ret,"InsertMenuItem should have failed.\n");\
749 } else ok( (eret1)==ret,"InsertMenuItem failed, err %ld\n",GetLastError());\
758 static void test_menu_iteminfo( void )
760 int S
=sizeof( MENUITEMINFOA
);
765 WCHAR txtW
[]={'W','i','n','e',0};
766 WCHAR initW
[]={'X','Y','Z',0};
768 void *txt
, *init
, *empty
, *string
;
769 HBITMAP hbm
= CreateBitmap(1,1,1,1,NULL
);
771 HMENU submenu
=CreateMenu();
774 if( ansi
) {txt
=txtA
;init
=initA
;empty
=emptyA
;string
=stringA
;}
775 else {txt
=txtW
;init
=initW
;empty
=emptyW
;string
=stringA
;}
776 trace( "%s string %p hbm %p txt %p\n", ansi
? "ANSI tests: " : "Unicode tests:", string
, hbm
, txt
);
777 /* test all combinations of MFT_STRING, MFT_OWNERDRAW and MFT_BITMAP */
778 /* (since MFT_STRING is zero, there are four of them) */
779 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, 0, 0, 0, 0, 0, 0, txt
, 0, 0, }, OK
)
780 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
781 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, 0, },
784 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
785 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
786 {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
789 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, 6, -1, }, OK
)
790 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
791 {, S
, MIIM_TYPE
, MFT_BITMAP
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
794 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, hbm
, 6, -1, }, OK
)
795 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
796 {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
799 /* not enough space for name*/
800 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
801 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, NULL
, 0, -9, },
802 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, NULL
, 4, 0, },
805 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
806 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 5, -9, },
807 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, 0, },
810 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
811 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 4, -9, },
812 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 3, 0, },
815 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
816 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, NULL
, 0, -9, },
817 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 0, 0, },
820 /* cannot combine MIIM_TYPE with some other flags */
821 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_STRING
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, ER
)
822 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
823 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
826 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
827 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_STRING
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
828 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
831 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_FTYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, ER
)
832 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
833 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
836 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
837 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
838 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
841 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_BITMAP
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, hbm
, 6, hbm
, }, ER
)
842 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
843 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
846 /* but succeeds with some others */
847 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
848 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_SUBMENU
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
849 {, S
, MIIM_TYPE
|MIIM_SUBMENU
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, 0, },
852 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
853 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_STATE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
854 {, S
, MIIM_TYPE
|MIIM_STATE
, MFT_STRING
, 0, -9, 0, -9, -9, -9, string
, 4, 0, },
857 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_ID
, MFT_STRING
, -1, 888, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
858 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
859 {, S
, MIIM_TYPE
|MIIM_ID
, MFT_STRING
, -9, 888, 0, -9, -9, -9, string
, 4, 0, },
862 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
, -1, -1, -1, -1, -1, 999, txt
, 6, -1, }, OK
)
863 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
864 {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
, -9, -9, 0, -9, -9, 999, string
, 4, 0, },
867 /* to be continued */
868 /* set text with MIIM_TYPE and retrieve with MIIM_STRING */
869 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
870 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
871 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, -9, },
874 /* set text with MIIM_TYPE and retrieve with MIIM_STRING; MFT_OWNERDRAW causes an empty string */
875 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
876 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
877 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
880 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
881 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
882 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
885 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
886 TMII_GMII ( {, S
, MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
887 {, S
, MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 80, -9, },
890 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
891 TMII_GMII ( {, S
, 0, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
892 {, S
, 0, -9, -9, -9, 0, -9, -9, -9, string
, 80, -9, },
895 /* contrary to MIIM_TYPE,you can set the text for an owner draw menu */
896 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
897 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
898 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 4, -9, },
901 /* same but retrieve with MIIM_TYPE */
902 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
903 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
904 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
907 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
908 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
909 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
912 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, NULL
, 0, -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_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
918 /* How is that with bitmaps? */
919 TMII_INSMI( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
920 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
921 {, S
, MIIM_TYPE
, MFT_BITMAP
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
924 TMII_INSMI( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
925 TMII_GMII ( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
926 {, S
, MIIM_BITMAP
|MIIM_FTYPE
, 0, -9, -9, 0, -9, -9, -9, string
, 80, hbm
, },
929 /* MIIM_BITMAP does not like MFT_BITMAP */
930 TMII_INSMI( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, ER
)
931 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
932 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
935 /* no problem with OWNERDRAWN */
936 TMII_INSMI( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
937 TMII_GMII ( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
938 {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 80, hbm
, },
941 /* setting MFT_BITMAP with MFT_FTYPE fails anyway */
942 TMII_INSMI( {, S
, MIIM_FTYPE
, MFT_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, ER
)
943 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
944 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
948 /* menu with submenu */
949 TMII_INSMI( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, submenu
, -1, -1, -1, txt
, 0, -1, }, OK
)
950 TMII_GMII ( {, S
, MIIM_SUBMENU
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
951 {, S
, MIIM_SUBMENU
, -9, -9, -9, submenu
, -9, -9, -9, string
, 80, -9, },
954 TMII_INSMI( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, submenu
, -1, -1, -1, empty
, 0, -1, }, OK
)
955 TMII_GMII ( {, S
, MIIM_SUBMENU
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
956 {, S
, MIIM_SUBMENU
, -9, -9, -9, submenu
, -9, -9, -9, string
, 80, -9, },
959 /* menu with submenu, without MIIM_SUBMENU the submenufield is cleared */
960 TMII_INSMI( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, submenu
, -1, -1, -1, txt
, 0, -1, }, OK
)
961 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
962 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 0, -9, },
964 TMII_GMII ( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
965 {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_SEPARATOR
, -9, -9, submenu
, -9, -9, -9, string
, 80, -9, },
968 /* menu with invalid submenu */
969 TMII_INSMI( {, S
, MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, 999, -1, -1, -1, txt
, 0, -1, }, ER
)
970 TMII_GMII ( {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
971 {, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, },
975 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, txt
, 0, 0, }, OK
)
976 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
977 {, S
, MIIM_TYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
980 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, hbm
, 6, -1, }, OK
)
981 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
982 {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, hbm
, 0, hbm
, },
985 /* SEPARATOR and STRING go well together */
986 /* BITMAP and STRING go well together */
987 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
988 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
989 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, hbm
, },
992 /* BITMAP, SEPARATOR and STRING go well together */
993 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
994 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
995 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 4, hbm
, },
998 /* last two tests, but use MIIM_TYPE to retrieve info */
999 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
1000 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1001 {, S
, MIIM_TYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1004 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1005 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1006 {, S
, MIIM_TYPE
, MFT_BITMAP
, -9, -9, 0, -9, -9, -9, hbm
, 4, hbm
, },
1009 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1010 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1011 {, S
, MIIM_TYPE
, MFT_SEPARATOR
|MFT_BITMAP
, -9, -9, 0, -9, -9, -9, hbm
, 4, hbm
, },
1014 /* same three with MFT_OWNERDRAW */
1015 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, -1, }, OK
)
1016 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1017 {, S
, MIIM_TYPE
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1020 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1021 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1022 {, S
, MIIM_TYPE
, MFT_BITMAP
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, hbm
, 4, hbm
, },
1025 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1026 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1027 {, S
, MIIM_TYPE
, MFT_SEPARATOR
|MFT_BITMAP
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, hbm
, 4, hbm
, },
1031 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
|MIIM_ID
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
1032 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1033 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1036 /* test with modifymenu: string is preserved after seting OWNERDRAW */
1037 TMII_INSMI( {, S
, MIIM_STRING
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
1038 TMII_MODM( MFT_OWNERDRAW
, -1, 787, OK
)
1039 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1040 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_DATA
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, 787, string
, 4, -9, },
1043 /* same with bitmap: now the text is cleared */
1044 TMII_INSMI( {, S
, MIIM_STRING
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
1045 TMII_MODM( MFT_BITMAP
, 545, hbm
, OK
)
1046 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1047 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_BITMAP
, -9, 545, 0, -9, -9, -9, string
, 0, hbm
, },
1050 /* start with bitmap: now setting text clears it (though he flag is raised) */
1051 TMII_INSMI( {, S
, MIIM_BITMAP
, MFT_STRING
, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1052 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1053 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_STRING
, -9, 0, 0, -9, -9, -9, string
, 0, hbm
, },
1055 TMII_MODM( MFT_STRING
, 545, txt
, OK
)
1056 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1057 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_STRING
, -9, 545, 0, -9, -9, -9, string
, 4, 0, },
1060 /*repeat with text NULL */
1061 TMII_INSMI( {, S
, MIIM_BITMAP
, MFT_STRING
, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1062 TMII_MODM( MFT_STRING
, 545, NULL
, OK
)
1063 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1064 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_SEPARATOR
, -9, 545, 0, -9, -9, -9, string
, 0, 0, },
1067 /* repeat with text "" */
1068 TMII_INSMI( {, S
, MIIM_BITMAP
, -1 , -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1069 TMII_MODM( MFT_STRING
, 545, empty
, OK
)
1070 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1071 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, MFT_STRING
, -9, 545, 0, -9, -9, -9, string
, 0, 0, },
1074 /* start with bitmap: set ownerdraw */
1075 TMII_INSMI( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1076 TMII_MODM( MFT_OWNERDRAW
, -1, 232, OK
)
1077 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1078 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_DATA
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, 232, string
, 0, hbm
, },
1082 TMII_INSMI( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1083 TMII_GMII ( {, S
, 0, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1084 {, S
, 0, -9, -9, -9, 0, -9, -9, -9, string
, 80, -9, },
1087 /* some tests with small cbSize: the hbmpItem is to be ignored */
1088 TMII_INSMI( {, S
- 4, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1089 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1090 {, S
, MIIM_TYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, NULL
, 0, NULL
, },
1093 TMII_INSMI( {, S
- 4, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1094 TMII_GMII ( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1095 {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 80, NULL
, },
1098 TMII_INSMI( {, S
- 4, MIIM_STRING
|MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1099 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1100 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, NULL
, },
1103 TMII_INSMI( {, S
- 4, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1104 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1105 {, S
, MIIM_TYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1108 TMII_INSMI( {, S
- 4, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1109 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1110 {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1113 TMII_INSMI( {, S
- 4, MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, txt
, 6, hbm
, }, OK
)
1114 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1115 {, S
, MIIM_TYPE
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, NULL
, 4, NULL
, },
1118 /* MIIM_TYPE by itself does not get/set the dwItemData for OwnerDrawn menus */
1119 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, 343, txt
, 0, -1, }, OK
)
1120 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1121 {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, 343, 0, 0, 0, },
1124 TMII_INSMI( {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, 343, txt
, 0, -1, }, OK
)
1125 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1126 {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, 0, 0, 0, },
1129 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, -1, -1, -1, 343, txt
, 0, -1, }, OK
)
1130 TMII_GMII ( {, S
, MIIM_TYPE
|MIIM_DATA
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1131 {, S
, MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -9, -9, 0, -9, -9, 0, 0, 0, 0, },
1134 /* set a string menu to ownerdraw with MIIM_TYPE */
1135 TMII_INSMI( {, S
, MIIM_TYPE
, MFT_STRING
, -2, -2, -2, -2, -2, -2, txt
, -2, -2, }, OK
)
1136 TMII_SMII( {, S
, MIIM_TYPE
, MFT_OWNERDRAW
, -1, -1, -1, -1, -1, -1, -1, -1, -1, }, OK
)
1137 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1138 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_OWNERDRAW
, -9, -9, 0, -9, -9, -9, string
, 4, -9, },
1141 /* test with modifymenu add submenu */
1142 TMII_INSMI( {, S
, MIIM_STRING
, MFT_STRING
, -1, -1, -1, -1, -1, -1, txt
, 0, -1, }, OK
)
1143 TMII_MODM( MF_POPUP
, submenu
, txt
, OK
)
1144 TMII_GMII ( {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_SUBMENU
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1145 {, S
, MIIM_FTYPE
|MIIM_STRING
|MIIM_SUBMENU
, MFT_STRING
, -9, -9, submenu
, -9, -9, -9, string
, 4, -9, },
1147 TMII_GMII ( {, S
, MIIM_TYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1148 {, S
, MIIM_TYPE
, MFT_STRING
, -9, -9, 0, -9, -9, -9, string
, 4, 0, },
1151 /* MFT_SEPARATOR bit is kept when the text is added */
1152 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
1153 TMII_SMII( {, S
, MIIM_STRING
, -1, -1, -1, -1, -1, -1, -1, txt
, -1, -1, }, OK
)
1154 TMII_GMII ( {, S
, MIIM_STRING
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1155 {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 4, -9, },
1158 /* MFT_SEPARATOR bit is kept when bitmap is added */
1159 TMII_INSMI( {, S
, MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, -1, -1, -1, -1, NULL
, 0, -1, }, OK
)
1160 TMII_SMII( {, S
, MIIM_BITMAP
, -1, -1, -1, -1, -1, -1, -1, -1, -1, hbm
, }, OK
)
1161 TMII_GMII ( {, S
, MIIM_BITMAP
|MIIM_FTYPE
, -9, -9, -9, -9, -9, -9, -9, string
, 80, -9, },
1162 {, S
, MIIM_BITMAP
|MIIM_FTYPE
, MFT_SEPARATOR
, -9, -9, 0, -9, -9, -9, string
, 80, hbm
, },
1166 } while( !(ansi
= !ansi
) );
1171 The following tests try to confirm the algorithm used to return the menu items
1172 when there is a collision between a menu item and a popup menu
1174 void test_menu_search_bycommand( void )
1176 HMENU hmenu
, hmenuSub
, hmenuSub2
;
1183 /* Case 1: Menu containing a menu item */
1184 hmenu
= CreateMenu();
1186 memset( &info
, 0, sizeof info
);
1187 info
.cbSize
= sizeof info
;
1188 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1189 info
.fType
= MFT_STRING
;
1190 strcpy(strIn
, "Case 1 MenuItem");
1191 info
.dwTypeData
= strIn
;
1192 info
.wID
= (UINT
) 0x1234;
1194 rc
= InsertMenuItem(hmenu
, 0, TRUE
, &info
);
1195 ok (rc
, "Inserting the menuitem failed\n");
1197 id
= GetMenuItemID(hmenu
, 0);
1198 ok (id
== 0x1234, "Getting the menuitem id failed(gave %x)\n", id
);
1200 /* Confirm the menuitem was given the id supplied (getting by position) */
1201 memset( &info
, 0, sizeof info
);
1203 info
.cbSize
= sizeof(MENUITEMINFO
);
1204 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1205 info
.dwTypeData
= strback
;
1206 info
.cch
= sizeof(strback
);
1208 rc
= GetMenuItemInfo(hmenu
, 0, TRUE
, &info
); /* Get by position */
1209 ok (rc
, "Getting the menu items info failed\n");
1210 ok (info
.wID
== 0x1234, "IDs differ for the menuitem\n");
1211 ok (!strcmp(info
.dwTypeData
, "Case 1 MenuItem"), "Returned item has wrong label\n");
1213 /* Search by id - Should return the item */
1214 memset( &info
, 0, sizeof info
);
1216 info
.cbSize
= sizeof(MENUITEMINFO
);
1217 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1218 info
.dwTypeData
= strback
;
1219 info
.cch
= sizeof(strback
);
1220 rc
= GetMenuItemInfo(hmenu
, 0x1234, FALSE
, &info
); /* Get by ID */
1222 ok (rc
, "Getting the menu items info failed\n");
1223 ok (info
.wID
== 0x1234, "IDs differ for the menuitem\n");
1224 ok (!strcmp(info
.dwTypeData
, "Case 1 MenuItem"), "Returned item has wrong label\n");
1226 DestroyMenu( hmenu
);
1228 /* Case 2: Menu containing a popup menu */
1229 hmenu
= CreateMenu();
1230 hmenuSub
= CreateMenu();
1232 strcpy(strIn
, "Case 2 SubMenu");
1233 rc
= InsertMenu(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, strIn
);
1234 ok (rc
, "Inserting the popup menu into the main menu failed\n");
1236 id
= GetMenuItemID(hmenu
, 0);
1237 ok (id
== -1, "Getting the menuitem id unexpectedly worked (gave %x)\n", id
);
1239 /* Confirm the menuitem itself was given an id the same as the HMENU, (getting by position) */
1240 memset( &info
, 0, sizeof info
);
1242 info
.cbSize
= sizeof(MENUITEMINFO
);
1243 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1244 info
.dwTypeData
= strback
;
1245 info
.cch
= sizeof(strback
);
1246 info
.wID
= 0xdeadbeef;
1248 rc
= GetMenuItemInfo(hmenu
, 0, TRUE
, &info
); /* Get by position */
1249 ok (rc
, "Getting the menu items info failed\n");
1250 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the menuitem\n");
1251 ok (!strcmp(info
.dwTypeData
, "Case 2 SubMenu"), "Returned item has wrong label\n");
1253 /* Search by id - returns the popup menu itself */
1254 memset( &info
, 0, sizeof info
);
1256 info
.cbSize
= sizeof(MENUITEMINFO
);
1257 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1258 info
.dwTypeData
= strback
;
1259 info
.cch
= sizeof(strback
);
1260 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
); /* Get by ID */
1262 ok (rc
, "Getting the menu items info failed\n");
1263 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the popup menu\n");
1264 ok (!strcmp(info
.dwTypeData
, "Case 2 SubMenu"), "Returned item has wrong label\n");
1267 Now add an item after it with the same id
1269 memset( &info
, 0, sizeof info
);
1270 info
.cbSize
= sizeof info
;
1271 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1272 info
.fType
= MFT_STRING
;
1273 strcpy(strIn
, "Case 2 MenuItem 1");
1274 info
.dwTypeData
= strIn
;
1275 info
.wID
= (UINT_PTR
) hmenuSub
;
1276 rc
= InsertMenuItem(hmenu
, -1, TRUE
, &info
);
1277 ok (rc
, "Inserting the menuitem failed\n");
1279 /* Search by id - returns the item which follows the popup menu */
1280 memset( &info
, 0, sizeof info
);
1282 info
.cbSize
= sizeof(MENUITEMINFO
);
1283 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1284 info
.dwTypeData
= strback
;
1285 info
.cch
= sizeof(strback
);
1286 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
); /* Get by ID */
1288 ok (rc
, "Getting the menu items info failed\n");
1289 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the popup menu\n");
1290 ok (!strcmp(info
.dwTypeData
, "Case 2 MenuItem 1"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1293 Now add an item before the popup (with the same id)
1295 memset( &info
, 0, sizeof info
);
1296 info
.cbSize
= sizeof info
;
1297 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1298 info
.fType
= MFT_STRING
;
1299 strcpy(strIn
, "Case 2 MenuItem 2");
1300 info
.dwTypeData
= strIn
;
1301 info
.wID
= (UINT_PTR
) hmenuSub
;
1302 rc
= InsertMenuItem(hmenu
, 0, TRUE
, &info
);
1303 ok (rc
, "Inserting the menuitem failed\n");
1305 /* Search by id - returns the item which precedes the popup menu */
1306 memset( &info
, 0, sizeof info
);
1308 info
.cbSize
= sizeof(MENUITEMINFO
);
1309 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1310 info
.dwTypeData
= strback
;
1311 info
.cch
= sizeof(strback
);
1312 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
); /* Get by ID */
1314 ok (rc
, "Getting the menu items info failed\n");
1315 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the popup menu\n");
1316 ok (!strcmp(info
.dwTypeData
, "Case 2 MenuItem 2"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1318 DestroyMenu( hmenu
);
1319 DestroyMenu( hmenuSub
);
1322 Case 3: Menu containing a popup menu which in turn
1323 contains 2 items with the same id as the popup itself
1326 hmenu
= CreateMenu();
1327 hmenuSub
= CreateMenu();
1329 memset( &info
, 0, sizeof info
);
1330 info
.cbSize
= sizeof info
;
1331 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1332 info
.fType
= MFT_STRING
;
1333 info
.dwTypeData
= "MenuItem";
1334 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
1336 rc
= InsertMenu(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, "Submenu");
1337 ok (rc
, "Inserting the popup menu into the main menu failed\n");
1339 rc
= InsertMenuItem(hmenuSub
, 0, TRUE
, &info
);
1340 ok (rc
, "Inserting the sub menu menuitem failed\n");
1342 memset( &info
, 0, sizeof info
);
1343 info
.cbSize
= sizeof info
;
1344 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1345 info
.fType
= MFT_STRING
;
1346 info
.dwTypeData
= "MenuItem 2";
1347 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
1349 rc
= InsertMenuItem(hmenuSub
, 1, TRUE
, &info
);
1350 ok (rc
, "Inserting the sub menu menuitem 2 failed\n");
1352 /* Prove that you can't query the id of a popup directly (By position) */
1353 id
= GetMenuItemID(hmenu
, 0);
1354 ok (id
== -1, "Getting the sub menu id should have failed because its a popup (gave %x)\n", id
);
1356 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
1357 memset( &info
, 0, sizeof info
);
1359 info
.cbSize
= sizeof(MENUITEMINFO
);
1360 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1361 info
.dwTypeData
= strback
;
1362 info
.cch
= sizeof(strback
);
1364 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
);
1365 ok (rc
, "Getting the menus info failed\n");
1366 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for popup menu\n");
1367 ok (!strcmp(info
.dwTypeData
, "MenuItem"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1368 DestroyMenu( hmenu
);
1369 DestroyMenu( hmenuSub
);
1372 Case 4: Menu containing 2 popup menus, the second
1373 contains 2 items with the same id as the first popup menu
1375 hmenu
= CreateMenu();
1376 hmenuSub
= CreateMenu();
1377 hmenuSub2
= CreateMenu();
1379 rc
= InsertMenu(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, "Submenu");
1380 ok (rc
, "Inserting the popup menu into the main menu failed\n");
1382 rc
= InsertMenu(hmenu
, 1, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub2
, "Submenu2");
1383 ok (rc
, "Inserting the popup menu into the main menu failed\n");
1385 memset( &info
, 0, sizeof info
);
1386 info
.cbSize
= sizeof info
;
1387 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1388 info
.fType
= MFT_STRING
;
1389 info
.dwTypeData
= "MenuItem";
1390 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
1392 rc
= InsertMenuItem(hmenuSub2
, 0, TRUE
, &info
);
1393 ok (rc
, "Inserting the sub menu menuitem failed\n");
1395 memset( &info
, 0, sizeof info
);
1396 info
.cbSize
= sizeof info
;
1397 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1398 info
.fType
= MFT_STRING
;
1399 info
.dwTypeData
= "MenuItem 2";
1400 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
1402 rc
= InsertMenuItem(hmenuSub2
, 1, TRUE
, &info
);
1403 ok (rc
, "Inserting the sub menu menuitem 2 failed\n");
1405 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
1406 memset( &info
, 0, sizeof info
);
1408 info
.cbSize
= sizeof(MENUITEMINFO
);
1409 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1410 info
.dwTypeData
= strback
;
1411 info
.cch
= sizeof(strback
);
1413 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
);
1414 ok (rc
, "Getting the menus info failed\n");
1415 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for popup menu\n");
1416 ok (!strcmp(info
.dwTypeData
, "MenuItem"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1418 memset( &info
, 0, sizeof info
);
1420 info
.cbSize
= sizeof(MENUITEMINFO
);
1421 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1422 info
.dwTypeData
= strback
;
1423 info
.cch
= sizeof(strback
);
1425 rc
= GetMenuItemInfo(hmenu
, (UINT_PTR
)hmenuSub2
, FALSE
, &info
);
1426 ok (rc
, "Getting the menus info failed\n");
1427 ok (info
.wID
== (UINT
)hmenuSub2
, "IDs differ for popup menu\n");
1428 ok (!strcmp(info
.dwTypeData
, "Submenu2"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1430 DestroyMenu( hmenu
);
1431 DestroyMenu( hmenuSub
);
1432 DestroyMenu( hmenuSub2
);
1436 Case 5: Menu containing a popup menu which in turn
1437 contains an item with a different id than the popup menu.
1438 This tests the fallback to a popup menu ID.
1441 hmenu
= CreateMenu();
1442 hmenuSub
= CreateMenu();
1444 rc
= AppendMenu(hmenu
, MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, "Submenu");
1445 ok (rc
, "Appending the popup menu to the main menu failed\n");
1447 rc
= AppendMenu(hmenuSub
, MF_STRING
, 102, "Item");
1448 ok (rc
, "Appending the item to the popup menu failed\n");
1450 /* Set the ID for hmenuSub */
1451 info
.cbSize
= sizeof(info
);
1452 info
.fMask
= MIIM_ID
;
1455 rc
= SetMenuItemInfo(hmenu
, 0, TRUE
, &info
);
1456 ok(rc
, "Setting the ID for the popup menu failed\n");
1458 /* Check if the ID has been set */
1460 rc
= GetMenuItemInfo(hmenu
, 0, TRUE
, &info
);
1461 ok(rc
, "Getting the ID for the popup menu failed\n");
1462 ok(info
.wID
== 101, "The ID for the popup menu has not been set\n");
1464 /* Prove getting the item info via ID returns the popup menu */
1465 memset( &info
, 0, sizeof(info
));
1467 info
.cbSize
= sizeof(MENUITEMINFO
);
1468 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1469 info
.dwTypeData
= strback
;
1470 info
.cch
= sizeof(strback
);
1472 rc
= GetMenuItemInfo(hmenu
, 101, FALSE
, &info
);
1473 ok (rc
, "Getting the menu info failed\n");
1474 ok (info
.wID
== 101, "IDs differ\n");
1475 ok (!strcmp(info
.dwTypeData
, "Submenu"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1477 /* Also look for the menu item */
1478 memset( &info
, 0, sizeof(info
));
1480 info
.cbSize
= sizeof(MENUITEMINFO
);
1481 info
.fMask
= MIIM_STRING
| MIIM_ID
;
1482 info
.dwTypeData
= strback
;
1483 info
.cch
= sizeof(strback
);
1485 rc
= GetMenuItemInfo(hmenu
, 102, FALSE
, &info
);
1486 ok (rc
, "Getting the menu info failed\n");
1487 ok (info
.wID
== 102, "IDs differ\n");
1488 ok (!strcmp(info
.dwTypeData
, "Item"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1491 DestroyMenu(hmenuSub
);
1494 struct menu_item_pair_s
{
1495 UINT uMenu
; /* 1 - top level menu, [0-Menu 1-Enabled 2-Disabled]
1496 * 2 - 2nd level menu, [0-Popup 1-Enabled 2-Disabled]
1497 * 3 - 3rd level menu, [0-Enabled 1-Disabled] */
1501 static struct menu_mouse_tests_s
{
1503 struct menu_item_pair_s menu_item_pairs
[5]; /* for mousing */
1504 WORD wVk
[5]; /* keys */
1508 /* for each test, send keys or clicks and check for menu visibility */
1509 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 0}, TRUE
, TRUE
}, /* test 0 */
1510 { INPUT_KEYBOARD
, {{0}}, {VK_ESCAPE
, 0}, FALSE
, FALSE
},
1511 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 0}, TRUE
, TRUE
},
1512 { INPUT_KEYBOARD
, {{0}}, {'D', 0}, FALSE
, FALSE
},
1513 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 0}, TRUE
, TRUE
},
1514 { INPUT_KEYBOARD
, {{0}}, {'E', 0}, FALSE
, FALSE
},
1515 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 0}, TRUE
, TRUE
},
1516 { INPUT_KEYBOARD
, {{0}}, {VK_ESCAPE
, VK_ESCAPE
, 0}, FALSE
, FALSE
},
1517 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', VK_ESCAPE
, 0}, TRUE
, TRUE
},
1518 { INPUT_KEYBOARD
, {{0}}, {VK_ESCAPE
, 0}, FALSE
, FALSE
},
1519 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 0}, TRUE
, TRUE
},
1520 { INPUT_KEYBOARD
, {{0}}, {'D', 0}, FALSE
, FALSE
},
1521 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 0}, TRUE
, TRUE
},
1522 { INPUT_KEYBOARD
, {{0}}, {'E', 0}, FALSE
, FALSE
},
1523 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 'P', 0}, TRUE
, TRUE
},
1524 { INPUT_KEYBOARD
, {{0}}, {'D', 0}, FALSE
, FALSE
},
1525 { INPUT_KEYBOARD
, {{0}}, {VK_LMENU
, 'M', 'P', 0}, TRUE
, TRUE
},
1526 { INPUT_KEYBOARD
, {{0}}, {'E', 0}, FALSE
, FALSE
},
1528 { INPUT_MOUSE
, {{1, 2}, {0}}, {0}, TRUE
, TRUE
}, /* test 18 */
1529 { INPUT_MOUSE
, {{1, 1}, {0}}, {0}, FALSE
, FALSE
},
1530 { INPUT_MOUSE
, {{1, 0}, {0}}, {0}, TRUE
, TRUE
},
1531 { INPUT_MOUSE
, {{1, 1}, {0}}, {0}, FALSE
, FALSE
},
1532 { INPUT_MOUSE
, {{1, 0}, {2, 2}, {0}}, {0}, TRUE
, TRUE
},
1533 { INPUT_MOUSE
, {{2, 1}, {0}}, {0}, FALSE
, FALSE
},
1534 { INPUT_MOUSE
, {{1, 0}, {2, 0}, {0}}, {0}, TRUE
, TRUE
},
1535 { INPUT_MOUSE
, {{3, 0}, {0}}, {0}, FALSE
, FALSE
},
1536 { INPUT_MOUSE
, {{1, 0}, {2, 0}, {0}}, {0}, TRUE
, TRUE
},
1537 { INPUT_MOUSE
, {{3, 1}, {0}}, {0}, TRUE
, TRUE
},
1538 { INPUT_MOUSE
, {{1, 1}, {0}}, {0}, FALSE
, FALSE
},
1542 static void send_key(WORD wVk
)
1545 memset(&i
, 0, 2*sizeof(INPUT
));
1546 i
[0].type
= i
[1].type
= INPUT_KEYBOARD
;
1547 i
[0].u
.ki
.wVk
= i
[1].u
.ki
.wVk
= wVk
;
1548 i
[1].u
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
1549 SendInput(2, (INPUT
*) i
, sizeof(INPUT
));
1552 static void click_menu(HANDLE hWnd
, struct menu_item_pair_s
*mi
)
1554 HMENU hMenu
= hMenus
[mi
->uMenu
];
1558 int screen_w
= GetSystemMetrics(SM_CXSCREEN
);
1559 int screen_h
= GetSystemMetrics(SM_CYSCREEN
);
1561 GetMenuItemRect(mi
->uMenu
> 2 ? NULL
: hWnd
, hMenu
, mi
->uItem
, &r
);
1563 memset(&i
, 0, 3*sizeof(INPUT
));
1564 i
[0].type
= i
[1].type
= i
[2].type
= INPUT_MOUSE
;
1565 i
[0].u
.mi
.dx
= i
[1].u
.mi
.dx
= i
[2].u
.mi
.dx
1566 = ((r
.left
+ 5) * 65535) / screen_w
;
1567 i
[0].u
.mi
.dy
= i
[1].u
.mi
.dy
= i
[2].u
.mi
.dy
1568 = ((r
.top
+ 5) * 65535) / screen_h
;
1569 i
[0].u
.mi
.dwFlags
= i
[1].u
.mi
.dwFlags
= i
[2].u
.mi
.dwFlags
1570 = MOUSEEVENTF_ABSOLUTE
;
1571 i
[0].u
.mi
.dwFlags
|= MOUSEEVENTF_MOVE
;
1572 i
[1].u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTDOWN
;
1573 i
[2].u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTUP
;
1574 SendInput(3, (INPUT
*) i
, sizeof(INPUT
));
1576 /* hack to prevent mouse message buildup in Wine */
1577 while (PeekMessage( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
1580 static DWORD WINAPI
test_menu_input_thread(LPVOID lpParameter
)
1583 HANDLE hWnd
= lpParameter
;
1586 /* mixed keyboard/mouse test */
1587 for (i
= 0; menu_tests
[i
].type
!= -1; i
++)
1591 if (menu_tests
[i
].type
== INPUT_KEYBOARD
)
1592 for (j
= 0; menu_tests
[i
].wVk
[j
] != 0; j
++)
1593 send_key(menu_tests
[i
].wVk
[j
]);
1595 for (j
= 0; menu_tests
[i
].menu_item_pairs
[j
].uMenu
!= 0; j
++)
1596 click_menu(hWnd
, &menu_tests
[i
].menu_item_pairs
[j
]);
1598 while (menu_tests
[i
].bMenuVisible
!= bMenuVisible
)
1606 if (menu_tests
[i
]._todo_wine
)
1609 ok(menu_tests
[i
].bMenuVisible
== bMenuVisible
, "test %d\n", i
);
1613 ok(menu_tests
[i
].bMenuVisible
== bMenuVisible
, "test %d\n", i
);
1618 static LRESULT CALLBACK
WndProc(HWND hWnd
, UINT msg
, WPARAM wParam
,
1622 case WM_ENTERMENULOOP
:
1623 bMenuVisible
= TRUE
;
1625 case WM_EXITMENULOOP
:
1626 bMenuVisible
= FALSE
;
1629 return( DefWindowProcA( hWnd
, msg
, wParam
, lParam
) );
1634 static void test_menu_input(void) {
1637 HINSTANCE hInstance
= GetModuleHandleA( NULL
);
1638 HANDLE hThread
, hWnd
;
1640 wclass
.lpszClassName
= "MenuTestClass";
1641 wclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
1642 wclass
.lpfnWndProc
= WndProc
;
1643 wclass
.hInstance
= hInstance
;
1644 wclass
.hIcon
= LoadIconA( 0, (LPSTR
)IDI_APPLICATION
);
1645 wclass
.hCursor
= LoadCursorA( NULL
, (LPSTR
)IDC_ARROW
);
1646 wclass
.hbrBackground
= (HBRUSH
)( COLOR_WINDOW
+ 1);
1647 wclass
.lpszMenuName
= 0;
1648 wclass
.cbClsExtra
= 0;
1649 wclass
.cbWndExtra
= 0;
1650 assert (RegisterClassA( &wclass
));
1651 assert (hWnd
= CreateWindowA( wclass
.lpszClassName
, "MenuTest",
1652 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, 0,
1653 400, 200, NULL
, NULL
, hInstance
, NULL
) );
1656 hMenus
[3] = CreatePopupMenu();
1657 AppendMenu(hMenus
[3], MF_STRING
, 0, "&Enabled");
1658 AppendMenu(hMenus
[3], MF_STRING
|MF_DISABLED
, 0, "&Disabled");
1660 hMenus
[2] = CreatePopupMenu();
1661 AppendMenu(hMenus
[2], MF_STRING
|MF_POPUP
, (UINT_PTR
) hMenus
[3], "&Popup");
1662 AppendMenu(hMenus
[2], MF_STRING
, 0, "&Enabled");
1663 AppendMenu(hMenus
[2], MF_STRING
|MF_DISABLED
, 0, "&Disabled");
1665 hMenus
[1] = CreateMenu();
1666 AppendMenu(hMenus
[1], MF_STRING
|MF_POPUP
, (UINT_PTR
) hMenus
[2], "&Menu");
1667 AppendMenu(hMenus
[1], MF_STRING
, 0, "&Enabled");
1668 AppendMenu(hMenus
[1], MF_STRING
|MF_DISABLED
, 0, "&Disabled");
1670 SetMenu(hWnd
, hMenus
[1]);
1671 ShowWindow(hWnd
, SW_SHOW
);
1674 hThread
= CreateThread(NULL
, 0, test_menu_input_thread
, hWnd
, 0, NULL
);
1677 if (WAIT_TIMEOUT
!= WaitForSingleObject(hThread
, 50))
1679 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
1681 DestroyWindow(hWnd
);
1687 (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "SetMenuInfo" );
1689 (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetMenuInfo" );
1691 register_menu_check_class();
1693 test_menu_locked_by_window();
1694 test_menu_ownerdraw();
1695 test_menu_add_string();
1696 test_menu_iteminfo();
1697 test_menu_search_bycommand();
1698 test_menu_bmp_and_string();