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
27 #define OEMRESOURCE /* For OBM_MNARROW */
34 #include "wine/test.h"
36 static ATOM atomMenuCheckClass
;
38 static LRESULT WINAPI
menu_check_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
42 case WM_ENTERMENULOOP
:
43 /* mark window as having entered menu loop */
44 SetWindowLongPtrA(hwnd
, GWLP_USERDATA
, TRUE
);
45 /* exit menu modal loop
46 * ( A SendMessage does not work on NT3.51 here ) */
47 return PostMessageA(hwnd
, WM_CANCELMODE
, 0, 0);
49 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
52 /* The MSVC headers ignore our NONAMELESSUNION requests so we have to define
65 /* globals to communicate between test and wndproc */
67 static BOOL bMenuVisible
;
69 static BOOL got_input
;
70 static HMENU hMenus
[4];
75 /* menu texts with their sizes */
78 SIZE size
; /* size of text up to any \t */
79 SIZE sc_size
; /* size of the short-cut */
88 static unsigned int MOD_maxid
;
89 static RECT MOD_rc
[MOD_NRMENUS
];
90 static int MOD_avec
, MOD_hic
;
91 static int MOD_odheight
;
92 static SIZE MODsizes
[MOD_NRMENUS
]= { {MOD_SIZE
, MOD_SIZE
},{MOD_SIZE
, MOD_SIZE
},
93 {MOD_SIZE
, MOD_SIZE
},{MOD_SIZE
, MOD_SIZE
}};
94 static BOOL MOD_GotDrawItemMsg
= FALSE
;
95 static int gflag_initmenupopup
,
99 static WPARAM selectitem_wp
;
100 static LPARAM selectitem_lp
;
102 /* wndproc used by test_menu_ownerdraw() */
103 static LRESULT WINAPI
menu_ownerdraw_wnd_proc(HWND hwnd
, UINT msg
,
104 WPARAM wparam
, LPARAM lparam
)
106 static HMENU hmenupopup
;
109 case WM_INITMENUPOPUP
:
110 gflag_initmenupopup
++;
111 hmenupopup
= (HMENU
) wparam
;
113 case WM_ENTERMENULOOP
:
114 gflag_entermenuloop
++;
121 MEASUREITEMSTRUCT
* pmis
= (MEASUREITEMSTRUCT
*)lparam
;
122 if (winetest_debug
> 1)
123 trace("WM_MEASUREITEM received data %lx size %dx%d\n",
124 pmis
->itemData
, pmis
->itemWidth
, pmis
->itemHeight
);
125 ok( !wparam
, "wrong wparam %lx\n", wparam
);
126 ok( pmis
->CtlType
== ODT_MENU
, "wrong type %x\n", pmis
->CtlType
);
127 MOD_odheight
= pmis
->itemHeight
;
128 pmis
->itemWidth
= MODsizes
[pmis
->itemData
].cx
;
129 pmis
->itemHeight
= MODsizes
[pmis
->itemData
].cy
;
134 DRAWITEMSTRUCT
* pdis
;
137 char chrs
[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
140 pdis
= (DRAWITEMSTRUCT
*) lparam
;
141 if (winetest_debug
> 1) {
143 GetMenuItemRect( hwnd
, (HMENU
)pdis
->hwndItem
, pdis
->itemData
,&rc
);
144 trace("WM_DRAWITEM received hwnd %p hmenu %p itemdata %ld item %d rc %s itemrc: %s\n",
145 hwnd
, pdis
->hwndItem
, pdis
->itemData
, pdis
->itemID
,
146 wine_dbgstr_rect(&pdis
->rcItem
), wine_dbgstr_rect(&rc
));
147 oldpen
=SelectObject( pdis
->hDC
, GetStockObject(
148 pdis
->itemState
& ODS_SELECTED
? WHITE_PEN
:BLACK_PEN
));
149 Rectangle( pdis
->hDC
, pdis
->rcItem
.left
,pdis
->rcItem
.top
,
150 pdis
->rcItem
.right
,pdis
->rcItem
.bottom
);
151 SelectObject( pdis
->hDC
, oldpen
);
153 ok( !wparam
, "wrong wparam %lx\n", wparam
);
154 ok( pdis
->CtlType
== ODT_MENU
, "wrong type %x\n", pdis
->CtlType
);
155 /* calculate widths of some menu texts */
156 if( ! MOD_txtsizes
[0].size
.cx
)
157 for(i
= 0; MOD_txtsizes
[i
].text
; i
++) {
160 strcpy( buf
, MOD_txtsizes
[i
].text
);
161 if( ( p
= strchr( buf
, '\t'))) {
163 DrawTextA( pdis
->hDC
, p
+ 1, -1, &rc
,
164 DT_SINGLELINE
|DT_CALCRECT
);
165 MOD_txtsizes
[i
].sc_size
.cx
= rc
.right
- rc
.left
;
166 MOD_txtsizes
[i
].sc_size
.cy
= rc
.bottom
- rc
.top
;
168 DrawTextA( pdis
->hDC
, buf
, -1, &rc
,
169 DT_SINGLELINE
|DT_CALCRECT
);
170 MOD_txtsizes
[i
].size
.cx
= rc
.right
- rc
.left
;
171 MOD_txtsizes
[i
].size
.cy
= rc
.bottom
- rc
.top
;
174 if( pdis
->itemData
> MOD_maxid
) return TRUE
;
175 /* store the rectangle */
176 MOD_rc
[pdis
->itemData
] = pdis
->rcItem
;
177 /* calculate average character width */
178 GetTextExtentPointA( pdis
->hDC
, chrs
, 52, &sz
);
179 MOD_avec
= (sz
.cx
+ 26)/52;
180 GetTextMetricsA( pdis
->hDC
, &tm
);
181 MOD_hic
= tm
.tmHeight
;
182 MOD_GotDrawItemMsg
= TRUE
;
188 ok( lparam
|| broken(!lparam
), /* win9x, nt4 */
189 "Menu window handle is NULL!\n");
191 HMENU hmenu
= (HMENU
)SendMessageA( (HWND
)lparam
, MN_GETHMENU
, 0, 0);
192 ok( hmenupopup
== hmenu
, "MN_GETHMENU returns %p expected %p\n",
195 PostMessageA(hwnd
, WM_CANCELMODE
, 0, 0);
199 selectitem_wp
= wparam
;
200 selectitem_lp
= lparam
;
203 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
206 static void register_menu_check_class(void)
214 GetModuleHandleA(NULL
),
216 LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
),
217 (HBRUSH
)(COLOR_BTNFACE
+1),
222 atomMenuCheckClass
= RegisterClassA(&wc
);
225 static void test_getmenubarinfo(void)
234 mbi
.cbSize
= sizeof(MENUBARINFO
);
236 hwnd
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
237 WS_SYSMENU
| WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 100, 100,
238 NULL
, NULL
, NULL
, NULL
);
239 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
241 /* no menu: getmenubarinfo should fail */
242 SetLastError(0xdeadbeef);
243 ret
= GetMenuBarInfo(hwnd
, OBJID_MENU
, 0, &mbi
);
244 err
= GetLastError();
245 ok(ret
== FALSE
, "GetMenuBarInfo should not have been successful\n");
246 ok(err
== 0xdeadbeef, "err = %d\n", err
);
248 /* create menubar, no items yet */
249 hmenu
= CreateMenu();
250 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
252 ret
= SetMenu(hwnd
, hmenu
);
253 ok(ret
, "SetMenu failed with error %d\n", GetLastError());
255 SetLastError(0xdeadbeef);
256 ret
= GetMenuBarInfo(NULL
, OBJID_CLIENT
, 0, &mbi
);
257 err
= GetLastError();
258 ok(!ret
, "GetMenuBarInfo succeeded\n");
259 ok(err
== ERROR_INVALID_WINDOW_HANDLE
, "err = %d\n", err
);
261 SetLastError(0xdeadbeef);
262 ret
= GetMenuBarInfo(hwnd
, OBJID_CLIENT
, 0, &mbi
);
263 err
= GetLastError();
264 ok(!ret
, "GetMenuBarInfo succeeded\n");
265 ok(err
==ERROR_INVALID_MENU_HANDLE
|| broken(err
==0xdeadbeef) /* NT, W2K, XP */, "err = %d\n", err
);
267 SetLastError(0xdeadbeef);
268 ret
= GetMenuBarInfo(hwnd
, OBJID_MENU
, -1, &mbi
);
269 err
= GetLastError();
270 ok(ret
== FALSE
, "GetMenuBarInfo should have failed\n");
271 ok(err
== 0xdeadbeef, "err = %d\n", err
);
274 SetLastError(0xdeadbeef);
275 ret
= GetMenuBarInfo(hwnd
, OBJID_MENU
, 0, &mbi
);
276 err
= GetLastError();
277 ok(ret
== FALSE
, "GetMenuBarInfo should have failed\n");
278 ok(err
== ERROR_INVALID_PARAMETER
, "err = %d\n", err
);
279 mbi
.cbSize
= sizeof(MENUBARINFO
);
281 SetLastError(0xdeadbeef);
282 ret
= GetMenuBarInfo(hwnd
, 123, 0, &mbi
);
283 err
= GetLastError();
284 ok(ret
== FALSE
, "GetMenuBarInfo should have failed\n");
285 ok(err
== 0xdeadbeef, "err = %d\n", err
);
287 ret
= GetMenuBarInfo(hwnd
, OBJID_MENU
, 0, &mbi
);
288 ok(ret
, "GetMenuBarInfo failed with error %d\n", GetLastError());
290 ok(mbi
.rcBar
.left
== 0 && mbi
.rcBar
.top
== 0 && mbi
.rcBar
.bottom
== 0 && mbi
.rcBar
.right
== 0,
291 "rcBar: Expected (0,0)-(0,0), got: %s\n", wine_dbgstr_rect(&mbi
.rcBar
));
292 ok(mbi
.hMenu
== hmenu
, "hMenu: Got %p instead of %p\n",
294 ok(mbi
.fBarFocused
== 0, "fBarFocused: Got %d instead of 0.\n", mbi
.fBarFocused
);
295 ok(mbi
.fFocused
== 0, "fFocused: Got %d instead of 0.\n", mbi
.fFocused
);
298 ret
= AppendMenuA(hmenu
, MF_STRING
, 100, "item 1");
299 ok(ret
, "AppendMenu failed.\n");
300 ret
= AppendMenuA(hmenu
, MF_STRING
, 101, "item 2");
301 ok(ret
, "AppendMenu failed.\n");
302 ret
= SetMenu(hwnd
, hmenu
);
303 ok(ret
, "SetMenu failed with error %d\n", GetLastError());
305 SetLastError(0xdeadbeef);
306 ret
= GetMenuBarInfo(hwnd
, OBJID_MENU
, 200, &mbi
);
307 err
= GetLastError();
308 ok(ret
== FALSE
, "GetMenuBarInfo should have failed\n");
309 ok(err
== 0xdeadbeef, "err = %d\n", err
);
311 /* get info for the whole menu */
312 ret
= GetMenuBarInfo(hwnd
, OBJID_MENU
, 0, &mbi
);
313 ok(ret
, "GetMenuBarInfo failed with error %d\n", GetLastError());
315 /* calculate menu rectangle, from window rectangle and the position of the first item */
316 ret
= GetWindowRect(hwnd
, &rcw
);
317 ok(ret
, "GetWindowRect failed.\n");
318 ret
= GetMenuItemRect(hwnd
, hmenu
, 0, &rci
);
319 ok(ret
, "GetMenuItemRect failed.\n");
320 todo_wine
ok(mbi
.rcBar
.left
== rci
.left
&& mbi
.rcBar
.top
== rci
.top
&&
321 mbi
.rcBar
.bottom
== rci
.bottom
&& mbi
.rcBar
.right
== rcw
.right
- rci
.left
+ rcw
.left
,
322 "rcBar: Got %s instead of (%d,%d)-(%d,%d)\n", wine_dbgstr_rect(&mbi
.rcBar
),
323 rci
.left
, rci
.top
, rcw
.right
- rci
.left
+ rcw
.left
, rci
.bottom
);
324 ok(mbi
.hMenu
== hmenu
, "hMenu: Got %p instead of %p\n", mbi
.hMenu
, hmenu
);
325 ok(mbi
.fBarFocused
== 0, "fBarFocused: got %d instead of 0\n", mbi
.fBarFocused
);
326 ok(mbi
.fFocused
== 0, "fFocused: got %d instead of 0\n", mbi
.fFocused
);
328 /* get info for item nr.2 */
329 ret
= GetMenuBarInfo(hwnd
, OBJID_MENU
, 2, &mbi
);
330 ok(ret
, "GetMenuBarInfo failed with error %d\n", GetLastError());
331 ret
= GetMenuItemRect(hwnd
, hmenu
, 1, &rci
);
332 ok(ret
, "GetMenuItemRect failed.\n");
333 ok(EqualRect(&mbi
.rcBar
, &rci
), "rcBar: Got %s instead of %s\n", wine_dbgstr_rect(&mbi
.rcBar
),
334 wine_dbgstr_rect(&rci
));
335 ok(mbi
.hMenu
== hmenu
, "hMenu: Got %p instead of %p\n", mbi
.hMenu
, hmenu
);
336 ok(mbi
.fBarFocused
== 0, "fBarFocused: got %d instead of 0\n", mbi
.fBarFocused
);
337 ok(mbi
.fFocused
== 0, "fFocused: got %d instead of 0\n", mbi
.fFocused
);
342 static void test_GetMenuItemRect(void)
349 POINT client_top_left
;
353 hwnd
= CreateWindowW((LPCWSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
, WS_OVERLAPPEDWINDOW
, 0, 0, 100, 100, NULL
,
355 ok(hwnd
!= NULL
, "CreateWindow failed with error %d\n", GetLastError());
356 hmenu
= CreateMenu();
357 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
358 popup_hmenu
= CreatePopupMenu();
359 ok(popup_hmenu
!= NULL
, "CreatePopupMenu failed with error %d\n", GetLastError());
360 ret
= AppendMenuA(popup_hmenu
, MF_STRING
, 0, "Popup");
361 ok(ret
, "AppendMenu failed with error %d\n", GetLastError());
362 ret
= AppendMenuA(hmenu
, MF_STRING
| MF_POPUP
, (UINT_PTR
)popup_hmenu
, "Menu");
363 ok(ret
, "AppendMenu failed with error %d\n", GetLastError());
364 ret
= SetMenu(hwnd
, hmenu
);
365 ok(ret
, "SetMenu failed with error %d\n", GetLastError());
367 /* Get the menu item rectangle of the displayed sysmenu item */
368 ret
= GetMenuItemRect(hwnd
, hmenu
, 0, &item_rect
);
369 ok(ret
, "GetMenuItemRect failed with error %d\n", GetLastError());
370 GetWindowRect(hwnd
, &window_rect
);
371 /* Get the screen coordinate of the left top corner of the client rectangle */
372 client_top_left
.x
= 0;
373 client_top_left
.y
= 0;
374 MapWindowPoints(hwnd
, 0, &client_top_left
, 1);
375 caption_height
= GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYCAPTION
);
377 ok(item_rect
.left
== client_top_left
.x
, "Expect item_rect.left %d == %d\n", item_rect
.left
, client_top_left
.x
);
378 ok(item_rect
.right
<= window_rect
.right
, "Expect item_rect.right %d <= %d\n", item_rect
.right
, window_rect
.right
);
379 /* A gap of 1 pixel is added deliberately in commit 75f9e64, so using equal operator would fail on Wine.
380 * Check that top and bottom are correct with 1 pixel margin tolerance */
381 ok(item_rect
.top
- (window_rect
.top
+ caption_height
) <= 1, "Expect item_rect.top %d - %d <= 1\n", item_rect
.top
,
382 window_rect
.top
+ caption_height
);
383 ok(item_rect
.bottom
- (client_top_left
.y
- 1) <= 1, "Expect item_rect.bottom %d - %d <= 1\n", item_rect
.bottom
,
384 client_top_left
.y
- 1);
386 /* Get the item rectangle of the not yet displayed popup menu item. */
387 ret
= GetMenuItemRect(hwnd
, popup_hmenu
, 0, &item_rect
);
388 ok(ret
, "GetMenuItemRect failed with error %d\n", GetLastError());
389 ok(item_rect
.left
== client_top_left
.x
, "Expect item_rect.left %d == %d\n", item_rect
.left
, client_top_left
.x
);
390 ok(item_rect
.right
== client_top_left
.x
, "Expect item_rect.right %d == %d\n", item_rect
.right
, client_top_left
.x
);
391 ok(item_rect
.top
== client_top_left
.y
, "Expect item_rect.top %d == %d\n", item_rect
.top
, client_top_left
.y
);
392 ok(item_rect
.bottom
== client_top_left
.y
, "Expect item_rect.bottom %d == %d\n", item_rect
.bottom
,
398 static void test_system_menu(void)
400 WCHAR testW
[] = {'t','e','s','t',0};
410 hwnd
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
411 WS_SYSMENU
| WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 100, 100,
412 NULL
, NULL
, NULL
, NULL
);
413 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
414 menu
= GetSystemMenu( hwnd
, FALSE
);
415 ok( menu
!= NULL
, "no system menu\n" );
417 for (i
= 0xf000; i
< 0xf200; i
++)
419 memset( &info
, 0xcc, sizeof(info
) );
420 info
.cbSize
= sizeof(info
);
421 info
.fMask
= MIIM_STRING
| MIIM_FTYPE
| MIIM_ID
;
422 info
.dwTypeData
= buffer
;
423 info
.cch
= sizeof( buffer
);
424 ret
= GetMenuItemInfoA( menu
, i
, FALSE
, &info
);
425 if (ret
) trace( "found %x: '%s'\n", i
, buffer
);
434 ok( ret
, "%x menu item not found\n", i
);
436 case SC_SCREENSAVE
+1: /* used for the 'About Wine' entry, don't test */
439 ok( !ret
, "%x menu item found\n", i
);
442 found
[i
- 0xf000] = ret
;
445 for (i
= 0xf000; i
< 0xf200; i
++)
447 res
= CheckMenuItem( menu
, i
, 0 );
448 if (res
== -1) ok( !found
[i
- 0xf000], "could not check existent item %x\n", i
);
449 else ok( found
[i
- 0xf000], "could check non-existent item %x\n", i
);
451 res
= EnableMenuItem( menu
, i
, 0 );
452 if (res
== -1) ok( !found
[i
- 0xf000], "could not enable existent item %x\n", i
);
453 else ok( found
[i
- 0xf000], "could enable non-existent item %x\n", i
);
455 res
= GetMenuState( menu
, i
, 0 );
456 if (res
== -1) ok( !found
[i
- 0xf000], "could not get state existent item %x\n", i
);
457 else ok( found
[i
- 0xf000], "could get state of non-existent item %x\n", i
);
459 if (!found
[i
- 0xf000]) /* don't remove the existing ones */
461 ret
= RemoveMenu( menu
, i
, 0 );
462 ok( !ret
, "could remove non-existent item %x\n", i
);
465 ret
= ModifyMenuA( menu
, i
, 0, i
, "test" );
466 if (i
== SC_TASKLIST
) ok( ret
, "failed to modify SC_TASKLIST\n" );
467 else if (!ret
) ok( !found
[i
- 0xf000], "could not modify existent item %x\n", i
);
468 else ok( found
[i
- 0xf000], "could modify non-existent item %x\n", i
);
470 ret
= ModifyMenuW( menu
, i
, 0, i
, testW
);
471 if (i
== SC_TASKLIST
) ok( ret
, "failed to modify SC_TASKLIST\n" );
472 else if (!ret
) ok( !found
[i
- 0xf000], "could not modify existent item %x\n", i
);
473 else ok( found
[i
- 0xf000], "could modify non-existent item %x\n", i
);
475 ret
= ModifyMenuA( menu
, i
, MF_BYPOSITION
, i
, "test" );
476 ok( !ret
, "could modify non-existent item %x\n", i
);
478 strcpy( buffer
, "test" );
479 memset( &info
, 0xcc, sizeof(info
) );
480 info
.cbSize
= sizeof(info
);
481 info
.fMask
= MIIM_STRING
| MIIM_ID
;
483 info
.dwTypeData
= buffer
;
484 info
.cch
= strlen( buffer
);
485 ret
= SetMenuItemInfoA( menu
, i
, FALSE
, &info
);
486 if (i
== SC_TASKLIST
) ok( ret
, "failed to set SC_TASKLIST\n" );
487 else if (!ret
) ok( !found
[i
- 0xf000], "could not set existent item %x\n", i
);
488 else ok( found
[i
- 0xf000], "could set non-existent item %x\n", i
);
489 ret
= SetMenuItemInfoA( menu
, i
, TRUE
, &info
);
490 ok( !ret
, "could modify non-existent item %x\n", i
);
492 memset( &infoW
, 0xcc, sizeof(infoW
) );
493 infoW
.cbSize
= sizeof(infoW
);
494 infoW
.fMask
= MIIM_STRING
| MIIM_ID
;
496 infoW
.dwTypeData
= testW
;
497 infoW
.cch
= lstrlenW( testW
);
498 ret
= SetMenuItemInfoW( menu
, i
, FALSE
, &infoW
);
499 if (i
== SC_TASKLIST
) ok( ret
, "failed to set SC_TASKLIST\n" );
500 else if (!ret
) ok( !found
[i
- 0xf000], "could not set existent item %x\n", i
);
501 else ok( found
[i
- 0xf000], "could set non-existent item %x\n", i
);
502 ret
= SetMenuItemInfoW( menu
, i
, TRUE
, &infoW
);
503 ok( !ret
, "could modify non-existent item %x\n", i
);
506 /* confirm that SC_TASKLIST still does not exist */
507 for (i
= 0xf000; i
< 0xf200; i
++)
509 memset( &info
, 0xcc, sizeof(info
) );
510 info
.cbSize
= sizeof(info
);
511 info
.fMask
= MIIM_STRING
| MIIM_FTYPE
| MIIM_ID
;
512 info
.dwTypeData
= buffer
;
513 info
.cch
= sizeof( buffer
);
514 ret
= GetMenuItemInfoA( menu
, i
, FALSE
, &info
);
523 ok( ret
, "%x menu item not found\n", i
);
525 case SC_SCREENSAVE
+1: /* used for the 'About Wine' entry, don't test */
528 ok( !ret
, "%x menu item found\n", i
);
533 /* now a normal (non-system) menu */
536 ok( menu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError() );
538 res
= CheckMenuItem( menu
, SC_TASKLIST
, 0 );
539 ok( res
== -1, "CheckMenuItem succeeded\n" );
540 res
= EnableMenuItem( menu
, SC_TASKLIST
, 0 );
541 ok( res
== -1, "EnableMenuItem succeeded\n" );
542 res
= GetMenuState( menu
, SC_TASKLIST
, 0 );
543 ok( res
== -1, "GetMenuState succeeded\n" );
544 ret
= RemoveMenu( menu
, SC_TASKLIST
, 0 );
545 ok( !ret
, "RemoveMenu succeeded\n" );
546 ret
= ModifyMenuA( menu
, SC_TASKLIST
, 0, SC_TASKLIST
, "test" );
547 ok( ret
, "ModifyMenuA failed err %d\n", GetLastError() );
548 ret
= ModifyMenuW( menu
, SC_TASKLIST
, 0, SC_TASKLIST
, testW
);
549 ok( ret
, "ModifyMenuW failed err %d\n", GetLastError() );
550 ret
= ModifyMenuA( menu
, SC_TASKLIST
-1, 0, SC_TASKLIST
, "test" );
551 ok( !ret
, "ModifyMenu succeeded on SC_TASKLIST-1\n" );
552 strcpy( buffer
, "test" );
553 memset( &info
, 0xcc, sizeof(info
) );
554 info
.cbSize
= sizeof(info
);
555 info
.fMask
= MIIM_STRING
| MIIM_ID
;
556 info
.wID
= SC_TASKLIST
;
557 info
.dwTypeData
= buffer
;
558 info
.cch
= strlen( buffer
);
559 ret
= SetMenuItemInfoA( menu
, SC_TASKLIST
, FALSE
, &info
);
560 ok( ret
, "failed to set SC_TASKLIST\n" );
561 ret
= SetMenuItemInfoA( menu
, SC_TASKLIST
+1, FALSE
, &info
);
562 ok( !ret
, "succeeded setting SC_TASKLIST+1\n" );
563 ret
= SetMenuItemInfoA( menu
, SC_TASKLIST
, TRUE
, &info
);
564 ok( !ret
, "succeeded setting by position\n" );
566 memset( &infoW
, 0xcc, sizeof(infoW
) );
567 infoW
.cbSize
= sizeof(infoW
);
568 infoW
.fMask
= MIIM_STRING
| MIIM_ID
;
569 infoW
.wID
= SC_TASKLIST
;
570 infoW
.dwTypeData
= testW
;
571 infoW
.cch
= lstrlenW( testW
);
572 ret
= SetMenuItemInfoW( menu
, SC_TASKLIST
, FALSE
, &infoW
);
573 ok( ret
, "failed to set SC_TASKLIST\n" );
574 ret
= SetMenuItemInfoW( menu
, SC_TASKLIST
+1, FALSE
, &infoW
);
575 ok( !ret
, "succeeded setting SC_TASKLIST+1\n" );
576 ret
= SetMenuItemInfoW( menu
, SC_TASKLIST
, TRUE
, &infoW
);
577 ok( !ret
, "succeeded setting by position\n" );
580 DestroyWindow( hwnd
);
583 /* demonstrates that windows locks the menu object so that it is still valid
584 * even after a client calls DestroyMenu on it */
585 static void test_menu_locked_by_window(void)
589 HWND hwnd
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
590 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
591 NULL
, NULL
, NULL
, NULL
);
592 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
593 hmenu
= CreateMenu();
594 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
595 ret
= InsertMenuA(hmenu
, 0, MF_STRING
, 0, "&Test");
596 ok(ret
, "InsertMenu failed with error %d\n", GetLastError());
597 ret
= SetMenu(hwnd
, hmenu
);
598 ok(ret
, "SetMenu failed with error %d\n", GetLastError());
599 ret
= DestroyMenu(hmenu
);
600 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
602 ret
= DrawMenuBar(hwnd
);
603 ok(ret
, "DrawMenuBar failed with error %d\n", GetLastError());
604 ret
= IsMenu(GetMenu(hwnd
));
605 ok(!ret
|| broken(ret
) /* nt4 */, "Menu handle should have been destroyed\n");
607 SendMessageA(hwnd
, WM_SYSCOMMAND
, SC_KEYMENU
, 0);
608 /* did we process the WM_INITMENU message? */
609 ret
= GetWindowLongPtrA(hwnd
, GWLP_USERDATA
);
611 ok(ret
, "WM_INITMENU should have been sent\n");
617 /* demonstrates that subpopup's are locked
618 * even after a client calls DestroyMenu on it */
619 static LRESULT WINAPI
subpopuplocked_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
625 hwndmenu
= GetCapture();
627 PostMessageA( hwndmenu
, WM_KEYDOWN
, VK_DOWN
, 0);
628 PostMessageA( hwndmenu
, WM_KEYDOWN
, VK_RIGHT
, 0);
629 PostMessageA( hwndmenu
, WM_KEYDOWN
, VK_RETURN
, 0);
632 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
635 static void test_subpopup_locked_by_menu(void)
638 HMENU hmenu
, hsubmenu
;
639 MENUINFO mi
= { sizeof( MENUINFO
)};
640 MENUITEMINFOA mii
= { sizeof( MENUITEMINFOA
)};
642 const int itemid
= 0x1234567;
644 /* create window, popupmenu with one subpopup */
645 hwnd
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
646 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
647 NULL
, NULL
, NULL
, NULL
);
648 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
649 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
) subpopuplocked_wnd_proc
);
650 hmenu
= CreatePopupMenu();
651 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
652 hsubmenu
= CreatePopupMenu();
653 ok(hsubmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
654 ret
= InsertMenuA(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hsubmenu
,
656 ok(ret
, "InsertMenu failed with error %d\n", GetLastError());
657 ret
= InsertMenuA(hsubmenu
, 0, MF_BYPOSITION
| MF_STRING
, itemid
, "PopUpMenu");
658 ok(ret
, "InsertMenu failed with error %d\n", GetLastError());
659 /* first some tests that all this functions properly */
660 mii
.fMask
= MIIM_SUBMENU
;
661 ret
= GetMenuItemInfoA( hmenu
, 0, TRUE
, &mii
);
662 ok( ret
, "GetMenuItemInfo failed error %d\n", GetLastError());
663 ok( mii
.hSubMenu
== hsubmenu
, "submenu is %p\n", mii
.hSubMenu
);
664 mi
.fMask
|= MIM_STYLE
;
665 ret
= GetMenuInfo( hsubmenu
, &mi
);
666 ok( ret
, "GetMenuInfo returned 0 with error %d\n", GetLastError());
667 ret
= IsMenu( hsubmenu
);
668 ok( ret
, "Menu handle is not valid\n");
670 ret
= TrackPopupMenu( hmenu
, TPM_RETURNCMD
, 100,100, 0, hwnd
, NULL
);
671 ok( ret
== itemid
, "TrackPopupMenu returned %d error is %d\n", ret
, GetLastError());
673 /* then destroy the sub-popup */
674 ret
= DestroyMenu( hsubmenu
);
675 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
676 /* and repeat the tests */
677 mii
.fMask
= MIIM_SUBMENU
;
678 ret
= GetMenuItemInfoA( hmenu
, 0, TRUE
, &mii
);
679 ok( ret
, "GetMenuItemInfo failed error %d\n", GetLastError());
680 /* GetMenuInfo fails now */
681 ok( mii
.hSubMenu
== hsubmenu
, "submenu is %p\n", mii
.hSubMenu
);
682 mi
.fMask
|= MIM_STYLE
;
683 ret
= GetMenuInfo( hsubmenu
, &mi
);
684 ok( !ret
, "GetMenuInfo should have failed\n");
685 /* IsMenu says it is not */
686 ret
= IsMenu( hsubmenu
);
687 ok( !ret
, "Menu handle should be invalid\n");
689 /* but TrackPopupMenu still works! */
690 ret
= TrackPopupMenu( hmenu
, TPM_RETURNCMD
, 100,100, 0, hwnd
, NULL
);
692 ok( ret
== itemid
, "TrackPopupMenu returned %d error is %d\n", ret
, GetLastError());
700 static void test_menu_ownerdraw(void)
707 HWND hwnd
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
708 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
709 NULL
, NULL
, NULL
, NULL
);
710 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
712 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)menu_ownerdraw_wnd_proc
);
713 hmenu
= CreatePopupMenu();
714 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
715 if( !hmenu
) { DestroyWindow(hwnd
);return;}
717 for( j
=0;j
<2;j
++) /* create columns */
718 for(i
=0;i
<2;i
++) { /* create rows */
719 ret
= AppendMenuA( hmenu
, MF_OWNERDRAW
|
720 (i
==0 ? MF_MENUBREAK
: 0), k
, (LPCSTR
)MAKEINTRESOURCE(k
));
722 ok( ret
, "AppendMenu failed for %d\n", k
-1);
725 assert( k
<= ARRAY_SIZE(MOD_rc
));
726 /* display the menu */
727 TrackPopupMenu( hmenu
, TPM_RETURNCMD
, 100,100, 0, hwnd
, NULL
);
729 /* columns have a 4 pixel gap between them */
730 ok( MOD_rc
[0].right
+ 4 == MOD_rc
[2].left
,
731 "item rectangles are not separated by 4 pixels space\n");
732 /* height should be what the MEASUREITEM message has returned */
733 ok( MOD_rc
[0].bottom
- MOD_rc
[0].top
== MOD_SIZE
,
734 "menu item has wrong height: %d should be %d\n",
735 MOD_rc
[0].bottom
- MOD_rc
[0].top
, MOD_SIZE
);
736 /* no gaps between the rows */
737 ok( MOD_rc
[0].bottom
- MOD_rc
[1].top
== 0,
738 "There should not be a space between the rows, gap is %d\n",
739 MOD_rc
[0].bottom
- MOD_rc
[1].top
);
740 /* test the correct value of the item height that was sent
741 * by the WM_MEASUREITEM message */
742 ok( MOD_odheight
== HIWORD( GetDialogBaseUnits()) || /* WinNT,2k,XP */
743 MOD_odheight
== MOD_hic
, /* Win95,98,ME */
744 "Wrong height field in MEASUREITEMSTRUCT, expected %d or %d actual %d\n",
745 HIWORD( GetDialogBaseUnits()), MOD_hic
, MOD_odheight
);
746 /* test what MF_MENUBREAK did at the first position. Also show
747 * that an MF_SEPARATOR is ignored in the height calculation. */
748 leftcol
= MOD_rc
[0].left
;
749 ModifyMenuA( hmenu
, 0, MF_BYCOMMAND
| MF_OWNERDRAW
| MF_SEPARATOR
, 0, 0);
750 /* display the menu */
751 TrackPopupMenu( hmenu
, TPM_RETURNCMD
, 100,100, 0, hwnd
, NULL
);
752 /* left should be 4 pixels less now */
753 ok( leftcol
== MOD_rc
[0].left
+ 4,
754 "columns should be 4 pixels to the left (actual %d).\n",
755 leftcol
- MOD_rc
[0].left
);
757 ok( MOD_rc
[0].right
- MOD_rc
[0].left
== 2 * MOD_avec
+ MOD_SIZE
,
758 "width of owner drawn menu item is wrong. Got %d expected %d\n",
759 MOD_rc
[0].right
- MOD_rc
[0].left
, 2*MOD_avec
+ MOD_SIZE
);
761 ok( MOD_rc
[0].bottom
- MOD_rc
[0].top
== MOD_SIZE
,
762 "Height is incorrect. Got %d expected %d\n",
763 MOD_rc
[0].bottom
- MOD_rc
[0].top
, MOD_SIZE
);
765 /* test owner-drawn callback bitmap */
766 ModifyMenuA( hmenu
, 1, MF_BYPOSITION
| MFT_BITMAP
, 1, (LPCSTR
)HBMMENU_CALLBACK
);
767 mii
.cbSize
= sizeof(mii
);
768 mii
.fMask
= MIIM_BITMAP
| MIIM_FTYPE
| MIIM_ID
;
769 if (GetMenuItemInfoA( hmenu
, 1, TRUE
, &mii
))
771 ok( mii
.fType
== MFT_BITMAP
, "wrong type %x\n", mii
.fType
);
772 ok( mii
.wID
== 1, "wrong id %x\n", mii
.wID
);
773 ok( mii
.hbmpItem
== HBMMENU_CALLBACK
, "wrong data %p\n", mii
.hbmpItem
);
775 TrackPopupMenu( hmenu
, TPM_RETURNCMD
, 100,100, 0, hwnd
, NULL
);
777 /* test width/height of an ownerdraw menu bar as well */
778 ret
= DestroyMenu(hmenu
);
779 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
780 hmenu
= CreateMenu();
781 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
782 if( !hmenu
) { DestroyWindow(hwnd
);return;}
785 ret
= AppendMenuA( hmenu
, MF_OWNERDRAW
, i
, 0 );
786 ok( ret
, "AppendMenu failed for %d\n", i
);
788 ret
= SetMenu( hwnd
, hmenu
);
789 UpdateWindow( hwnd
); /* hack for wine to draw the window + menu */
790 ok(ret
, "SetMenu failed with error %d\n", GetLastError());
792 ok( MOD_rc
[0].right
- MOD_rc
[0].left
== 2 * MOD_avec
+ MOD_SIZE
,
793 "width of owner drawn menu item is wrong. Got %d expected %d\n",
794 MOD_rc
[0].right
- MOD_rc
[0].left
, 2*MOD_avec
+ MOD_SIZE
);
796 ok( MOD_rc
[0].bottom
- MOD_rc
[0].top
== GetSystemMetrics( SM_CYMENU
) - 1,
797 "Height of owner drawn menu item is wrong. Got %d expected %d\n",
798 MOD_rc
[0].bottom
- MOD_rc
[0].top
, GetSystemMetrics( SM_CYMENU
) - 1);
801 ret
= DestroyMenu(hmenu
);
802 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
806 /* helper for test_menu_bmp_and_string() */
807 static void test_mbs_help( int ispop
, int hassub
, int mnuopt
,
808 HWND hwnd
, int arrowwidth
, int count
, HBITMAP hbmp
,
809 SIZE bmpsize
, LPCSTR text
, SIZE size
, SIZE sc_size
)
812 HMENU hmenu
, submenu
;
813 MENUITEMINFOA mii
={ sizeof( MENUITEMINFOA
)};
820 MOD_GotDrawItemMsg
= FALSE
;
821 mii
.fMask
= MIIM_FTYPE
| MIIM_DATA
| MIIM_STATE
;
823 /* check the menu item unless MNS_CHECKORBMP is set */
824 mii
.fState
= (mnuopt
!= 2 ? MFS_CHECKED
: MFS_UNCHECKED
);
826 MODsizes
[0] = bmpsize
;
830 mii
.fMask
|= MIIM_STRING
;
831 strcpy(text_copy
, text
);
832 mii
.dwTypeData
= text_copy
; /* structure member declared non-const */
833 if( ( p
= strchr( text
, '\t'))) {
834 hastab
= *(p
+ 1) ? 2 : 1;
837 /* tabs don't make sense in menubars */
838 if(hastab
&& !ispop
) return;
840 mii
.fMask
|= MIIM_BITMAP
;
843 submenu
= CreateMenu();
844 ok( submenu
!= 0, "CreateMenu failed with error %d\n", GetLastError());
846 hmenu
= CreatePopupMenu();
848 hmenu
= CreateMenu();
849 ok( hmenu
!= 0, "Create{Popup}Menu failed with error %d\n", GetLastError());
851 mii
.fMask
|= MIIM_SUBMENU
;
852 mii
.hSubMenu
= submenu
;
855 mi
.cbSize
= sizeof(mi
);
856 mi
.fMask
= MIM_STYLE
;
857 GetMenuInfo( hmenu
, &mi
);
858 if( mnuopt
) mi
.dwStyle
|= mnuopt
== 1 ? MNS_NOCHECK
: MNS_CHECKORBMP
;
859 ret
= SetMenuInfo( hmenu
, &mi
);
860 ok( ret
, "SetMenuInfo failed with error %d\n", GetLastError());
862 ret
= InsertMenuItemA( hmenu
, 0, FALSE
, &mii
);
863 ok( ret
, "InsertMenuItem failed with error %d\n", GetLastError());
865 if( winetest_debug
) {
867 RECT rc
= {100, 50, 400, 70};
870 sprintf( buf
,"%d text \"%s\" mnuopt %d", count
, text
? text
: "(nil)", mnuopt
);
871 FillRect( hdc
, &rc
, (HBRUSH
) COLOR_WINDOW
);
872 TextOutA( hdc
, 10, 50, buf
, strlen( buf
));
873 ReleaseDC( hwnd
, hdc
);
876 TrackPopupMenu( hmenu
, TPM_RETURNCMD
, 100,100, 0, hwnd
, NULL
);
878 ret
= SetMenu( hwnd
, hmenu
);
879 ok(ret
, "SetMenu failed with error %d\n", GetLastError());
882 ret
= GetMenuItemRect( hwnd
, hmenu
, 0, &rc
);
883 ok(ret
, "GetMenuItemRect failed with error %d\n", GetLastError());
885 if (0) /* comment out menu size checks, behavior is different in almost every Windows version */
886 /* the tests should however succeed on win2000, XP and Wine (at least up to 1.1.15) */
887 /* with a variety of dpis and desktop font sizes */
889 /* check menu width */
891 expect
= ( text
|| hbmp
?
892 4 + (mnuopt
!= 1 ? GetSystemMetrics(SM_CXMENUCHECK
) : 0)
894 arrowwidth
+ MOD_avec
+ (hbmp
?
895 ((INT_PTR
)hbmp
<0||(INT_PTR
)hbmp
>12 ? bmpsize
.cx
+ 2 : GetSystemMetrics( SM_CXMENUSIZE
) + 2)
897 (text
&& hastab
? /* TAB space */
898 MOD_avec
+ ( hastab
==2 ? sc_size
.cx
: 0) : 0) +
899 (text
? 2 + (text
[0] ? size
.cx
:0): 0) ;
901 expect
= !(text
|| hbmp
) ? 0 :
902 ( hbmp
? (text
? 2:0) + bmpsize
.cx
: 0 ) +
903 (text
? 2 * MOD_avec
+ (text
[0] ? size
.cx
:0): 0) ;
904 ok( rc
.right
- rc
.left
== expect
,
905 "menu width wrong, got %d expected %d\n", rc
.right
- rc
.left
, expect
);
906 failed
= failed
|| !(rc
.right
- rc
.left
== expect
);
907 /* check menu height */
909 expect
= max( ( !(text
|| hbmp
) ? GetSystemMetrics( SM_CYMENUSIZE
)/2 : 0),
910 max( (text
? max( 2 + size
.cy
, MOD_hic
+ 4) : 0),
912 ((INT_PTR
)hbmp
<0||(INT_PTR
)hbmp
>12 ?
914 : GetSystemMetrics( SM_CYMENUSIZE
) + 2)
917 expect
= ( !(text
|| hbmp
) ? GetSystemMetrics( SM_CYMENUSIZE
)/2 :
918 max( GetSystemMetrics( SM_CYMENU
) - 1, (hbmp
? bmpsize
.cy
: 0)));
919 ok( rc
.bottom
- rc
.top
== expect
,
920 "menu height wrong, got %d expected %d (%d)\n",
921 rc
.bottom
- rc
.top
, expect
, GetSystemMetrics( SM_CYMENU
));
922 failed
= failed
|| !(rc
.bottom
- rc
.top
== expect
);
923 if( hbmp
== HBMMENU_CALLBACK
&& MOD_GotDrawItemMsg
) {
924 /* check the position of the bitmap */
928 else if (mnuopt
== 0)
929 expect
= 4 + GetSystemMetrics(SM_CXMENUCHECK
);
930 else if (mnuopt
== 1)
932 else /* mnuopt == 2 */
934 ok( expect
== MOD_rc
[0].left
,
935 "bitmap left is %d expected %d\n", MOD_rc
[0].left
, expect
);
936 failed
= failed
|| !(expect
== MOD_rc
[0].left
);
938 expect
= (rc
.bottom
- rc
.top
- MOD_rc
[0].bottom
+ MOD_rc
[0].top
) / 2;
939 ok( expect
== MOD_rc
[0].top
,
940 "bitmap top is %d expected %d\n", MOD_rc
[0].top
, expect
);
941 failed
= failed
|| !(expect
== MOD_rc
[0].top
);
944 /* if there was a failure, report details */
946 trace("*** count %d %s text \"%s\" bitmap %p bmsize %d,%d textsize %d+%d,%d mnuopt %d hastab %d\n",
947 count
, (ispop
? "POPUP": "MENUBAR"),text
? text
: "(nil)", hbmp
, bmpsize
.cx
, bmpsize
.cy
,
948 size
.cx
, size
.cy
, sc_size
.cx
, mnuopt
, hastab
);
949 trace(" check %d,%d arrow %d avechar %d\n",
950 GetSystemMetrics(SM_CXMENUCHECK
),
951 GetSystemMetrics(SM_CYMENUCHECK
),arrowwidth
, MOD_avec
);
952 if( hbmp
== HBMMENU_CALLBACK
)
953 trace( " rc %s bmp.rc %s\n", wine_dbgstr_rect(&rc
), wine_dbgstr_rect(&MOD_rc
[0]));
956 ret
= DestroyMenu(submenu
);
957 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
958 ret
= DestroyMenu(hmenu
);
959 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
963 static void test_menu_bmp_and_string(void)
971 MENUINFO mi
= {sizeof(MENUINFO
)};
972 MENUITEMINFOA mii
= {sizeof(MENUITEMINFOA
)};
973 int count
, szidx
, txtidx
, bmpidx
, hassub
, mnuopt
, ispop
;
976 memset( bmfill
, 0xcc, sizeof( bmfill
));
977 hwnd
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
, WS_SYSMENU
|
978 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
979 NULL
, NULL
, NULL
, NULL
);
980 hbm_arrow
= LoadBitmapA( 0, (LPCSTR
)OBM_MNARROW
);
981 GetObjectA( hbm_arrow
, sizeof(bm
), &bm
);
982 arrowwidth
= bm
.bmWidth
;
983 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
985 /* test system menu */
986 hsysmenu
= GetSystemMenu( hwnd
, FALSE
);
987 ok( hsysmenu
!= NULL
, "GetSystemMenu failed with error %d\n", GetLastError());
988 mi
.fMask
= MIM_STYLE
;
990 got
= GetMenuInfo( hsysmenu
, &mi
);
991 ok( got
, "GetMenuInfo failed gle=%d\n", GetLastError());
992 ok( MNS_CHECKORBMP
== mi
.dwStyle
, "System Menu Style is %08x, without the bit %08x\n",
993 mi
.dwStyle
, MNS_CHECKORBMP
);
994 mii
.fMask
= MIIM_BITMAP
;
996 got
= GetMenuItemInfoA( hsysmenu
, SC_CLOSE
, FALSE
, &mii
);
997 ok( got
, "GetMenuItemInfoA failed gle=%d\n", GetLastError());
998 ok( HBMMENU_POPUP_CLOSE
== mii
.hbmpItem
, "Item info did not get the right hbitmap: got %p expected %p\n",
999 mii
.hbmpItem
, HBMMENU_POPUP_CLOSE
);
1001 memset(&mii
, 0x81, sizeof(mii
));
1002 mii
.cbSize
= sizeof(mii
);
1003 mii
.fMask
= MIIM_STATE
| MIIM_ID
| MIIM_TYPE
| MIIM_DATA
;
1004 mii
.dwTypeData
= (LPSTR
)bmfill
;
1005 mii
.cch
= sizeof(bmfill
);
1006 mii
.dwItemData
= 0x81818181;
1007 got
= GetMenuItemInfoA(hsysmenu
, SC_RESTORE
, FALSE
, &mii
);
1008 ok(got
, "GetMenuItemInfo failed\n");
1009 ok((mii
.fType
& ~(MFT_RIGHTJUSTIFY
|MFT_RIGHTORDER
)) == MFT_STRING
, "expected MFT_STRING, got %#x\n", mii
.fType
);
1010 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
1011 ok(mii
.wID
== SC_RESTORE
, "expected SC_RESTORE, got %#x\n", mii
.wID
);
1012 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
1013 ok(mii
.dwItemData
== 0, "expected 0, got %#lx\n", mii
.dwItemData
);
1014 ok(mii
.dwTypeData
== (LPSTR
)bmfill
, "expected %p, got %p\n", bmfill
, mii
.dwTypeData
);
1015 ok(mii
.cch
!= 0, "cch should not be 0\n");
1016 ok(mii
.hbmpItem
== HBMMENU_POPUP_RESTORE
, "expected HBMMENU_POPUP_RESTORE, got %p\n", mii
.hbmpItem
);
1018 mii
.cbSize
= sizeof(mii
);
1019 mii
.fMask
= MIIM_TYPE
;
1020 mii
.hbmpItem
= (HBITMAP
)0x81818181;
1021 got
= GetMenuItemInfoA(hsysmenu
, SC_CLOSE
, FALSE
, &mii
);
1022 ok(got
, "GetMenuItemInfo failed\n");
1023 ok((mii
.fType
& ~(MFT_RIGHTJUSTIFY
|MFT_RIGHTORDER
)) == MFT_STRING
, "expected MFT_STRING, got %#x\n", mii
.fType
);
1024 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
1025 ok(mii
.wID
== SC_RESTORE
, "expected SC_RESTORE, got %#x\n", mii
.wID
);
1026 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
1027 ok(mii
.dwItemData
== 0, "expected 0, got %#lx\n", mii
.dwItemData
);
1028 ok(mii
.dwTypeData
== (LPSTR
)bmfill
, "expected %p, got %p\n", bmfill
, mii
.dwTypeData
);
1029 ok(mii
.cch
!= 0, "cch should not be 0\n");
1030 ok(mii
.hbmpItem
== HBMMENU_POPUP_CLOSE
, "expected HBMMENU_POPUP_CLOSE, got %p\n", mii
.hbmpItem
);
1032 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)menu_ownerdraw_wnd_proc
);
1035 trace(" check %d,%d arrow %d avechar %d\n",
1036 GetSystemMetrics(SM_CXMENUCHECK
),
1037 GetSystemMetrics(SM_CYMENUCHECK
),arrowwidth
, MOD_avec
);
1040 for( ispop
=1; ispop
>= 0; ispop
--){
1041 static SIZE bmsizes
[]= {
1042 {10,10},{38,38},{1,30},{55,5}};
1043 for( szidx
=0; szidx
< ARRAY_SIZE(bmsizes
); szidx
++) {
1044 HBITMAP hbm
= CreateBitmap( bmsizes
[szidx
].cx
, bmsizes
[szidx
].cy
,1,1,bmfill
);
1045 HBITMAP bitmaps
[] = { HBMMENU_CALLBACK
, hbm
, HBMMENU_POPUP_CLOSE
, NULL
};
1046 ok( hbm
!= 0, "CreateBitmap failed err %d\n", GetLastError());
1047 for( txtidx
= 0; txtidx
< ARRAY_SIZE(MOD_txtsizes
); txtidx
++) {
1048 for( hassub
= 0; hassub
< 2 ; hassub
++) { /* add submenu item */
1049 for( mnuopt
= 0; mnuopt
< 3 ; mnuopt
++){ /* test MNS_NOCHECK/MNS_CHECKORBMP */
1050 for( bmpidx
= 0; bmpidx
<ARRAY_SIZE(bitmaps
); bmpidx
++) {
1051 /* no need to test NULL bitmaps of several sizes */
1052 if( !bitmaps
[bmpidx
] && szidx
> 0) continue;
1053 /* the HBMMENU_POPUP not to test for menu bars */
1055 bitmaps
[bmpidx
] >= HBMMENU_POPUP_CLOSE
&&
1056 bitmaps
[bmpidx
] <= HBMMENU_POPUP_MINIMIZE
) continue;
1057 if( !ispop
&& hassub
) continue;
1058 test_mbs_help( ispop
, hassub
, mnuopt
,
1059 hwnd
, arrowwidth
, ++count
,
1062 MOD_txtsizes
[txtidx
].text
,
1063 MOD_txtsizes
[txtidx
].size
,
1064 MOD_txtsizes
[txtidx
].sc_size
);
1073 DestroyWindow(hwnd
);
1076 static void test_menu_add_string( void )
1087 WCHAR strbackW
[0x80];
1088 static CHAR blah
[] = "blah";
1089 static const WCHAR expectedString
[] = {'D','u','m','m','y',' ','s','t','r','i','n','g', 0};
1091 hmenu
= CreateMenu();
1093 memset( &info
, 0, sizeof info
);
1094 info
.cbSize
= sizeof info
;
1095 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_ID
;
1096 info
.dwTypeData
= blah
;
1098 info
.dwItemData
= 0;
1101 InsertMenuItemA(hmenu
, 0, TRUE
, &info
);
1103 memset( &info
, 0, sizeof info
);
1104 info
.cbSize
= sizeof info
;
1105 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_STATE
| MIIM_DATA
| MIIM_ID
;
1106 info
.dwTypeData
= string
;
1107 info
.cch
= sizeof string
;
1109 GetMenuItemInfoA( hmenu
, 0, TRUE
, &info
);
1111 ok( !strcmp( string
, "blah" ), "menu item name differed\n");
1113 /* Test combination of ownerdraw and strings with GetMenuItemString(A/W) */
1114 strcpy(string
, "Dummy string");
1115 memset(&info
, 0x00, sizeof(info
));
1116 info
.cbSize
= sizeof(MENUITEMINFOA
);
1117 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
; /* Set OwnerDraw + typeData */
1118 info
.fType
= MFT_OWNERDRAW
;
1119 info
.dwTypeData
= string
;
1120 rc
= InsertMenuItemA( hmenu
, 0, TRUE
, &info
);
1121 ok (rc
, "InsertMenuItem failed\n");
1123 strcpy(string
,"Garbage");
1124 ok (GetMenuStringA( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
1125 ok (!strcmp( strback
, "Dummy string" ), "Menu text from Ansi version incorrect\n");
1127 ret
= GetMenuStringW( hmenu
, 0, strbackW
, 99, MF_BYPOSITION
);
1128 ok (ret
, "GetMenuStringW on ownerdraw entry failed\n");
1129 ok (!lstrcmpW( strbackW
, expectedString
), "Menu text from Unicode version incorrect\n");
1131 /* Just try some invalid parameter tests */
1132 SetLastError(0xdeadbeef);
1133 rc
= SetMenuItemInfoA( hmenu
, 0, TRUE
, NULL
);
1134 ret
= GetLastError();
1135 ok (!rc
, "SetMenuItemInfoA succeeded unexpectedly\n");
1136 ok (ret
== ERROR_INVALID_PARAMETER
, "Expected 87, got %d\n", ret
);
1138 SetLastError(0xdeadbeef);
1139 rc
= SetMenuItemInfoA( hmenu
, 0, FALSE
, NULL
);
1140 ret
= GetLastError();
1141 ok (!rc
, "SetMenuItemInfoA succeeded unexpectedly\n");
1142 ok (ret
== ERROR_INVALID_PARAMETER
, "Expected 87, got %d\n", ret
);
1144 /* Just change ftype to string and see what text is stored */
1145 memset(&info
, 0x00, sizeof(info
));
1146 info
.cbSize
= sizeof(MENUITEMINFOA
);
1147 info
.fMask
= MIIM_FTYPE
; /* Set string type */
1148 info
.fType
= MFT_STRING
;
1149 info
.dwTypeData
= (char *)0xdeadbeef;
1150 rc
= SetMenuItemInfoA( hmenu
, 0, TRUE
, &info
);
1151 ok (rc
, "SetMenuItemInfo failed\n");
1153 /* Did we keep the old dwTypeData? */
1154 ok (GetMenuStringA( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
1155 ok (!strcmp( strback
, "Dummy string" ), "Menu text from Ansi version incorrect\n");
1157 /* Ensure change to bitmap type fails */
1158 memset(&info
, 0x00, sizeof(info
));
1159 info
.cbSize
= sizeof(MENUITEMINFOA
);
1160 info
.fMask
= MIIM_FTYPE
; /* Set as bitmap type */
1161 info
.fType
= MFT_BITMAP
;
1162 info
.dwTypeData
= (char *)0xdeadbee2;
1163 rc
= SetMenuItemInfoA( hmenu
, 0, TRUE
, &info
);
1164 ok (!rc
, "SetMenuItemInfo unexpectedly worked\n");
1166 /* Just change ftype back and ensure data hasn't been freed */
1167 info
.fType
= MFT_OWNERDRAW
; /* Set as ownerdraw type */
1168 info
.dwTypeData
= (char *)0xdeadbee3;
1169 rc
= SetMenuItemInfoA( hmenu
, 0, TRUE
, &info
);
1170 ok (rc
, "SetMenuItemInfo failed\n");
1172 /* Did we keep the old dwTypeData? */
1173 ok (GetMenuStringA( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
1174 ok (!strcmp( strback
, "Dummy string" ), "Menu text from Ansi version incorrect\n");
1176 /* Just change string value (not type) */
1177 memset(&info
, 0x00, sizeof(info
));
1178 info
.cbSize
= sizeof(MENUITEMINFOA
);
1179 info
.fMask
= MIIM_STRING
; /* Set typeData */
1180 strcpy(string2
, "string2");
1181 info
.dwTypeData
= string2
;
1182 rc
= SetMenuItemInfoA( hmenu
, 0, TRUE
, &info
);
1183 ok (rc
, "SetMenuItemInfo failed\n");
1185 ok (GetMenuStringA( hmenu
, 0, strback
, 99, MF_BYPOSITION
), "GetMenuString on ownerdraw entry failed\n");
1186 ok (!strcmp( strback
, "string2" ), "Menu text from Ansi version incorrect\n");
1188 /* crashes with wine 0.9.5 */
1189 memset(&info
, 0x00, sizeof(info
));
1190 info
.cbSize
= sizeof(MENUITEMINFOA
);
1191 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
; /* Set OwnerDraw + typeData */
1192 info
.fType
= MFT_OWNERDRAW
;
1193 rc
= InsertMenuItemA( hmenu
, 0, TRUE
, &info
);
1194 ok (rc
, "InsertMenuItem failed\n");
1195 ok (!GetMenuStringA( hmenu
, 0, NULL
, 0, MF_BYPOSITION
),
1196 "GetMenuString on ownerdraw entry succeeded.\n");
1197 ret
= GetMenuStringW( hmenu
, 0, NULL
, 0, MF_BYPOSITION
);
1198 ok (!ret
, "GetMenuStringW on ownerdraw entry succeeded.\n");
1200 DestroyMenu( hmenu
);
1203 static void insert_menu_item( int line
, HMENU hmenu
, BOOL ansi
, UINT mask
, UINT type
, UINT state
, UINT id
,
1204 HMENU submenu
, HBITMAP checked
, HBITMAP unchecked
, ULONG_PTR data
,
1205 void *type_data
, UINT len
, HBITMAP item
, BOOL expect
)
1210 /* magic bitmap handle to test smaller cbSize */
1211 if (item
== (HBITMAP
)(ULONG_PTR
)0xdeadbeef)
1212 info
.cbSize
= FIELD_OFFSET(MENUITEMINFOA
,hbmpItem
);
1214 info
.cbSize
= sizeof(info
);
1217 info
.fState
= state
;
1219 info
.hSubMenu
= submenu
;
1220 info
.hbmpChecked
= checked
;
1221 info
.hbmpUnchecked
= unchecked
;
1222 info
.dwItemData
= data
;
1223 info
.dwTypeData
= type_data
;
1225 info
.hbmpItem
= item
;
1226 SetLastError( 0xdeadbeef );
1227 if (ansi
) ret
= InsertMenuItemA( hmenu
, 0, TRUE
, &info
);
1228 else ret
= InsertMenuItemW( hmenu
, 0, TRUE
, (MENUITEMINFOW
*)&info
);
1229 if (!expect
) ok_(__FILE__
, line
)( !ret
, "InsertMenuItem should have failed.\n" );
1230 else ok_(__FILE__
, line
)( ret
, "InsertMenuItem failed, err %u\n", GetLastError());
1233 static void check_menu_item_info( int line
, HMENU hmenu
, BOOL ansi
, UINT mask
, UINT type
, UINT state
,
1234 UINT id
, HMENU submenu
, HBITMAP checked
, HBITMAP unchecked
,
1235 ULONG_PTR data
, void *type_data
, UINT in_len
, UINT out_len
,
1236 HBITMAP item
, LPCSTR expname
, BOOL expect
, BOOL expstring
)
1242 SetLastError( 0xdeadbeef );
1243 memset( &info
, 0xcc, sizeof(info
) );
1244 info
.cbSize
= sizeof(info
);
1246 info
.dwTypeData
= type_data
;
1249 ret
= ansi
? GetMenuItemInfoA( hmenu
, 0, TRUE
, &info
) :
1250 GetMenuItemInfoW( hmenu
, 0, TRUE
, (MENUITEMINFOW
*)&info
);
1253 ok_(__FILE__
, line
)( !ret
, "GetMenuItemInfo should have failed.\n" );
1256 ok_(__FILE__
, line
)( ret
, "GetMenuItemInfo failed, err %u\n", GetLastError());
1257 if (mask
& MIIM_TYPE
)
1258 ok_(__FILE__
, line
)( info
.fType
== type
|| info
.fType
== LOWORD(type
),
1259 "wrong type %x/%x\n", info
.fType
, type
);
1260 if (mask
& MIIM_STATE
)
1261 ok_(__FILE__
, line
)( info
.fState
== state
|| info
.fState
== LOWORD(state
),
1262 "wrong state %x/%x\n", info
.fState
, state
);
1264 ok_(__FILE__
, line
)( info
.wID
== id
|| info
.wID
== LOWORD(id
),
1265 "wrong id %x/%x\n", info
.wID
, id
);
1266 if (mask
& MIIM_SUBMENU
)
1267 ok_(__FILE__
, line
)( info
.hSubMenu
== submenu
|| (ULONG_PTR
)info
.hSubMenu
== LOWORD(submenu
),
1268 "wrong submenu %p/%p\n", info
.hSubMenu
, submenu
);
1269 if (mask
& MIIM_CHECKMARKS
)
1271 ok_(__FILE__
, line
)( info
.hbmpChecked
== checked
|| (ULONG_PTR
)info
.hbmpChecked
== LOWORD(checked
),
1272 "wrong bmpchecked %p/%p\n", info
.hbmpChecked
, checked
);
1273 ok_(__FILE__
, line
)( info
.hbmpUnchecked
== unchecked
|| (ULONG_PTR
)info
.hbmpUnchecked
== LOWORD(unchecked
),
1274 "wrong bmpunchecked %p/%p\n", info
.hbmpUnchecked
, unchecked
);
1276 if (mask
& MIIM_DATA
)
1277 ok_(__FILE__
, line
)( info
.dwItemData
== data
|| info
.dwItemData
== LOWORD(data
),
1278 "wrong item data %lx/%lx\n", info
.dwItemData
, data
);
1279 if (mask
& MIIM_BITMAP
)
1280 ok_(__FILE__
, line
)( info
.hbmpItem
== item
|| (ULONG_PTR
)info
.hbmpItem
== LOWORD(item
),
1281 "wrong bmpitem %p/%p\n", info
.hbmpItem
, item
);
1282 ok_(__FILE__
, line
)( info
.dwTypeData
== type_data
|| (ULONG_PTR
)info
.dwTypeData
== LOWORD(type_data
),
1283 "wrong type data %p/%p\n", info
.dwTypeData
, type_data
);
1284 ok_(__FILE__
, line
)( info
.cch
== out_len
||
1285 broken(! ansi
&& info
.cch
== 2 * out_len
) /* East-Asian */,
1286 "wrong len %x/%x\n", info
.cch
, out_len
);
1290 ok_(__FILE__
, line
)( !strncmp( expname
, info
.dwTypeData
, out_len
),
1291 "menu item name differed from '%s' '%s'\n", expname
, info
.dwTypeData
);
1293 ok_(__FILE__
, line
)( !wcsncmp( (WCHAR
*)expname
, (WCHAR
*)info
.dwTypeData
, out_len
),
1294 "menu item name wrong\n" );
1296 SetLastError( 0xdeadbeef );
1297 ret
= ansi
? GetMenuStringA( hmenu
, 0, (char *)buffer
, 80, MF_BYPOSITION
) :
1298 GetMenuStringW( hmenu
, 0, buffer
, 80, MF_BYPOSITION
);
1300 ok_(__FILE__
, line
)( ret
, "GetMenuString failed, err %u\n", GetLastError());
1302 ok_(__FILE__
, line
)( !ret
, "GetMenuString should have failed\n" );
1306 static void modify_menu( int line
, HMENU hmenu
, BOOL ansi
, UINT flags
, UINT_PTR id
, void *data
)
1310 SetLastError( 0xdeadbeef );
1311 if (ansi
) ret
= ModifyMenuA( hmenu
, 0, flags
, id
, data
);
1312 else ret
= ModifyMenuW( hmenu
, 0, flags
, id
, data
);
1313 ok_(__FILE__
,line
)( ret
, "ModifyMenuA failed, err %u\n", GetLastError());
1316 static void set_menu_item_info( int line
, HMENU hmenu
, BOOL ansi
, UINT mask
, UINT type
, UINT state
,
1317 UINT id
, HMENU submenu
, HBITMAP checked
, HBITMAP unchecked
, ULONG_PTR data
,
1318 void *type_data
, UINT len
, HBITMAP item
)
1324 /* magic bitmap handle to test smaller cbSize */
1325 if (item
== (HBITMAP
)(ULONG_PTR
)0xdeadbeef)
1326 info
.cbSize
= FIELD_OFFSET(MENUITEMINFOA
,hbmpItem
);
1328 info
.cbSize
= sizeof(info
);
1331 info
.fState
= state
;
1333 info
.hSubMenu
= submenu
;
1334 info
.hbmpChecked
= checked
;
1335 info
.hbmpUnchecked
= unchecked
;
1336 info
.dwItemData
= data
;
1337 info
.dwTypeData
= type_data
;
1339 info
.hbmpItem
= item
;
1340 SetLastError( 0xdeadbeef );
1341 if (ansi
) ret
= SetMenuItemInfoA( hmenu
, 0, TRUE
, &info
);
1342 else ret
= SetMenuItemInfoW( hmenu
, 0, TRUE
, (MENUITEMINFOW
*)&info
);
1343 ok_(__FILE__
, line
)( ret
, "SetMenuItemInfo failed, err %u\n", GetLastError());
1346 #define TMII_INSMI( c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,eret1 )\
1347 hmenu = CreateMenu();\
1348 submenu = CreateMenu();\
1349 if(ansi)strcpy( string, init );\
1350 else wcscpy( string, init );\
1351 insert_menu_item( __LINE__, hmenu, ansi, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1, eret1 )
1353 /* GetMenuItemInfo + GetMenuString */
1354 #define TMII_GMII( c2,l2,\
1355 d3,e3,f3,g3,h3,i3,j3,k3,l3,m3,\
1356 expname, eret2, eret3)\
1357 check_menu_item_info( __LINE__, hmenu, ansi, c2, d3, e3, f3, g3, h3, i3, j3, k3, l2, l3, m3, \
1358 expname, eret2, eret3 )
1361 RemoveMenu(hmenu, 0, TRUE );\
1362 DestroyMenu( hmenu );\
1363 DestroyMenu( submenu );
1366 #define TMII_MODM( flags, id, data ) \
1367 modify_menu( __LINE__, hmenu, ansi, flags, id, data )
1369 /* SetMenuItemInfo */
1370 #define TMII_SMII( c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1 ) \
1371 set_menu_item_info( __LINE__, hmenu, ansi, c1, d1, e1, f1, g1, h1, i1, j1, k1, l1, m1 )
1378 static void test_menu_iteminfo( void )
1384 WCHAR txtW
[]={'W','i','n','e',0};
1385 WCHAR initW
[]={'X','Y','Z',0};
1387 void *txt
, *init
, *empty
, *string
;
1388 HBITMAP hbm
= CreateBitmap(1,1,1,1,NULL
);
1390 HMENU hmenu
, submenu
;
1391 HBITMAP dummy_hbm
= (HBITMAP
)(ULONG_PTR
)0xdeadbeef;
1394 if( ansi
) {txt
=txtA
;init
=initA
;empty
=emptyA
;string
=stringA
;}
1395 else {txt
=txtW
;init
=initW
;empty
=emptyW
;string
=stringA
;}
1396 trace( "%s string %p hbm %p txt %p\n", ansi
? "ANSI tests: " : "Unicode tests:", string
, hbm
, txt
);
1397 /* test all combinations of MFT_STRING, MFT_OWNERDRAW and MFT_BITMAP */
1398 /* (since MFT_STRING is zero, there are four of them) */
1399 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, 0, 0, 0, 0, 0, 0, txt
, 0, 0, OK
);
1400 TMII_GMII ( MIIM_TYPE
, 80,
1401 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 4, 0,
1404 TMII_INSMI( MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 0, 0, OK
);
1405 TMII_GMII ( MIIM_TYPE
, 80,
1406 MFT_STRING
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1409 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, hbm
, 6, 0, OK
);
1410 TMII_GMII ( MIIM_TYPE
, 80,
1411 MFT_BITMAP
, 0, 0, 0, 0, 0, 0, hbm
, 0, hbm
,
1414 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, hbm
, 6, 0, OK
);
1415 TMII_GMII ( MIIM_TYPE
, 80,
1416 MFT_BITMAP
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, hbm
, 0, hbm
,
1419 /* not enough space for name*/
1420 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1421 TMII_GMII ( MIIM_TYPE
, 0,
1422 MFT_STRING
, 0, 0, 0, 0, 0, 0, NULL
, 4, 0,
1425 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1426 TMII_GMII ( MIIM_TYPE
, 5,
1427 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 4, 0,
1430 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1431 TMII_GMII ( MIIM_TYPE
, 4,
1432 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 3, 0,
1435 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
, MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, NULL
, 0, 0, OK
);
1436 TMII_GMII ( MIIM_TYPE
, 0,
1437 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, NULL
, 0, 0,
1440 /* cannot combine MIIM_TYPE with some other flags */
1441 TMII_INSMI( MIIM_TYPE
|MIIM_STRING
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, ER
);
1443 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1444 TMII_GMII ( MIIM_TYPE
|MIIM_STRING
, 80,
1445 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1448 TMII_INSMI( MIIM_TYPE
|MIIM_FTYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, ER
);
1450 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1451 TMII_GMII ( MIIM_TYPE
|MIIM_FTYPE
, 80,
1452 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1455 TMII_INSMI( MIIM_TYPE
|MIIM_BITMAP
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, hbm
, 6, hbm
, ER
);
1457 /* but succeeds with some others */
1458 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1459 TMII_GMII ( MIIM_TYPE
|MIIM_SUBMENU
, 80,
1460 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 4, 0,
1463 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1464 TMII_GMII ( MIIM_TYPE
|MIIM_STATE
, 80,
1465 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 4, 0,
1468 TMII_INSMI( MIIM_TYPE
|MIIM_ID
, MFT_STRING
, -1, 888, 0, 0, 0, -1, txt
, 6, 0, OK
);
1469 TMII_GMII ( MIIM_TYPE
|MIIM_ID
, 80,
1470 MFT_STRING
, 0, 888, 0, 0, 0, 0, string
, 4, 0,
1473 TMII_INSMI( MIIM_TYPE
|MIIM_DATA
, MFT_STRING
, -1, -1, 0, 0, 0, 999, txt
, 6, 0, OK
);
1474 TMII_GMII ( MIIM_TYPE
|MIIM_DATA
, 80,
1475 MFT_STRING
, 0, 0, 0, 0, 0, 999, string
, 4, 0,
1478 /* to be continued */
1479 /* set text with MIIM_TYPE and retrieve with MIIM_STRING */
1480 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1481 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1482 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 4, 0,
1485 /* set text with MIIM_TYPE and retrieve with MIIM_STRING; MFT_OWNERDRAW causes an empty string */
1486 TMII_INSMI( MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1487 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1488 MFT_STRING
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, string
, 0, 0,
1491 TMII_INSMI( MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, NULL
, 0, 0, OK
);
1492 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1493 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, string
, 0, 0,
1496 TMII_INSMI( MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, NULL
, 0, 0, OK
);
1497 TMII_GMII ( MIIM_FTYPE
, 80,
1498 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, string
, 80, 0,
1501 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 0, 0, OK
);
1503 0, 0, 0, 0, 0, 0, 0, string
, 80, 0,
1506 /* contrary to MIIM_TYPE,you can set the text for an owner draw menu */
1507 TMII_INSMI( MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 0, 0, OK
);
1508 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1509 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, string
, 4, 0,
1512 /* same but retrieve with MIIM_TYPE */
1513 TMII_INSMI( MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 0, 0, OK
);
1514 TMII_GMII ( MIIM_TYPE
, 80,
1515 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, NULL
, 4, NULL
,
1518 TMII_INSMI( MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, NULL
, 0, 0, OK
);
1519 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1520 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, string
, 0, 0,
1523 TMII_INSMI( MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, NULL
, 0, 0, OK
);
1524 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1525 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, string
, 0, 0,
1528 TMII_INSMI( MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, NULL
, 0, 0, OK
);
1529 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1530 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, NULL
, 0, 0,
1534 /* How is that with bitmaps? */
1535 TMII_INSMI( MIIM_BITMAP
, -1, -1, -1, 0, 0, 0, -1, 0, -1, hbm
, OK
);
1536 TMII_GMII ( MIIM_TYPE
, 80,
1537 MFT_BITMAP
, 0, 0, 0, 0, 0, 0, hbm
, 0, hbm
,
1540 TMII_INSMI( MIIM_BITMAP
, -1, -1, -1, 0, 0, 0, -1, 0, -1, hbm
, OK
);
1541 TMII_GMII ( MIIM_BITMAP
|MIIM_FTYPE
, 80,
1542 0, 0, 0, 0, 0, 0, 0, string
, 80, hbm
,
1545 /* MIIM_BITMAP does not like MFT_BITMAP */
1546 TMII_INSMI( MIIM_BITMAP
|MIIM_FTYPE
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, 0, -1, hbm
, ER
);
1548 /* no problem with OWNERDRAWN */
1549 TMII_INSMI( MIIM_BITMAP
|MIIM_FTYPE
, MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, 0, -1, hbm
, OK
);
1550 TMII_GMII ( MIIM_BITMAP
|MIIM_FTYPE
, 80,
1551 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, string
, 80, hbm
,
1554 /* setting MFT_BITMAP with MFT_FTYPE fails anyway */
1555 TMII_INSMI( MIIM_FTYPE
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, 0, -1, 0, ER
);
1558 /* menu with submenu */
1559 TMII_INSMI( MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, submenu
, 0, 0, -1, txt
, 0, 0, OK
);
1560 TMII_GMII ( MIIM_SUBMENU
, 80,
1561 0, 0, 0, submenu
, 0, 0, 0, string
, 80, 0,
1564 TMII_INSMI( MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, submenu
, 0, 0, -1, empty
, 0, 0, OK
);
1565 TMII_GMII ( MIIM_SUBMENU
, 80,
1566 0, 0, 0, submenu
, 0, 0, 0, string
, 80, 0,
1569 /* menu with submenu, without MIIM_SUBMENU the submenufield is cleared */
1570 TMII_INSMI( MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, submenu
, 0, 0, -1, txt
, 0, 0, OK
);
1571 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1572 MFT_STRING
|MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, string
, 0, 0,
1574 TMII_GMII ( MIIM_SUBMENU
|MIIM_FTYPE
, 80,
1575 MFT_SEPARATOR
, 0, 0, submenu
, 0, 0, 0, string
, 80, 0,
1578 /* menu with invalid submenu */
1579 TMII_INSMI( MIIM_SUBMENU
|MIIM_FTYPE
, MFT_STRING
, -1, -1, (HMENU
)999, 0, 0, -1, txt
, 0, 0, ER
);
1582 TMII_INSMI( MIIM_TYPE
, MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, txt
, 0, 0, OK
);
1583 TMII_GMII ( MIIM_TYPE
, 80,
1584 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1587 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
|MFT_SEPARATOR
, -1, -1, 0, 0, 0, -1, hbm
, 6, 0, OK
);
1588 TMII_GMII ( MIIM_TYPE
, 80,
1589 MFT_BITMAP
|MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, hbm
, 0, hbm
,
1592 /* SEPARATOR and STRING go well together */
1593 /* BITMAP and STRING go well together */
1594 TMII_INSMI( MIIM_STRING
|MIIM_BITMAP
, -1, -1, -1, 0, 0, 0, -1, txt
, 6, hbm
, OK
);
1595 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, 80,
1596 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 4, hbm
,
1599 /* BITMAP, SEPARATOR and STRING go well together */
1600 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, 0, 0, 0, -1, txt
, 6, hbm
, OK
);
1601 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, 80,
1602 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, string
, 4, hbm
,
1605 /* last two tests, but use MIIM_TYPE to retrieve info */
1606 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
, MFT_SEPARATOR
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1607 TMII_GMII ( MIIM_TYPE
, 80,
1608 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, NULL
, 4, NULL
,
1611 TMII_INSMI( MIIM_STRING
|MIIM_BITMAP
, -1, -1, -1, 0, 0, 0, -1, txt
, 6, hbm
, OK
);
1612 TMII_GMII ( MIIM_TYPE
, 80,
1613 MFT_BITMAP
, 0, 0, 0, 0, 0, 0, hbm
, 4, hbm
,
1616 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, 0, 0, 0, -1, txt
, 6, hbm
, OK
);
1617 TMII_GMII ( MIIM_TYPE
, 80,
1618 MFT_SEPARATOR
|MFT_BITMAP
, 0, 0, 0, 0, 0, 0, hbm
, 4, hbm
,
1621 /* same three with MFT_OWNERDRAW */
1622 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 6, 0, OK
);
1623 TMII_GMII ( MIIM_TYPE
, 80,
1624 MFT_SEPARATOR
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, NULL
, 4, NULL
,
1627 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 6, hbm
, OK
);
1628 TMII_GMII ( MIIM_TYPE
, 80,
1629 MFT_BITMAP
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, hbm
, 4, hbm
,
1632 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 6, hbm
, OK
);
1633 TMII_GMII ( MIIM_TYPE
, 80,
1634 MFT_SEPARATOR
|MFT_BITMAP
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, hbm
, 4, hbm
,
1638 TMII_INSMI( MIIM_STRING
|MIIM_FTYPE
|MIIM_ID
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 0, 0, OK
);
1639 TMII_GMII ( MIIM_TYPE
, 80,
1640 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, NULL
, 4, NULL
,
1643 /* test with modifymenu: string is preserved after setting OWNERDRAW */
1644 TMII_INSMI( MIIM_STRING
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 0, 0, OK
);
1645 TMII_MODM( MFT_OWNERDRAW
, -1, (void*)787 );
1646 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_DATA
, 80,
1647 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 787, string
, 4, 0,
1650 /* same with bitmap: now the text is cleared */
1651 TMII_INSMI( MIIM_STRING
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 0, 0, OK
);
1652 TMII_MODM( MFT_BITMAP
, 545, hbm
);
1653 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, 80,
1654 MFT_BITMAP
, 0, 545, 0, 0, 0, 0, string
, 0, hbm
,
1657 /* start with bitmap: now setting text clears it (though he flag is raised) */
1658 TMII_INSMI( MIIM_BITMAP
, MFT_STRING
, -1, -1, 0, 0, 0, -1, 0, -1, hbm
, OK
);
1659 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, 80,
1660 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 0, hbm
,
1662 TMII_MODM( MFT_STRING
, 545, txt
);
1663 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, 80,
1664 MFT_STRING
, 0, 545, 0, 0, 0, 0, string
, 4, 0,
1667 /*repeat with text NULL */
1668 TMII_INSMI( MIIM_BITMAP
, MFT_STRING
, -1, -1, 0, 0, 0, -1, 0, -1, hbm
, OK
);
1669 TMII_MODM( MFT_STRING
, 545, NULL
);
1670 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, 80,
1671 MFT_SEPARATOR
, 0, 545, 0, 0, 0, 0, string
, 0, 0,
1674 /* repeat with text "" */
1675 TMII_INSMI( MIIM_BITMAP
, -1 , -1, -1, 0, 0, 0, -1, 0, -1, hbm
, OK
);
1676 TMII_MODM( MFT_STRING
, 545, empty
);
1677 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_ID
, 80,
1678 MFT_STRING
, 0, 545, 0, 0, 0, 0, string
, 0, 0,
1681 /* start with bitmap: set ownerdraw */
1682 TMII_INSMI( MIIM_BITMAP
, -1, -1, -1, 0, 0, 0, -1, 0, -1, hbm
, OK
);
1683 TMII_MODM( MFT_OWNERDRAW
, -1, (void *)232 );
1684 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
|MIIM_DATA
, 80,
1685 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 232, string
, 0, hbm
,
1689 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, 0, 0, 0, -1, txt
, 6, hbm
, OK
);
1691 0, 0, 0, 0, 0, 0, 0, string
, 80, 0,
1694 /* some tests with small cbSize: the hbmpItem is to be ignored */
1695 TMII_INSMI( MIIM_BITMAP
, -1, -1, -1, 0, 0, 0, -1, 0, -1, dummy_hbm
, OK
);
1696 TMII_GMII ( MIIM_TYPE
, 80,
1697 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, NULL
, 0, NULL
,
1700 TMII_INSMI( MIIM_BITMAP
, -1, -1, -1, 0, 0, 0, -1, 0, -1, dummy_hbm
, OK
);
1701 TMII_GMII ( MIIM_BITMAP
|MIIM_FTYPE
, 80,
1702 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, string
, 80, NULL
,
1705 TMII_INSMI( MIIM_STRING
|MIIM_BITMAP
, -1, -1, -1, 0, 0, 0, -1, txt
, 6, dummy_hbm
, OK
);
1706 TMII_GMII ( MIIM_TYPE
, 80,
1707 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 4, NULL
,
1710 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
, -1, -1, 0, 0, 0, -1, txt
, 6, dummy_hbm
, OK
);
1711 TMII_GMII ( MIIM_TYPE
, 80,
1712 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, NULL
, 4, NULL
,
1715 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 6, dummy_hbm
, OK
);
1716 TMII_GMII ( MIIM_TYPE
, 80,
1717 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, NULL
, 4, NULL
,
1720 TMII_INSMI( MIIM_FTYPE
|MIIM_STRING
|MIIM_BITMAP
, MFT_SEPARATOR
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, -1, txt
, 6, dummy_hbm
, OK
);
1721 TMII_GMII ( MIIM_TYPE
, 80,
1722 MFT_SEPARATOR
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, NULL
, 4, NULL
,
1725 /* MIIM_TYPE by itself does not get/set the dwItemData for OwnerDrawn menus */
1726 TMII_INSMI( MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, 343, txt
, 0, 0, OK
);
1727 TMII_GMII ( MIIM_TYPE
|MIIM_DATA
, 80,
1728 MFT_STRING
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 343, 0, 0, 0,
1731 TMII_INSMI( MIIM_TYPE
|MIIM_DATA
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, 343, txt
, 0, 0, OK
);
1732 TMII_GMII ( MIIM_TYPE
, 80,
1733 MFT_STRING
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1736 TMII_INSMI( MIIM_TYPE
, MFT_STRING
|MFT_OWNERDRAW
, -1, -1, 0, 0, 0, 343, txt
, 0, 0, OK
);
1737 TMII_GMII ( MIIM_TYPE
|MIIM_DATA
, 80,
1738 MFT_STRING
|MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1741 /* set a string menu to ownerdraw with MIIM_TYPE */
1742 TMII_INSMI( MIIM_TYPE
, MFT_STRING
, -2, -2, 0, 0, 0, -2, txt
, -2, 0, OK
);
1743 TMII_SMII ( MIIM_TYPE
, MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
1744 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1745 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, string
, 4, 0,
1748 /* test with modifymenu add submenu */
1749 TMII_INSMI( MIIM_STRING
, MFT_STRING
, -1, -1, 0, 0, 0, -1, txt
, 0, 0, OK
);
1750 TMII_MODM( MF_POPUP
, (UINT_PTR
)submenu
, txt
);
1751 TMII_GMII ( MIIM_FTYPE
|MIIM_STRING
|MIIM_SUBMENU
, 80,
1752 MFT_STRING
, 0, 0, submenu
, 0, 0, 0, string
, 4, 0,
1754 TMII_GMII ( MIIM_TYPE
, 80,
1755 MFT_STRING
, 0, 0, 0, 0, 0, 0, string
, 4, 0,
1758 /* MFT_SEPARATOR bit is kept when the text is added */
1759 TMII_INSMI( MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, NULL
, 0, 0, OK
);
1760 TMII_SMII( MIIM_STRING
, 0, 0, 0, 0, 0, 0, 0, txt
, 0, 0 );
1761 TMII_GMII ( MIIM_STRING
|MIIM_FTYPE
, 80,
1762 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, string
, 4, 0,
1765 /* MFT_SEPARATOR bit is kept when bitmap is added */
1766 TMII_INSMI( MIIM_STRING
|MIIM_FTYPE
, MFT_STRING
, -1, -1, 0, 0, 0, -1, NULL
, 0, 0, OK
);
1767 TMII_SMII( MIIM_BITMAP
, 0, 0, 0, 0, 0, 0, 0, 0, 0, hbm
);
1768 TMII_GMII ( MIIM_BITMAP
|MIIM_FTYPE
, 80,
1769 MFT_SEPARATOR
, 0, 0, 0, 0, 0, 0, string
, 80, hbm
,
1772 /* Bitmaps inserted with MIIM_TYPE and MFT_BITMAP:
1773 Only the low word of the dwTypeData is used.
1774 Use a magic bitmap here (Word 95 uses this to create its MDI menu buttons) */
1775 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
| MFT_RIGHTJUSTIFY
, -1, -1, 0, 0, 0, -1,
1776 (HMENU
)MAKELPARAM(HBMMENU_MBAR_CLOSE
, 0x1234), -1, 0, OK
);
1777 TMII_GMII ( MIIM_TYPE
, 80,
1778 MFT_BITMAP
| MFT_RIGHTJUSTIFY
, 0, 0, 0, 0, 0, 0, HBMMENU_MBAR_CLOSE
, 0, HBMMENU_MBAR_CLOSE
,
1782 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_RIGHTORDER
, -1, -1, 0, 0, 0, -1, hbm
, -1, 0, OK
);
1783 TMII_GMII ( MIIM_TYPE
, 80,
1784 MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_RIGHTORDER
, 0, 0, 0, 0, 0, 0, hbm
, 0, hbm
,
1788 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, hbm
, -1, 0, OK
);
1789 TMII_SMII( MIIM_STATE
, -1, MFS_CHECKED
| MFS_DEFAULT
| MFS_GRAYED
| MFS_HILITE
, 0, 0, 0, 0, 0, 0, 0, 0 );
1790 TMII_GMII ( MIIM_STATE
, 80,
1791 0, MFS_CHECKED
| MFS_DEFAULT
| MFS_GRAYED
| MFS_HILITE
, 0, 0, 0, 0, 0, 0, 80, 0,
1794 /* The style MFT_RADIOCHECK cannot be set with MIIM_CHECKMARKS only */
1795 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, hbm
, -1, 0, OK
);
1796 TMII_SMII( MIIM_CHECKMARKS
, MFT_RADIOCHECK
, 0, 0, 0, hbm
, hbm
, 0, 0, 0, 0 );
1797 TMII_GMII ( MIIM_CHECKMARKS
| MIIM_TYPE
, 80,
1798 MFT_BITMAP
, 0, 0, 0, hbm
, hbm
, 0, hbm
, 0, hbm
,
1801 /* MFT_BITMAP is added automatically by GetMenuItemInfo() for MIIM_TYPE */
1802 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, hbm
, -1, 0, OK
);
1803 TMII_SMII( MIIM_FTYPE
, MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, (HBITMAP
)0x1234, 0, 0 );
1804 TMII_GMII ( MIIM_FTYPE
, 80,
1805 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, 0, 80, 0,
1807 TMII_GMII ( MIIM_TYPE
, 80,
1808 MFT_BITMAP
| MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, hbm
, 0, hbm
,
1810 TMII_GMII ( MIIM_FTYPE
, 80,
1811 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, 0, 80, 0,
1813 TMII_SMII( MIIM_BITMAP
, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL
);
1814 TMII_GMII ( MIIM_TYPE
, 80,
1815 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, NULL
, 0, NULL
,
1818 /* Bitmaps inserted with MIIM_TYPE and MFT_BITMAP:
1819 Only the low word of the dwTypeData is used.
1820 Use a magic bitmap here (Word 95 uses this to create its MDI menu buttons) */
1821 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
| MFT_RIGHTJUSTIFY
, -1, -1, 0, 0, 0, -1,
1822 (HMENU
)MAKELPARAM(HBMMENU_MBAR_CLOSE
, 0x1234), -1, 0, OK
);
1823 TMII_GMII ( MIIM_TYPE
, 80,
1824 MFT_BITMAP
| MFT_RIGHTJUSTIFY
, 0, 0, 0, 0, 0, 0, HBMMENU_MBAR_CLOSE
, 0, HBMMENU_MBAR_CLOSE
,
1828 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_RIGHTORDER
, -1, -1, 0, 0, 0, -1, hbm
, -1, 0, OK
);
1829 TMII_GMII ( MIIM_TYPE
, 80,
1830 MFT_BITMAP
| MFT_MENUBARBREAK
| MFT_RADIOCHECK
| MFT_RIGHTJUSTIFY
| MFT_RIGHTORDER
, 0, 0, 0, 0, 0, 0, hbm
, 0, hbm
,
1834 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, hbm
, -1, 0, OK
);
1835 TMII_SMII( MIIM_STATE
, -1, MFS_CHECKED
| MFS_DEFAULT
| MFS_GRAYED
| MFS_HILITE
, 0, 0, 0, 0, 0, 0, 0, 0 );
1836 TMII_GMII ( MIIM_STATE
, 80,
1837 0, MFS_CHECKED
| MFS_DEFAULT
| MFS_GRAYED
| MFS_HILITE
, 0, 0, 0, 0, 0, 0, 80, 0,
1840 /* The style MFT_RADIOCHECK cannot be set with MIIM_CHECKMARKS only */
1841 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, hbm
, -1, 0, OK
);
1842 TMII_SMII( MIIM_CHECKMARKS
, MFT_RADIOCHECK
, 0, 0, 0, hbm
, hbm
, 0, 0, 0, 0 );
1843 TMII_GMII ( MIIM_CHECKMARKS
| MIIM_TYPE
, 80,
1844 MFT_BITMAP
, 0, 0, 0, hbm
, hbm
, 0, hbm
, 0, hbm
,
1847 /* MFT_BITMAP is added automatically by GetMenuItemInfo() for MIIM_TYPE */
1848 TMII_INSMI( MIIM_TYPE
, MFT_BITMAP
, -1, -1, 0, 0, 0, -1, hbm
, -1, 0, OK
);
1849 TMII_SMII( MIIM_FTYPE
, MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, (HBITMAP
)0x1234, 0, 0 );
1850 TMII_GMII ( MIIM_FTYPE
, 80,
1851 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, 0, 80, 0,
1853 TMII_GMII ( MIIM_TYPE
, 80,
1854 MFT_BITMAP
| MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, hbm
, 0, hbm
,
1856 TMII_GMII ( MIIM_FTYPE
, 80,
1857 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, 0, 80, 0,
1859 TMII_SMII( MIIM_BITMAP
, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL
);
1860 TMII_GMII ( MIIM_TYPE
, 80,
1861 MFT_OWNERDRAW
, 0, 0, 0, 0, 0, 0, NULL
, 0, NULL
,
1864 } while( !(ansi
= !ansi
) );
1869 The following tests try to confirm the algorithm used to return the menu items
1870 when there is a collision between a menu item and a popup menu
1872 static void test_menu_search_bycommand( void )
1874 HMENU hmenu
, hmenuSub
, hmenuSub2
;
1880 static CHAR menuitem
[] = "MenuItem",
1881 menuitem2
[] = "MenuItem 2";
1883 /* Case 1: Menu containing a menu item */
1884 hmenu
= CreateMenu();
1886 memset( &info
, 0, sizeof info
);
1887 info
.cbSize
= sizeof info
;
1888 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1889 info
.fType
= MFT_STRING
;
1890 strcpy(strIn
, "Case 1 MenuItem");
1891 info
.dwTypeData
= strIn
;
1892 info
.wID
= (UINT
) 0x1234;
1894 rc
= InsertMenuItemA(hmenu
, 0, TRUE
, &info
);
1895 ok (rc
, "Inserting the menuitem failed\n");
1897 id
= GetMenuItemID(hmenu
, 0);
1898 ok (id
== 0x1234, "Getting the menuitem id failed(gave %x)\n", id
);
1900 /* Confirm the menuitem was given the id supplied (getting by position) */
1901 memset( &info
, 0, sizeof info
);
1903 info
.cbSize
= sizeof(MENUITEMINFOA
);
1904 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1905 info
.dwTypeData
= strback
;
1906 info
.cch
= sizeof(strback
);
1908 rc
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &info
); /* Get by position */
1909 ok (rc
, "Getting the menu items info failed\n");
1910 ok (info
.wID
== 0x1234, "IDs differ for the menuitem\n");
1911 ok (!strcmp(info
.dwTypeData
, "Case 1 MenuItem"), "Returned item has wrong label\n");
1913 /* Search by id - Should return the item */
1914 memset( &info
, 0, sizeof info
);
1916 info
.cbSize
= sizeof(MENUITEMINFOA
);
1917 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1918 info
.dwTypeData
= strback
;
1919 info
.cch
= sizeof(strback
);
1920 rc
= GetMenuItemInfoA(hmenu
, 0x1234, FALSE
, &info
); /* Get by ID */
1922 ok (rc
, "Getting the menu items info failed\n");
1923 ok (info
.wID
== 0x1234, "IDs differ for the menuitem\n");
1924 ok (!strcmp(info
.dwTypeData
, "Case 1 MenuItem"), "Returned item has wrong label\n");
1926 DestroyMenu( hmenu
);
1928 /* Case 2: Menu containing a popup menu */
1929 hmenu
= CreateMenu();
1930 hmenuSub
= CreateMenu();
1932 strcpy(strIn
, "Case 2 SubMenu");
1933 rc
= InsertMenuA(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, strIn
);
1934 ok (rc
, "Inserting the popup menu into the main menu failed\n");
1936 id
= GetMenuItemID(hmenu
, 0);
1937 ok (id
== -1, "Getting the menuitem id unexpectedly worked (gave %x)\n", id
);
1939 /* Confirm the menuitem itself was given an id the same as the HMENU, (getting by position) */
1940 memset( &info
, 0, sizeof info
);
1942 info
.cbSize
= sizeof(MENUITEMINFOA
);
1943 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1944 info
.dwTypeData
= strback
;
1945 info
.cch
= sizeof(strback
);
1946 info
.wID
= 0xdeadbeef;
1948 rc
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &info
); /* Get by position */
1949 ok (rc
, "Getting the menu items info failed\n");
1950 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the menuitem\n");
1951 ok (!strcmp(info
.dwTypeData
, "Case 2 SubMenu"), "Returned item has wrong label\n");
1953 /* Search by id - returns the popup menu itself */
1954 memset( &info
, 0, sizeof info
);
1956 info
.cbSize
= sizeof(MENUITEMINFOA
);
1957 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1958 info
.dwTypeData
= strback
;
1959 info
.cch
= sizeof(strback
);
1960 rc
= GetMenuItemInfoA(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
); /* Get by ID */
1962 ok (rc
, "Getting the menu items info failed\n");
1963 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the popup menu\n");
1964 ok (!strcmp(info
.dwTypeData
, "Case 2 SubMenu"), "Returned item has wrong label\n");
1967 Now add an item after it with the same id
1969 memset( &info
, 0, sizeof info
);
1970 info
.cbSize
= sizeof info
;
1971 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1972 info
.fType
= MFT_STRING
;
1973 strcpy(strIn
, "Case 2 MenuItem 1");
1974 info
.dwTypeData
= strIn
;
1975 info
.wID
= (UINT_PTR
) hmenuSub
;
1976 rc
= InsertMenuItemA(hmenu
, -1, TRUE
, &info
);
1977 ok (rc
, "Inserting the menuitem failed\n");
1979 /* Search by id - returns the item which follows the popup menu */
1980 memset( &info
, 0, sizeof info
);
1982 info
.cbSize
= sizeof(MENUITEMINFOA
);
1983 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
1984 info
.dwTypeData
= strback
;
1985 info
.cch
= sizeof(strback
);
1986 rc
= GetMenuItemInfoA(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
); /* Get by ID */
1988 ok (rc
, "Getting the menu items info failed\n");
1989 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the popup menu\n");
1990 ok (!strcmp(info
.dwTypeData
, "Case 2 MenuItem 1"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
1993 Now add an item before the popup (with the same id)
1995 memset( &info
, 0, sizeof info
);
1996 info
.cbSize
= sizeof info
;
1997 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
1998 info
.fType
= MFT_STRING
;
1999 strcpy(strIn
, "Case 2 MenuItem 2");
2000 info
.dwTypeData
= strIn
;
2001 info
.wID
= (UINT_PTR
) hmenuSub
;
2002 rc
= InsertMenuItemA(hmenu
, 0, TRUE
, &info
);
2003 ok (rc
, "Inserting the menuitem failed\n");
2005 /* Search by id - returns the item which precedes the popup menu */
2006 memset( &info
, 0, sizeof info
);
2008 info
.cbSize
= sizeof(MENUITEMINFOA
);
2009 info
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
;
2010 info
.dwTypeData
= strback
;
2011 info
.cch
= sizeof(strback
);
2012 rc
= GetMenuItemInfoA(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
); /* Get by ID */
2014 ok (rc
, "Getting the menu items info failed\n");
2015 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for the popup menu\n");
2016 ok (!strcmp(info
.dwTypeData
, "Case 2 MenuItem 2"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
2018 DestroyMenu( hmenu
);
2019 DestroyMenu( hmenuSub
);
2022 Case 3: Menu containing a popup menu which in turn
2023 contains 2 items with the same id as the popup itself
2026 hmenu
= CreateMenu();
2027 hmenuSub
= CreateMenu();
2029 memset( &info
, 0, sizeof info
);
2030 info
.cbSize
= sizeof info
;
2031 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
2032 info
.fType
= MFT_STRING
;
2033 info
.dwTypeData
= menuitem
;
2034 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
2036 rc
= InsertMenuA(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, "Submenu");
2037 ok (rc
, "Inserting the popup menu into the main menu failed\n");
2039 rc
= InsertMenuItemA(hmenuSub
, 0, TRUE
, &info
);
2040 ok (rc
, "Inserting the sub menu menuitem failed\n");
2042 memset( &info
, 0, sizeof info
);
2043 info
.cbSize
= sizeof info
;
2044 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
2045 info
.fType
= MFT_STRING
;
2046 info
.dwTypeData
= menuitem2
;
2047 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
2049 rc
= InsertMenuItemA(hmenuSub
, 1, TRUE
, &info
);
2050 ok (rc
, "Inserting the sub menu menuitem 2 failed\n");
2052 /* Prove that you can't query the id of a popup directly (By position) */
2053 id
= GetMenuItemID(hmenu
, 0);
2054 ok (id
== -1, "Getting the sub menu id should have failed because it's a popup (gave %x)\n", id
);
2056 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
2057 memset( &info
, 0, sizeof info
);
2059 info
.cbSize
= sizeof(MENUITEMINFOA
);
2060 info
.fMask
= MIIM_STRING
| MIIM_ID
;
2061 info
.dwTypeData
= strback
;
2062 info
.cch
= sizeof(strback
);
2064 rc
= GetMenuItemInfoA(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
);
2065 ok (rc
, "Getting the menus info failed\n");
2066 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for popup menu\n");
2067 ok (!strcmp(info
.dwTypeData
, "MenuItem"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
2068 DestroyMenu( hmenu
);
2069 DestroyMenu( hmenuSub
);
2072 Case 4: Menu containing 2 popup menus, the second
2073 contains 2 items with the same id as the first popup menu
2075 hmenu
= CreateMenu();
2076 hmenuSub
= CreateMenu();
2077 hmenuSub2
= CreateMenu();
2079 rc
= InsertMenuA(hmenu
, 0, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, "Submenu");
2080 ok (rc
, "Inserting the popup menu into the main menu failed\n");
2082 rc
= InsertMenuA(hmenu
, 1, MF_BYPOSITION
| MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub2
, "Submenu2");
2083 ok (rc
, "Inserting the popup menu into the main menu failed\n");
2085 memset( &info
, 0, sizeof info
);
2086 info
.cbSize
= sizeof info
;
2087 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
2088 info
.fType
= MFT_STRING
;
2089 info
.dwTypeData
= menuitem
;
2090 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
2092 rc
= InsertMenuItemA(hmenuSub2
, 0, TRUE
, &info
);
2093 ok (rc
, "Inserting the sub menu menuitem failed\n");
2095 memset( &info
, 0, sizeof info
);
2096 info
.cbSize
= sizeof info
;
2097 info
.fMask
= MIIM_FTYPE
| MIIM_STRING
| MIIM_ID
;
2098 info
.fType
= MFT_STRING
;
2099 info
.dwTypeData
= menuitem2
;
2100 info
.wID
= (UINT_PTR
) hmenuSub
; /* Enforce id collisions with the hmenu of the popup submenu*/
2102 rc
= InsertMenuItemA(hmenuSub2
, 1, TRUE
, &info
);
2103 ok (rc
, "Inserting the sub menu menuitem 2 failed\n");
2105 /* Prove getting the item info via ID returns the first item (not the popup or 2nd item)*/
2106 memset( &info
, 0, sizeof info
);
2108 info
.cbSize
= sizeof(MENUITEMINFOA
);
2109 info
.fMask
= MIIM_STRING
| MIIM_ID
;
2110 info
.dwTypeData
= strback
;
2111 info
.cch
= sizeof(strback
);
2113 rc
= GetMenuItemInfoA(hmenu
, (UINT_PTR
)hmenuSub
, FALSE
, &info
);
2114 ok (rc
, "Getting the menus info failed\n");
2115 ok (info
.wID
== (UINT_PTR
)hmenuSub
, "IDs differ for popup menu\n");
2116 ok (!strcmp(info
.dwTypeData
, "MenuItem"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
2118 memset( &info
, 0, sizeof info
);
2120 info
.cbSize
= sizeof(MENUITEMINFOA
);
2121 info
.fMask
= MIIM_STRING
| MIIM_ID
;
2122 info
.dwTypeData
= strback
;
2123 info
.cch
= sizeof(strback
);
2125 rc
= GetMenuItemInfoA(hmenu
, (UINT_PTR
)hmenuSub2
, FALSE
, &info
);
2126 ok (rc
, "Getting the menus info failed\n");
2127 ok (info
.wID
== (UINT_PTR
)hmenuSub2
, "IDs differ for popup menu\n");
2128 ok (!strcmp(info
.dwTypeData
, "Submenu2"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
2130 DestroyMenu( hmenu
);
2131 DestroyMenu( hmenuSub
);
2132 DestroyMenu( hmenuSub2
);
2136 Case 5: Menu containing a popup menu which in turn
2137 contains an item with a different id than the popup menu.
2138 This tests the fallback to a popup menu ID.
2141 hmenu
= CreateMenu();
2142 hmenuSub
= CreateMenu();
2144 rc
= AppendMenuA(hmenu
, MF_POPUP
| MF_STRING
, (UINT_PTR
)hmenuSub
, "Submenu");
2145 ok (rc
, "Appending the popup menu to the main menu failed\n");
2147 rc
= AppendMenuA(hmenuSub
, MF_STRING
, 102, "Item");
2148 ok (rc
, "Appending the item to the popup menu failed\n");
2150 /* Set the ID for hmenuSub */
2151 info
.cbSize
= sizeof(info
);
2152 info
.fMask
= MIIM_ID
;
2155 rc
= SetMenuItemInfoA(hmenu
, 0, TRUE
, &info
);
2156 ok(rc
, "Setting the ID for the popup menu failed\n");
2158 /* Check if the ID has been set */
2160 rc
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &info
);
2161 ok(rc
, "Getting the ID for the popup menu failed\n");
2162 ok(info
.wID
== 101, "The ID for the popup menu has not been set\n");
2164 /* Prove getting the item info via ID returns the popup menu */
2165 memset( &info
, 0, sizeof(info
));
2167 info
.cbSize
= sizeof(MENUITEMINFOA
);
2168 info
.fMask
= MIIM_STRING
| MIIM_ID
;
2169 info
.dwTypeData
= strback
;
2170 info
.cch
= sizeof(strback
);
2172 rc
= GetMenuItemInfoA(hmenu
, 101, FALSE
, &info
);
2173 ok (rc
, "Getting the menu info failed\n");
2174 ok (info
.wID
== 101, "IDs differ\n");
2175 ok (!strcmp(info
.dwTypeData
, "Submenu"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
2177 /* Also look for the menu item */
2178 memset( &info
, 0, sizeof(info
));
2180 info
.cbSize
= sizeof(MENUITEMINFOA
);
2181 info
.fMask
= MIIM_STRING
| MIIM_ID
;
2182 info
.dwTypeData
= strback
;
2183 info
.cch
= sizeof(strback
);
2185 rc
= GetMenuItemInfoA(hmenu
, 102, FALSE
, &info
);
2186 ok (rc
, "Getting the menu info failed\n");
2187 ok (info
.wID
== 102, "IDs differ\n");
2188 ok (!strcmp(info
.dwTypeData
, "Item"), "Returned item has wrong label (%s)\n", info
.dwTypeData
);
2191 DestroyMenu(hmenuSub
);
2194 struct menu_item_pair_s
{
2195 UINT uMenu
; /* 1 - top level menu, [0-Menu 1-Enabled 2-Disabled]
2196 * 2 - 2nd level menu, [0-Popup 1-Enabled 2-Disabled]
2197 * 3 - 3rd level menu, [0-Enabled 1-Disabled] */
2201 static struct menu_mouse_tests_s
{
2203 struct menu_item_pair_s menu_item_pairs
[5]; /* for mousing */
2204 WORD wVk
[5]; /* keys */
2208 /* for each test, send keys or clicks and check for menu visibility */
2209 { INPUT_KEYBOARD
, {{0}}, {VK_MENU
, 0}, TRUE
, FALSE
}, /* test 0 */
2210 { INPUT_KEYBOARD
, {{0}}, {VK_ESCAPE
, 0}, FALSE
, FALSE
},
2211 { INPUT_KEYBOARD
, {{0}}, {VK_MENU
, 0}, TRUE
, FALSE
},
2212 { INPUT_KEYBOARD
, {{0}}, {'D', 0}, FALSE
, FALSE
},
2213 { INPUT_KEYBOARD
, {{0}}, {VK_MENU
, 0}, TRUE
, FALSE
},
2214 { INPUT_KEYBOARD
, {{0}}, {'E', 0}, FALSE
, FALSE
},
2215 { INPUT_KEYBOARD
, {{0}}, {VK_MENU
, 'M', 0}, TRUE
, FALSE
},
2216 { INPUT_KEYBOARD
, {{0}}, {VK_ESCAPE
, VK_ESCAPE
, 0}, FALSE
, FALSE
},
2217 { INPUT_KEYBOARD
, {{0}}, {VK_MENU
, 'M', VK_ESCAPE
, 0}, TRUE
, FALSE
},
2218 { INPUT_KEYBOARD
, {{0}}, {VK_ESCAPE
, 0}, FALSE
, FALSE
},
2219 { INPUT_KEYBOARD
, {{0}}, {VK_MENU
, 'M', 0}, TRUE
, FALSE
},
2220 { INPUT_KEYBOARD
, {{0}}, {'D', 0}, FALSE
, FALSE
},
2221 { INPUT_KEYBOARD
, {{0}}, {VK_MENU
, 'M', 0}, TRUE
, FALSE
},
2222 { INPUT_KEYBOARD
, {{0}}, {'E', 0}, FALSE
, FALSE
},
2223 { INPUT_KEYBOARD
, {{0}}, {VK_MENU
, 'M', 'P', 0}, TRUE
, FALSE
},
2224 { INPUT_KEYBOARD
, {{0}}, {'D', 0}, FALSE
, FALSE
},
2225 { INPUT_KEYBOARD
, {{0}}, {VK_MENU
, 'M', 'P', 0}, TRUE
, FALSE
},
2226 { INPUT_KEYBOARD
, {{0}}, {'E', 0}, FALSE
, FALSE
},
2227 { INPUT_KEYBOARD
, {{0}}, {VK_F10
, 0}, TRUE
, FALSE
},
2228 { INPUT_KEYBOARD
, {{0}}, {VK_F10
, 0}, FALSE
, FALSE
},
2230 { INPUT_MOUSE
, {{1, 2}, {0}}, {0}, TRUE
, FALSE
}, /* test 20 */
2231 { INPUT_MOUSE
, {{1, 1}, {0}}, {0}, FALSE
, FALSE
},
2232 { INPUT_MOUSE
, {{1, 0}, {0}}, {0}, TRUE
, FALSE
},
2233 { INPUT_MOUSE
, {{1, 1}, {0}}, {0}, FALSE
, FALSE
},
2234 { INPUT_MOUSE
, {{1, 0}, {2, 2}, {0}}, {0}, TRUE
, FALSE
},
2235 { INPUT_MOUSE
, {{2, 1}, {0}}, {0}, FALSE
, FALSE
},
2236 { INPUT_MOUSE
, {{1, 0}, {2, 0}, {0}}, {0}, TRUE
, FALSE
},
2237 { INPUT_MOUSE
, {{3, 0}, {0}}, {0}, FALSE
, FALSE
},
2238 { INPUT_MOUSE
, {{1, 0}, {2, 0}, {0}}, {0}, TRUE
, FALSE
},
2239 { INPUT_MOUSE
, {{3, 1}, {0}}, {0}, TRUE
, FALSE
},
2240 { INPUT_MOUSE
, {{1, 1}, {0}}, {0}, FALSE
, FALSE
},
2244 static void send_key(WORD wVk
)
2247 memset(i
, 0, sizeof(i
));
2248 i
[0].type
= i
[1].type
= INPUT_KEYBOARD
;
2249 i
[0].u
.ki
.wVk
= i
[1].u
.ki
.wVk
= wVk
;
2250 i
[1].u
.ki
.dwFlags
= KEYEVENTF_KEYUP
;
2251 SendInput(2, (INPUT
*) i
, sizeof(INPUT
));
2254 static BOOL
click_menu(HANDLE hWnd
, struct menu_item_pair_s
*mi
)
2256 HMENU hMenu
= hMenus
[mi
->uMenu
];
2260 int screen_w
= GetSystemMetrics(SM_CXSCREEN
);
2261 int screen_h
= GetSystemMetrics(SM_CYSCREEN
);
2262 BOOL ret
= GetMenuItemRect(mi
->uMenu
> 2 ? NULL
: hWnd
, hMenu
, mi
->uItem
, &r
);
2263 if(!ret
) return FALSE
;
2265 memset(i
, 0, sizeof(i
));
2266 i
[0].type
= i
[1].type
= i
[2].type
= INPUT_MOUSE
;
2267 i
[0].u
.mi
.dx
= i
[1].u
.mi
.dx
= i
[2].u
.mi
.dx
2268 = ((r
.left
+ 5) * 65535) / screen_w
;
2269 i
[0].u
.mi
.dy
= i
[1].u
.mi
.dy
= i
[2].u
.mi
.dy
2270 = ((r
.top
+ 5) * 65535) / screen_h
;
2271 i
[0].u
.mi
.dwFlags
= i
[1].u
.mi
.dwFlags
= i
[2].u
.mi
.dwFlags
2272 = MOUSEEVENTF_ABSOLUTE
;
2273 i
[0].u
.mi
.dwFlags
|= MOUSEEVENTF_MOVE
;
2274 i
[1].u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTDOWN
;
2275 i
[2].u
.mi
.dwFlags
|= MOUSEEVENTF_LEFTUP
;
2276 ret
= SendInput(3, (INPUT
*) i
, sizeof(INPUT
));
2278 /* hack to prevent mouse message buildup in Wine */
2279 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
2283 static DWORD WINAPI
test_menu_input_thread(LPVOID lpParameter
)
2286 HANDLE hWnd
= lpParameter
;
2289 /* mixed keyboard/mouse test */
2290 for (i
= 0; menu_tests
[i
].type
!= -1; i
++)
2295 got_input
= i
&& menu_tests
[i
-1].bMenuVisible
;
2297 if (menu_tests
[i
].type
== INPUT_KEYBOARD
)
2298 for (j
= 0; menu_tests
[i
].wVk
[j
] != 0; j
++)
2299 send_key(menu_tests
[i
].wVk
[j
]);
2301 for (j
= 0; menu_tests
[i
].menu_item_pairs
[j
].uMenu
!= 0; j
++)
2303 /* Maybe clicking too fast before menu is initialized. Sleep 100 ms and retry */
2305 while (!(ret
= click_menu(hWnd
, &menu_tests
[i
].menu_item_pairs
[j
])))
2307 if (elapsed
> 1000) break;
2315 skip( "test %u: failed to send input\n", i
);
2316 PostMessageA( hWnd
, WM_CANCELMODE
, 0, 0 );
2321 while (menu_tests
[i
].bMenuVisible
!= bMenuVisible
)
2331 skip( "test %u: didn't receive input\n", i
);
2332 PostMessageA( hWnd
, WM_CANCELMODE
, 0, 0 );
2336 todo_wine_if (menu_tests
[i
]._todo_wine
)
2337 ok(menu_tests
[i
].bMenuVisible
== bMenuVisible
, "test %d\n", i
);
2342 static LRESULT CALLBACK
WndProc(HWND hWnd
, UINT msg
, WPARAM wParam
,
2351 case WM_ENTERMENULOOP
:
2352 bMenuVisible
= TRUE
;
2354 case WM_INITMENUPOPUP
:
2355 case WM_UNINITMENUPOPUP
:
2356 case WM_EXITMENULOOP
:
2363 case WM_LBUTTONDOWN
:
2365 case WM_NCMOUSEMOVE
:
2366 case WM_NCLBUTTONDOWN
:
2367 case WM_NCLBUTTONUP
:
2371 return( DefWindowProcA( hWnd
, msg
, wParam
, lParam
) );
2374 mbi
.cbSize
= sizeof(MENUBARINFO
);
2376 /* get info for the menu */
2377 br
= GetMenuBarInfo(hWnd
, OBJID_MENU
, 0, &mbi
);
2378 ok(br
, "msg %x: GetMenuBarInfo failed\n", msg
);
2379 hmenu
= GetMenu(hWnd
);
2380 ok(!mbi
.hwndMenu
, "msg %x: GetMenuBarInfo.hwndMenu wrong: %p expected NULL\n",
2382 ok(mbi
.hMenu
== hmenu
, "msg %x: GetMenuBarInfo got wrong menu: %p expected %p\n",
2383 msg
, mbi
.hMenu
, hmenu
);
2384 ok(!bMenuVisible
== !mbi
.fBarFocused
, "msg %x: GetMenuBarInfo.fBarFocused (%d) is wrong\n",
2385 msg
, mbi
.fBarFocused
!= 0);
2386 ok(!bMenuVisible
== !mbi
.fFocused
, "msg %x: GetMenuBarInfo.fFocused (%d) is wrong\n",
2387 msg
, mbi
.fFocused
!= 0);
2389 /* get info for the menu's first item */
2390 br
= GetMenuBarInfo(hWnd
, OBJID_MENU
, 1, &mbi
);
2391 ok(br
, "msg %x: GetMenuBarInfo failed\n", msg
);
2392 state
= GetMenuState(hmenu
, 0, MF_BYPOSITION
);
2393 /* Native returns handle to destroyed window */
2394 todo_wine_if (msg
==WM_UNINITMENUPOPUP
&& popmenu
==1)
2395 ok(!mbi
.hwndMenu
== !popmenu
,
2396 "msg %x: GetMenuBarInfo.hwndMenu wrong: %p expected %sNULL\n",
2397 msg
, mbi
.hwndMenu
, popmenu
? "not " : "");
2398 ok(mbi
.hMenu
== hmenu
, "msg %x: GetMenuBarInfo got wrong menu: %p expected %p\n",
2399 msg
, mbi
.hMenu
, hmenu
);
2400 ok(!bMenuVisible
== !mbi
.fBarFocused
, "nsg %x: GetMenuBarInfo.fBarFocused (%d) is wrong\n",
2401 msg
, mbi
.fBarFocused
!= 0);
2402 ok(!(bMenuVisible
&& (state
& MF_HILITE
)) == !mbi
.fFocused
,
2403 "msg %x: GetMenuBarInfo.fFocused (%d) is wrong\n", msg
, mbi
.fFocused
!= 0);
2405 if (msg
== WM_EXITMENULOOP
)
2406 bMenuVisible
= FALSE
;
2407 else if (msg
== WM_INITMENUPOPUP
)
2409 else if (msg
== WM_UNINITMENUPOPUP
)
2414 static void test_menu_input(void) {
2417 HINSTANCE hInstance
= GetModuleHandleA( NULL
);
2418 HANDLE hThread
, hWnd
;
2423 wclass
.lpszClassName
= "MenuTestClass";
2424 wclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
2425 wclass
.lpfnWndProc
= WndProc
;
2426 wclass
.hInstance
= hInstance
;
2427 wclass
.hIcon
= LoadIconA( 0, (LPCSTR
)IDI_APPLICATION
);
2428 wclass
.hCursor
= LoadCursorA( 0, (LPCSTR
)IDC_ARROW
);
2429 wclass
.hbrBackground
= (HBRUSH
)( COLOR_WINDOW
+ 1 );
2430 wclass
.lpszMenuName
= 0;
2431 wclass
.cbClsExtra
= 0;
2432 wclass
.cbWndExtra
= 0;
2433 aclass
= RegisterClassA( &wclass
);
2434 ok (aclass
, "MenuTest class not created\n");
2435 if (!aclass
) return;
2436 hWnd
= CreateWindowA( wclass
.lpszClassName
, "MenuTest",
2437 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, 0,
2438 400, 200, NULL
, NULL
, hInstance
, NULL
);
2439 ok (hWnd
!= NULL
, "MenuTest window not created\n");
2442 hMenus
[3] = CreatePopupMenu();
2443 AppendMenuA(hMenus
[3], MF_STRING
, 0, "&Enabled");
2444 AppendMenuA(hMenus
[3], MF_STRING
|MF_DISABLED
, 0, "&Disabled");
2446 hMenus
[2] = CreatePopupMenu();
2447 AppendMenuA(hMenus
[2], MF_STRING
|MF_POPUP
, (UINT_PTR
) hMenus
[3], "&Popup");
2448 AppendMenuA(hMenus
[2], MF_STRING
, 0, "&Enabled");
2449 AppendMenuA(hMenus
[2], MF_STRING
|MF_DISABLED
, 0, "&Disabled");
2451 hMenus
[1] = CreateMenu();
2452 AppendMenuA(hMenus
[1], MF_STRING
|MF_POPUP
, (UINT_PTR
) hMenus
[2], "&Menu");
2453 AppendMenuA(hMenus
[1], MF_STRING
, 0, "&Enabled");
2454 AppendMenuA(hMenus
[1], MF_STRING
|MF_DISABLED
, 0, "&Disabled");
2456 SetMenu(hWnd
, hMenus
[1]);
2457 ShowWindow(hWnd
, SW_SHOW
);
2460 GetCursorPos(&orig_pos
);
2462 hThread
= CreateThread(NULL
, 0, test_menu_input_thread
, hWnd
, 0, &tid
);
2465 if (WAIT_TIMEOUT
!= WaitForSingleObject(hThread
, 50))
2467 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA(&msg
);
2469 SetCursorPos(orig_pos
.x
, orig_pos
.y
);
2470 DestroyWindow(hWnd
);
2473 static void test_menu_flags( void )
2475 HMENU hMenu
, hPopupMenu
;
2477 hMenu
= CreateMenu();
2478 hPopupMenu
= CreatePopupMenu();
2480 AppendMenuA(hMenu
, MF_POPUP
| MF_STRING
, (UINT_PTR
)hPopupMenu
, "Popup");
2482 AppendMenuA(hPopupMenu
, MF_STRING
| MF_HILITE
| MF_DEFAULT
, 101, "Item 1");
2483 InsertMenuA(hPopupMenu
, 1, MF_BYPOSITION
| MF_STRING
| MF_HILITE
| MF_DEFAULT
, 102, "Item 2");
2484 AppendMenuA(hPopupMenu
, MF_STRING
, 103, "Item 3");
2485 ModifyMenuA(hPopupMenu
, 2, MF_BYPOSITION
| MF_STRING
| MF_HILITE
| MF_DEFAULT
, 103, "Item 3");
2487 ok(GetMenuState(hPopupMenu
, 0, MF_BYPOSITION
) & MF_HILITE
,
2488 "AppendMenu should accept MF_HILITE\n");
2489 ok(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_HILITE
,
2490 "InsertMenu should accept MF_HILITE\n");
2491 ok(GetMenuState(hPopupMenu
, 2, MF_BYPOSITION
) & MF_HILITE
,
2492 "ModifyMenu should accept MF_HILITE\n");
2494 ok(!(GetMenuState(hPopupMenu
, 0, MF_BYPOSITION
) & MF_DEFAULT
),
2495 "AppendMenu must not accept MF_DEFAULT\n");
2496 ok(!(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_DEFAULT
),
2497 "InsertMenu must not accept MF_DEFAULT\n");
2498 ok(!(GetMenuState(hPopupMenu
, 2, MF_BYPOSITION
) & MF_DEFAULT
),
2499 "ModifyMenu must not accept MF_DEFAULT\n");
2504 static void test_menu_hilitemenuitem( void )
2506 HMENU hMenu
, hPopupMenu
;
2511 wclass
.lpszClassName
= "HiliteMenuTestClass";
2512 wclass
.style
= CS_HREDRAW
| CS_VREDRAW
;
2513 wclass
.lpfnWndProc
= WndProc
;
2514 wclass
.hInstance
= GetModuleHandleA( NULL
);
2515 wclass
.hIcon
= LoadIconA( 0, (LPCSTR
)IDI_APPLICATION
);
2516 wclass
.hCursor
= LoadCursorA( 0, (LPCSTR
)IDC_ARROW
);
2517 wclass
.hbrBackground
= (HBRUSH
)( COLOR_WINDOW
+ 1 );
2518 wclass
.lpszMenuName
= 0;
2519 wclass
.cbClsExtra
= 0;
2520 wclass
.cbWndExtra
= 0;
2521 aclass
= RegisterClassA( &wclass
);
2522 ok (aclass
, "HiliteMenuTest class could not be created\n");
2523 if (!aclass
) return;
2524 hWnd
= CreateWindowA( wclass
.lpszClassName
, "HiliteMenuTest",
2525 WS_OVERLAPPEDWINDOW
, CW_USEDEFAULT
, 0,
2526 400, 200, NULL
, NULL
, wclass
.hInstance
, NULL
);
2527 ok (hWnd
!= NULL
, "HiliteMenuTest window could not be created\n");
2530 hMenu
= CreateMenu();
2531 hPopupMenu
= CreatePopupMenu();
2533 AppendMenuA(hMenu
, MF_POPUP
| MF_STRING
, (UINT_PTR
)hPopupMenu
, "Popup");
2535 AppendMenuA(hPopupMenu
, MF_STRING
, 101, "Item 1");
2536 AppendMenuA(hPopupMenu
, MF_STRING
, 102, "Item 2");
2537 AppendMenuA(hPopupMenu
, MF_STRING
, 103, "Item 3");
2539 SetMenu(hWnd
, hMenu
);
2541 /* test invalid arguments */
2543 ok(!(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_HILITE
),
2544 "HiliteMenuItem: Item 2 is hilited\n");
2546 SetLastError(0xdeadbeef);
2549 ok(!HiliteMenuItem(NULL
, hPopupMenu
, 1, MF_HILITE
| MF_BYPOSITION
),
2550 "HiliteMenuItem: call should have failed.\n");
2552 ok(GetLastError() == 0xdeadbeef || /* 9x */
2553 GetLastError() == ERROR_INVALID_WINDOW_HANDLE
/* NT */,
2554 "HiliteMenuItem: expected error ERROR_INVALID_WINDOW_HANDLE, got: %d\n", GetLastError());
2556 SetLastError(0xdeadbeef);
2557 ok(!HiliteMenuItem(hWnd
, NULL
, 1, MF_HILITE
| MF_BYPOSITION
),
2558 "HiliteMenuItem: call should have failed.\n");
2559 ok(GetLastError() == 0xdeadbeef || /* 9x */
2560 GetLastError() == ERROR_INVALID_MENU_HANDLE
/* NT */,
2561 "HiliteMenuItem: expected error ERROR_INVALID_MENU_HANDLE, got: %d\n", GetLastError());
2563 ok(!(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_HILITE
),
2564 "HiliteMenuItem: Item 2 is hilited\n");
2566 /* either MF_HILITE or MF_UNHILITE *and* MF_BYCOMMAND or MF_BYPOSITION need to be set */
2568 SetLastError(0xdeadbeef);
2569 ok(HiliteMenuItem(hWnd
, hPopupMenu
, 1, MF_BYPOSITION
),
2570 "HiliteMenuItem: call should have succeeded.\n");
2571 ok(GetLastError() == 0xdeadbeef,
2572 "HiliteMenuItem: expected error 0xdeadbeef, got: %d\n", GetLastError());
2574 ok(!(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_HILITE
),
2575 "HiliteMenuItem: Item 2 is hilited\n");
2577 SetLastError(0xdeadbeef);
2580 ok(HiliteMenuItem(hWnd
, hPopupMenu
, 1, MF_HILITE
),
2581 "HiliteMenuItem: call should have succeeded.\n");
2583 ok(GetLastError() == 0xdeadbeef,
2584 "HiliteMenuItem: expected error 0xdeadbeef, got: %d\n", GetLastError());
2586 ok(!(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_HILITE
),
2587 "HiliteMenuItem: Item 2 is hilited\n");
2589 /* hilite a menu item (by position) */
2591 SetLastError(0xdeadbeef);
2592 ok(HiliteMenuItem(hWnd
, hPopupMenu
, 1, MF_HILITE
| MF_BYPOSITION
),
2593 "HiliteMenuItem: call should not have failed.\n");
2594 ok(GetLastError() == 0xdeadbeef,
2595 "HiliteMenuItem: expected error 0xdeadbeef, got: %d\n", GetLastError());
2599 ok(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_HILITE
,
2600 "HiliteMenuItem: Item 2 is not hilited\n");
2603 /* unhilite a menu item (by position) */
2605 SetLastError(0xdeadbeef);
2606 ok(HiliteMenuItem(hWnd
, hPopupMenu
, 1, MF_UNHILITE
| MF_BYPOSITION
),
2607 "HiliteMenuItem: call should not have failed.\n");
2608 ok(GetLastError() == 0xdeadbeef,
2609 "HiliteMenuItem: expected error 0xdeadbeef, got: %d\n", GetLastError());
2611 ok(!(GetMenuState(hPopupMenu
, 1, MF_BYPOSITION
) & MF_HILITE
),
2612 "HiliteMenuItem: Item 2 is hilited\n");
2614 /* hilite a menu item (by command) */
2616 SetLastError(0xdeadbeef);
2617 ok(HiliteMenuItem(hWnd
, hPopupMenu
, 103, MF_HILITE
| MF_BYCOMMAND
),
2618 "HiliteMenuItem: call should not have failed.\n");
2619 ok(GetLastError() == 0xdeadbeef,
2620 "HiliteMenuItem: expected error 0xdeadbeef, got: %d\n", GetLastError());
2624 ok(GetMenuState(hPopupMenu
, 2, MF_BYPOSITION
) & MF_HILITE
,
2625 "HiliteMenuItem: Item 3 is not hilited\n");
2628 /* unhilite a menu item (by command) */
2630 SetLastError(0xdeadbeef);
2631 ok(HiliteMenuItem(hWnd
, hPopupMenu
, 103, MF_UNHILITE
| MF_BYCOMMAND
),
2632 "HiliteMenuItem: call should not have failed.\n");
2633 ok(GetLastError() == 0xdeadbeef,
2634 "HiliteMenuItem: expected error 0xdeadbeef, got: %d\n", GetLastError());
2636 ok(!(GetMenuState(hPopupMenu
, 2, MF_BYPOSITION
) & MF_HILITE
),
2637 "HiliteMenuItem: Item 3 is hilited\n");
2639 DestroyWindow(hWnd
);
2642 static void check_menu_items(HMENU hmenu
, UINT checked_cmd
, UINT checked_type
,
2647 count
= GetMenuItemCount(hmenu
);
2648 ok (count
!= -1, "GetMenuItemCount returned -1\n");
2650 for (i
= 0; i
< count
; i
++)
2655 memset(&mii
, 0, sizeof(mii
));
2656 mii
.cbSize
= sizeof(mii
);
2657 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
| MIIM_SUBMENU
;
2658 ret
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
2659 ok(ret
, "GetMenuItemInfo(%u) failed\n", i
);
2661 if (winetest_debug
> 1)
2662 trace("item #%u: fType %04x, fState %04x, wID %u, hSubMenu %p\n",
2663 i
, mii
.fType
, mii
.fState
, mii
.wID
, mii
.hSubMenu
);
2667 ok(mii
.wID
== (UINT_PTR
)mii
.hSubMenu
, "id %u: wID %x should be equal to hSubMenu %p\n",
2668 checked_cmd
, mii
.wID
, mii
.hSubMenu
);
2669 if (!GetMenuItemCount(mii
.hSubMenu
))
2671 ok(mii
.fType
== checked_type
, "id %u: expected fType %04x, got %04x\n", checked_cmd
, checked_type
, mii
.fType
);
2672 ok(mii
.fState
== checked_state
, "id %u: expected fState %04x, got %04x\n", checked_cmd
, checked_state
, mii
.fState
);
2674 check_menu_items(mii
.hSubMenu
, checked_cmd
, checked_type
, checked_state
);
2678 if (mii
.wID
== checked_cmd
)
2680 ok(mii
.fType
== checked_type
, "id %u: expected fType %04x, got %04x\n", checked_cmd
, checked_type
, mii
.fType
);
2681 ok(mii
.fState
== checked_state
, "id %u: expected fState %04x, got %04x\n", checked_cmd
, checked_state
, mii
.fState
);
2682 ok(mii
.wID
!= 0, "id %u: not expected wID 0\n", checked_cmd
);
2686 ok(mii
.fType
!= MFT_RADIOCHECK
, "id %u: not expected fType MFT_RADIOCHECK on cmd %u\n", checked_cmd
, mii
.wID
);
2688 if (mii
.fType
== MFT_SEPARATOR
)
2690 ok(mii
.fState
== MFS_GRAYED
, "id %u: expected fState MFS_GRAYED, got %04x\n", checked_cmd
, mii
.fState
);
2691 ok(mii
.wID
== 0, "id %u: expected wID 0, got %u\n", checked_cmd
, mii
.wID
);
2695 ok(mii
.fState
== 0, "id %u: expected fState 0, got %04x\n", checked_cmd
, mii
.fState
);
2696 ok(mii
.wID
!= 0, "id %u: not expected wID 0\n", checked_cmd
);
2703 static void clear_ftype_and_state(HMENU hmenu
, UINT id
, UINT flags
)
2708 memset(&mii
, 0, sizeof(mii
));
2709 mii
.cbSize
= sizeof(mii
);
2710 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
;
2711 ret
= SetMenuItemInfoA(hmenu
, id
, (flags
& MF_BYPOSITION
) != 0, &mii
);
2712 ok(ret
, "SetMenuItemInfo(%u) failed\n", id
);
2715 static void test_CheckMenuRadioItem(void)
2720 hmenu
= LoadMenuA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(1));
2723 check_menu_items(hmenu
, -1, 0, 0);
2725 ret
= CheckMenuRadioItem(hmenu
, 100, 100, 100, MF_BYCOMMAND
);
2726 ok(ret
, "CheckMenuRadioItem failed\n");
2727 check_menu_items(hmenu
, 100, MFT_RADIOCHECK
, MFS_CHECKED
);
2729 /* MSDN is wrong, Windows does not remove MFT_RADIOCHECK */
2730 ret
= CheckMenuRadioItem(hmenu
, 100, 100, -1, MF_BYCOMMAND
);
2731 ok(!ret
, "CheckMenuRadioItem should return FALSE\n");
2732 check_menu_items(hmenu
, 100, MFT_RADIOCHECK
, 0);
2735 clear_ftype_and_state(hmenu
, 100, MF_BYCOMMAND
);
2736 check_menu_items(hmenu
, -1, 0, 0);
2738 /* first and checked items are on different menus */
2739 ret
= CheckMenuRadioItem(hmenu
, 0, 300, 202, MF_BYCOMMAND
);
2740 ok(!ret
, "CheckMenuRadioItem should return FALSE\n");
2741 check_menu_items(hmenu
, -1, 0, 0);
2743 ret
= CheckMenuRadioItem(hmenu
, 200, 300, 202, MF_BYCOMMAND
);
2744 ok(ret
, "CheckMenuRadioItem failed\n");
2745 check_menu_items(hmenu
, 202, MFT_RADIOCHECK
, MFS_CHECKED
);
2747 /* MSDN is wrong, Windows does not remove MFT_RADIOCHECK */
2748 ret
= CheckMenuRadioItem(hmenu
, 202, 202, -1, MF_BYCOMMAND
);
2749 ok(!ret
, "CheckMenuRadioItem should return FALSE\n");
2750 check_menu_items(hmenu
, 202, MFT_RADIOCHECK
, 0);
2753 clear_ftype_and_state(hmenu
, 202, MF_BYCOMMAND
);
2754 check_menu_items(hmenu
, -1, 0, 0);
2756 /* just for fun, try to check separator */
2757 ret
= CheckMenuRadioItem(hmenu
, 0, 300, 0, MF_BYCOMMAND
);
2758 ok(!ret
, "CheckMenuRadioItem should return FALSE\n");
2759 check_menu_items(hmenu
, -1, 0, 0);
2762 static void test_menu_resource_layout(void)
2766 MENUITEMTEMPLATEHEADER mith
;
2770 { 0, 0 }, /* versionNumber, offset */
2772 /* mtOption, mtID, mtString[] '\0' terminated */
2773 MF_STRING
, 1, 'F', 0,
2776 /* MF_SEPARATOR, 4, 'S', 0, FIXME: Wine ignores 'S' */
2777 MF_STRING
|MF_GRAYED
|MF_END
, 5, 'E', 0
2782 UINT type
, state
, id
;
2786 { MF_STRING
, MF_ENABLED
, 1, "F" },
2787 { MF_SEPARATOR
, MF_GRAYED
|MF_DISABLED
, 2, "" },
2788 { MF_SEPARATOR
, MF_GRAYED
|MF_DISABLED
, 3, "" },
2789 /*{ MF_SEPARATOR, MF_GRAYED|MF_DISABLED, 4, "S" }, FIXME: Wine ignores 'S'*/
2790 { MF_STRING
, MF_GRAYED
, 5, "E" },
2791 { MF_SEPARATOR
, MF_GRAYED
|MF_DISABLED
, 6, "" },
2792 { MF_STRING
, MF_ENABLED
, 7, "" },
2793 { MF_SEPARATOR
, MF_GRAYED
|MF_DISABLED
, 8, "" }
2799 hmenu
= LoadMenuIndirectA(&menu_template
);
2800 ok(hmenu
!= 0, "LoadMenuIndirect error %u\n", GetLastError());
2802 ret
= AppendMenuA(hmenu
, MF_STRING
, 6, NULL
);
2803 ok(ret
, "AppendMenu failed\n");
2804 ret
= AppendMenuA(hmenu
, MF_STRING
, 7, "\0");
2805 ok(ret
, "AppendMenu failed\n");
2806 ret
= AppendMenuA(hmenu
, MF_SEPARATOR
, 8, "separator");
2807 ok(ret
, "AppendMenu failed\n");
2809 count
= GetMenuItemCount(hmenu
);
2810 ok(count
== ARRAY_SIZE(menu_data
), "expected %u menu items, got %u\n",
2811 (UINT
) ARRAY_SIZE(menu_data
), count
);
2813 for (i
= 0; i
< count
; i
++)
2818 memset(&mii
, 0, sizeof(mii
));
2819 mii
.cbSize
= sizeof(mii
);
2820 mii
.dwTypeData
= buf
;
2821 mii
.cch
= sizeof(buf
);
2822 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
| MIIM_STRING
;
2823 ret
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
2824 ok(ret
, "GetMenuItemInfo(%u) failed\n", i
);
2825 if (winetest_debug
> 1)
2826 trace("item #%u: fType %04x, fState %04x, wID %u, dwTypeData %s\n",
2827 i
, mii
.fType
, mii
.fState
, mii
.wID
, (LPCSTR
)mii
.dwTypeData
);
2829 ok(mii
.fType
== menu_data
[i
].type
,
2830 "%u: expected fType %04x, got %04x\n", i
, menu_data
[i
].type
, mii
.fType
);
2831 ok(mii
.fState
== menu_data
[i
].state
,
2832 "%u: expected fState %04x, got %04x\n", i
, menu_data
[i
].state
, mii
.fState
);
2833 ok(mii
.wID
== menu_data
[i
].id
,
2834 "%u: expected wID %04x, got %04x\n", i
, menu_data
[i
].id
, mii
.wID
);
2835 ok(mii
.cch
== strlen(menu_data
[i
].str
),
2836 "%u: expected cch %u, got %u\n", i
, (UINT
)strlen(menu_data
[i
].str
), mii
.cch
);
2837 ok(!strcmp(mii
.dwTypeData
, menu_data
[i
].str
),
2838 "%u: expected dwTypeData %s, got %s\n", i
, menu_data
[i
].str
, (LPCSTR
)mii
.dwTypeData
);
2850 static HMENU
create_menu_from_data(const struct menu_data
*item
, INT item_count
)
2856 hmenu
= CreateMenu();
2859 for (i
= 0; i
< item_count
; i
++)
2861 SetLastError(0xdeadbeef);
2862 ret
= AppendMenuA(hmenu
, item
[i
].type
, item
[i
].id
, item
[i
].str
);
2863 ok(ret
, "%d: AppendMenu(%04x, %04x, %p) error %u\n",
2864 i
, item
[i
].type
, item
[i
].id
, item
[i
].str
, GetLastError());
2869 /* use InsertMenuItem: does not set the MFT_BITMAP flag,
2870 * and does not accept non-magic bitmaps with invalid
2872 static HMENU
create_menuitem_from_data(const struct menu_data
*item
, INT item_count
)
2877 MENUITEMINFOA mii
= { sizeof( MENUITEMINFOA
) };
2879 hmenu
= CreateMenu();
2882 for (i
= 0; i
< item_count
; i
++)
2884 SetLastError(0xdeadbeef);
2886 mii
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STATE
;
2888 if( item
[i
].type
& MFT_BITMAP
)
2890 mii
.fMask
|= MIIM_BITMAP
;
2891 mii
.hbmpItem
= (HBITMAP
)item
[i
].str
;
2893 else if( item
[i
].type
& MFT_SEPARATOR
)
2894 mii
.fType
= MFT_SEPARATOR
;
2897 mii
.fMask
|= MIIM_STRING
;
2898 mii
.dwTypeData
= (LPSTR
)item
[i
].str
;
2899 mii
.cch
= strlen( item
[i
].str
);
2902 if( item
[i
].type
& MF_HELP
) mii
.fType
|= MF_HELP
;
2903 mii
.wID
= item
[i
].id
;
2904 ret
= InsertMenuItemA( hmenu
, -1, TRUE
, &mii
);
2905 ok(ret
, "%d: InsertMenuItem(%04x, %04x, %p) error %u\n",
2906 i
, item
[i
].type
, item
[i
].id
, item
[i
].str
, GetLastError());
2911 static void compare_menu_data(HMENU hmenu
, const struct menu_data
*item
, INT item_count
)
2916 count
= GetMenuItemCount(hmenu
);
2917 ok(count
== item_count
, "expected %d, got %d menu items\n", count
, item_count
);
2919 for (i
= 0; i
< count
; i
++)
2924 memset(&mii
, 0, sizeof(mii
));
2925 mii
.cbSize
= sizeof(mii
);
2926 mii
.dwTypeData
= buf
;
2927 mii
.cch
= sizeof(buf
);
2928 mii
.fMask
= MIIM_FTYPE
| MIIM_ID
| MIIM_STRING
| MIIM_BITMAP
;
2929 ret
= GetMenuItemInfoA(hmenu
, i
, TRUE
, &mii
);
2930 ok(ret
, "GetMenuItemInfo(%u) failed\n", i
);
2932 if (winetest_debug
> 1)
2933 trace("item #%u: fType %04x, fState %04x, wID %04x, hbmp %p\n",
2934 i
, mii
.fType
, mii
.fState
, mii
.wID
, mii
.hbmpItem
);
2936 ok(mii
.fType
== item
[i
].type
,
2937 "%u: expected fType %04x, got %04x\n", i
, item
[i
].type
, mii
.fType
);
2938 ok(mii
.wID
== item
[i
].id
,
2939 "%u: expected wID %04x, got %04x\n", i
, item
[i
].id
, mii
.wID
);
2940 if (mii
.hbmpItem
|| !item
[i
].str
)
2941 /* For some reason Windows sets high word to not 0 for
2944 ok(LOWORD(mii
.hbmpItem
) == LOWORD(item
[i
].str
),
2945 "%u: expected hbmpItem %p, got %p\n", i
, item
[i
].str
, mii
.hbmpItem
);
2948 ok(mii
.cch
== strlen(item
[i
].str
),
2949 "%u: expected cch %u, got %u\n", i
, (UINT
)strlen(item
[i
].str
), mii
.cch
);
2950 ok(!strcmp(mii
.dwTypeData
, item
[i
].str
),
2951 "%u: expected dwTypeData %s, got %s\n", i
, item
[i
].str
, (LPCSTR
)mii
.dwTypeData
);
2956 static void test_InsertMenu(void)
2958 HBITMAP hbm
= CreateBitmap(1,1,1,1,NULL
);
2959 /* Note: XP treats only bitmap handles 1 - 6 as "magic" ones
2960 * regardless of their id.
2962 static const struct menu_data in1
[] =
2964 { MF_STRING
, 1, "File" },
2965 { MF_BITMAP
|MF_HELP
, SC_CLOSE
, MAKEINTRESOURCEA(1) },
2966 { MF_STRING
|MF_HELP
, 2, "Help" }
2968 static const struct menu_data out1
[] =
2970 { MF_STRING
, 1, "File" },
2971 { MF_STRING
|MF_HELP
, 2, "Help" },
2972 { MF_BITMAP
|MF_HELP
, SC_CLOSE
, MAKEINTRESOURCEA(1) }
2974 static const struct menu_data out1a
[] =
2976 { MF_STRING
, 1, "File" },
2977 { MF_STRING
|MF_HELP
, 2, "Help" },
2978 { MF_HELP
, SC_CLOSE
, MAKEINTRESOURCEA(1) }
2980 const struct menu_data in2
[] =
2982 { MF_STRING
, 1, "File" },
2983 { MF_BITMAP
|MF_HELP
, SC_CLOSE
, (char*)hbm
},
2984 { MF_STRING
|MF_HELP
, 2, "Help" }
2986 const struct menu_data out2
[] =
2988 { MF_STRING
, 1, "File" },
2989 { MF_BITMAP
|MF_HELP
, SC_CLOSE
, (char*)hbm
},
2990 { MF_STRING
|MF_HELP
, 2, "Help" }
2992 const struct menu_data out2a
[] =
2994 { MF_STRING
, 1, "File" },
2995 { MF_HELP
, SC_CLOSE
, (char*)hbm
},
2996 { MF_STRING
|MF_HELP
, 2, "Help" }
2998 static const struct menu_data in3
[] =
3000 { MF_STRING
, 1, "File" },
3001 { MF_SEPARATOR
|MF_HELP
, SC_CLOSE
, MAKEINTRESOURCEA(1) },
3002 { MF_STRING
|MF_HELP
, 2, "Help" }
3004 static const struct menu_data out3
[] =
3006 { MF_STRING
, 1, "File" },
3007 { MF_SEPARATOR
|MF_HELP
, SC_CLOSE
, MAKEINTRESOURCEA(0) },
3008 { MF_STRING
|MF_HELP
, 2, "Help" },
3010 static const struct menu_data in4
[] =
3012 { MF_STRING
, 1, "File" },
3013 { MF_BITMAP
|MF_HELP
, 1, MAKEINTRESOURCEA(1) },
3014 { MF_STRING
|MF_HELP
, 2, "Help" }
3016 static const struct menu_data out4
[] =
3018 { MF_STRING
, 1, "File" },
3019 { MF_STRING
|MF_HELP
, 2, "Help" },
3020 { MF_BITMAP
|MF_HELP
, 1, MAKEINTRESOURCEA(1) }
3022 static const struct menu_data out4a
[] =
3024 { MF_STRING
, 1, "File" },
3025 { MF_STRING
|MF_HELP
, 2, "Help" },
3026 { MF_HELP
, 1, MAKEINTRESOURCEA(1) }
3030 #define create_menu(a) create_menu_from_data((a), ARRAY_SIZE(a))
3031 #define create_menuitem(a) create_menuitem_from_data((a), ARRAY_SIZE(a))
3032 #define compare_menu(h, a) compare_menu_data((h), (a), ARRAY_SIZE(a))
3034 hmenu
= create_menu(in1
);
3035 compare_menu(hmenu
, out1
);
3038 hmenu
= create_menu(in2
);
3039 compare_menu(hmenu
, out2
);
3042 hmenu
= create_menu(in3
);
3043 compare_menu(hmenu
, out3
);
3046 hmenu
= create_menu(in4
);
3047 compare_menu(hmenu
, out4
);
3050 /* now using InsertMenuItemInfo */
3051 hmenu
= create_menuitem(in1
);
3052 compare_menu(hmenu
, out1a
);
3055 hmenu
= create_menuitem(in2
);
3056 compare_menu(hmenu
, out2a
);
3059 hmenu
= create_menuitem(in3
);
3060 compare_menu(hmenu
, out3
);
3063 hmenu
= create_menuitem(in4
);
3064 compare_menu(hmenu
, out4a
);
3068 #undef create_menuitem
3072 static void test_menu_getmenuinfo(void)
3080 hmenu
= CreateMenu();
3082 /* test some parameter errors */
3083 SetLastError(0xdeadbeef);
3084 ret
= GetMenuInfo( hmenu
, NULL
);
3085 gle
= GetLastError();
3086 ok( !ret
, "GetMenuInfo() should have failed\n");
3087 ok( gle
== ERROR_INVALID_PARAMETER
||
3088 broken(gle
== 0xdeadbeef), /* Win98, WinME */
3089 "GetMenuInfo() error got %u expected %u\n", gle
, ERROR_INVALID_PARAMETER
);
3090 SetLastError(0xdeadbeef);
3092 ret
= GetMenuInfo( hmenu
, &mi
);
3093 gle
= GetLastError();
3094 ok( !ret
, "GetMenuInfo() should have failed\n");
3095 ok( gle
== ERROR_INVALID_PARAMETER
||
3096 broken(gle
== 0xdeadbeef), /* Win98, WinME */
3097 "GetMenuInfo() error got %u expected %u\n", gle
, ERROR_INVALID_PARAMETER
);
3098 SetLastError(0xdeadbeef);
3099 mi
.cbSize
= sizeof( MENUINFO
);
3100 ret
= GetMenuInfo( hmenu
, &mi
);
3101 gle
= GetLastError();
3102 ok( ret
, "GetMenuInfo() should have succeeded\n");
3103 ok( gle
== 0xdeadbeef, "GetMenuInfo() error got %u\n", gle
);
3104 SetLastError(0xdeadbeef);
3106 ret
= GetMenuInfo( NULL
, &mi
);
3107 gle
= GetLastError();
3108 ok( !ret
, "GetMenuInfo() should have failed\n");
3109 ok( gle
== ERROR_INVALID_PARAMETER
||
3110 broken(gle
== 0xdeadbeef), /* Win98, WinME */
3111 "GetMenuInfo() error got %u expected %u\n", gle
, ERROR_INVALID_PARAMETER
);
3113 DestroyMenu( hmenu
);
3117 static void test_menu_setmenuinfo(void)
3119 HMENU hmenu
, hsubmenu
;
3121 MENUITEMINFOA mii
= { sizeof(MENUITEMINFOA
) };
3126 /* create a menu with a submenu */
3127 hmenu
= CreateMenu();
3128 hsubmenu
= CreateMenu();
3129 assert( hmenu
&& hsubmenu
);
3130 mii
.fMask
= MIIM_SUBMENU
;
3131 mii
.hSubMenu
= hsubmenu
;
3132 ret
= InsertMenuItemA( hmenu
, 0, FALSE
, &mii
);
3133 ok( ret
, "InsertMenuItem failed with error %d\n", GetLastError());
3134 /* test some parameter errors */
3135 SetLastError(0xdeadbeef);
3136 ret
= SetMenuInfo( hmenu
, NULL
);
3137 gle
= GetLastError();
3138 ok( !ret
, "SetMenuInfo() should have failed\n");
3139 ok( gle
== ERROR_INVALID_PARAMETER
||
3140 broken(gle
== 0xdeadbeef), /* Win98, WinME */
3141 "SetMenuInfo() error got %u expected %u\n", gle
, ERROR_INVALID_PARAMETER
);
3142 SetLastError(0xdeadbeef);
3144 ret
= SetMenuInfo( hmenu
, &mi
);
3145 gle
= GetLastError();
3146 ok( !ret
, "SetMenuInfo() should have failed\n");
3147 ok( gle
== ERROR_INVALID_PARAMETER
||
3148 broken(gle
== 0xdeadbeef), /* Win98, WinME */
3149 "SetMenuInfo() error got %u expected %u\n", gle
, ERROR_INVALID_PARAMETER
);
3150 SetLastError(0xdeadbeef);
3151 mi
.cbSize
= sizeof( MENUINFO
);
3152 ret
= SetMenuInfo( hmenu
, &mi
);
3153 gle
= GetLastError();
3154 ok( ret
, "SetMenuInfo() should have succeeded\n");
3155 ok( gle
== 0xdeadbeef, "SetMenuInfo() error got %u\n", gle
);
3156 SetLastError(0xdeadbeef);
3158 ret
= SetMenuInfo( NULL
, &mi
);
3159 gle
= GetLastError();
3160 ok( !ret
, "SetMenuInfo() should have failed\n");
3161 ok( gle
== ERROR_INVALID_PARAMETER
||
3162 broken(gle
== 0xdeadbeef), /* Win98, WinME */
3163 "SetMenuInfo() error got %u expected %u\n", gle
, ERROR_INVALID_PARAMETER
);
3164 /* functional tests */
3165 /* menu and submenu should have the CHECKORBMP style bit cleared */
3166 SetLastError(0xdeadbeef);
3167 mi
.cbSize
= sizeof( MENUINFO
);
3168 mi
.fMask
= MIM_STYLE
;
3169 ret
= GetMenuInfo( hmenu
, &mi
);
3170 gle
= GetLastError();
3171 ok( ret
, "GetMenuInfo() should have succeeded\n");
3172 ok( gle
== 0xdeadbeef, "GetMenuInfo() error got %u\n", gle
);
3173 ok( !(mi
.dwStyle
& MNS_CHECKORBMP
), "menustyle was not expected to have the MNS_CHECKORBMP flag\n");
3174 SetLastError(0xdeadbeef);
3175 mi
.cbSize
= sizeof( MENUINFO
);
3176 mi
.fMask
= MIM_STYLE
;
3177 ret
= GetMenuInfo( hsubmenu
, &mi
);
3178 gle
= GetLastError();
3179 ok( ret
, "GetMenuInfo() should have succeeded\n");
3180 ok( gle
== 0xdeadbeef, "GetMenuInfo() error got %u\n", gle
);
3181 ok( !(mi
.dwStyle
& MNS_CHECKORBMP
), "menustyle was not expected to have the MNS_CHECKORBMP flag\n");
3183 SetLastError(0xdeadbeef);
3184 mi
.cbSize
= sizeof( MENUINFO
);
3185 mi
.fMask
= MIM_STYLE
| MIM_APPLYTOSUBMENUS
;
3186 mi
.dwStyle
= MNS_CHECKORBMP
;
3187 ret
= SetMenuInfo( hmenu
, &mi
);
3188 gle
= GetLastError();
3189 ok( ret
, "SetMenuInfo() should have succeeded\n");
3190 ok( gle
== 0xdeadbeef, "SetMenuInfo() error got %u\n", gle
);
3191 /* Now both menus should have the MNS_CHECKORBMP style bit set */
3192 SetLastError(0xdeadbeef);
3193 mi
.cbSize
= sizeof( MENUINFO
);
3194 mi
.fMask
= MIM_STYLE
;
3195 ret
= GetMenuInfo( hmenu
, &mi
);
3196 gle
= GetLastError();
3197 ok( ret
, "GetMenuInfo() should have succeeded\n");
3198 ok( gle
== 0xdeadbeef, "GetMenuInfo() error got %u\n", gle
);
3199 ok( mi
.dwStyle
& MNS_CHECKORBMP
, "menustyle was expected to have the MNS_CHECKORBMP flag\n");
3200 SetLastError(0xdeadbeef);
3201 mi
.cbSize
= sizeof( MENUINFO
);
3202 mi
.fMask
= MIM_STYLE
;
3203 ret
= GetMenuInfo( hsubmenu
, &mi
);
3204 gle
= GetLastError();
3205 ok( ret
, "GetMenuInfo() should have succeeded\n");
3206 ok( gle
== 0xdeadbeef, "GetMenuInfo() error got %u\n", gle
);
3207 ok( mi
.dwStyle
& MNS_CHECKORBMP
, "menustyle was expected to have the MNS_CHECKORBMP flag\n");
3208 /* now repeat that without the APPLYTOSUBMENUS flag and another style bit */
3209 SetLastError(0xdeadbeef);
3210 mi
.cbSize
= sizeof( MENUINFO
);
3211 mi
.fMask
= MIM_STYLE
;
3212 mi
.dwStyle
= MNS_NOCHECK
;
3213 ret
= SetMenuInfo( hmenu
, &mi
);
3214 gle
= GetLastError();
3215 ok( ret
, "SetMenuInfo() should have succeeded\n");
3216 ok( gle
== 0xdeadbeef, "SetMenuInfo() error got %u\n", gle
);
3217 /* Now only the top menu should have the MNS_NOCHECK style bit set */
3218 SetLastError(0xdeadbeef);
3219 mi
.cbSize
= sizeof( MENUINFO
);
3220 mi
.fMask
= MIM_STYLE
;
3221 ret
= GetMenuInfo( hmenu
, &mi
);
3222 gle
= GetLastError();
3223 ok( ret
, "GetMenuInfo() should have succeeded\n");
3224 ok( gle
== 0xdeadbeef, "GetMenuInfo() error got %u\n", gle
);
3225 ok( mi
.dwStyle
& MNS_NOCHECK
, "menustyle was expected to have the MNS_NOCHECK flag\n");
3226 SetLastError(0xdeadbeef);
3227 mi
.cbSize
= sizeof( MENUINFO
);
3228 mi
.fMask
= MIM_STYLE
;
3229 ret
= GetMenuInfo( hsubmenu
, &mi
);
3230 gle
= GetLastError();
3231 ok( ret
, "GetMenuInfo() should have succeeded\n");
3232 ok( gle
== 0xdeadbeef, "GetMenuInfo() error got %u\n", gle
);
3233 ok( !(mi
.dwStyle
& MNS_NOCHECK
), "menustyle was not expected to have the MNS_NOCHECK flag\n");
3235 /* test background brush */
3236 mi
.cbSize
= sizeof(mi
);
3237 mi
.fMask
= MIM_BACKGROUND
;
3238 ret
= GetMenuInfo( hmenu
, &mi
);
3239 ok( ret
, "GetMenuInfo() should have succeeded\n" );
3240 ok( mi
.hbrBack
== NULL
, "got %p\n", mi
.hbrBack
);
3242 brush
= CreateSolidBrush( RGB(0xff, 0, 0) );
3244 ret
= SetMenuInfo( hmenu
, &mi
);
3245 ok( ret
, "SetMenuInfo() should have succeeded\n" );
3247 ret
= GetMenuInfo( hmenu
, &mi
);
3248 ok( ret
, "GetMenuInfo() should have succeeded\n" );
3249 ok( mi
.hbrBack
== brush
, "got %p original %p\n", mi
.hbrBack
, brush
);
3252 ret
= SetMenuInfo( hmenu
, &mi
);
3253 ok( ret
, "SetMenuInfo() should have succeeded\n" );
3254 ret
= GetMenuInfo( hmenu
, &mi
);
3255 ok( ret
, "GetMenuInfo() should have succeeded\n" );
3256 ok( mi
.hbrBack
== NULL
, "got %p\n", mi
.hbrBack
);
3257 DeleteObject( brush
);
3260 DestroyMenu( hsubmenu
);
3261 DestroyMenu( hmenu
);
3265 /* little func to easy switch either TrackPopupMenu() or TrackPopupMenuEx() */
3266 static DWORD
MyTrackPopupMenu( int ex
, HMENU hmenu
, UINT flags
, INT x
, INT y
, HWND hwnd
, LPTPMPARAMS ptpm
)
3269 ? TrackPopupMenuEx( hmenu
, flags
, x
, y
, hwnd
, ptpm
)
3270 : TrackPopupMenu( hmenu
, flags
, x
, y
, 0, hwnd
, NULL
);
3273 /* some TrackPopupMenu and TrackPopupMenuEx tests */
3274 /* the LastError values differ between NO_ERROR and invalid handle */
3275 /* between all windows versions tested. The first value is that valid on XP */
3276 /* Vista was the only that made returned different error values */
3277 /* between the TrackPopupMenu and TrackPopupMenuEx functions */
3278 static void test_menu_trackpopupmenu(void)
3284 HWND hwnd
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
3285 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
3286 NULL
, NULL
, NULL
, NULL
);
3287 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
3289 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)menu_ownerdraw_wnd_proc
);
3290 for( Ex
= 0; Ex
< 2; Ex
++)
3292 hmenu
= CreatePopupMenu();
3293 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
3296 DestroyWindow(hwnd
);
3299 /* display the menu */
3300 /* start with an invalid menu handle */
3301 SetLastError(0xdeadbeef);
3303 gflag_initmenupopup
= gflag_entermenuloop
= gflag_initmenu
= 0;
3304 ret
= MyTrackPopupMenu( Ex
, NULL
, TPM_RETURNCMD
, 100,100, hwnd
, NULL
);
3305 gle
= GetLastError();
3306 ok( !ret
, "TrackPopupMenu%s should have failed\n", Ex
? "Ex" : "");
3307 ok( gle
== ERROR_INVALID_MENU_HANDLE
3308 || broken (gle
== 0xdeadbeef) /* win95 */
3309 || broken (gle
== NO_ERROR
) /* win98/ME */
3310 ,"TrackPopupMenu%s error got %u expected %u\n",
3311 Ex
? "Ex" : "", gle
, ERROR_INVALID_MENU_HANDLE
);
3312 ok( !(gflag_initmenupopup
|| gflag_entermenuloop
|| gflag_initmenu
),
3313 "got unexpected message(s)%s%s%s\n",
3314 gflag_initmenupopup
? " WM_INITMENUPOPUP ": " ",
3315 gflag_entermenuloop
? "WM_INITMENULOOP ": "",
3316 gflag_initmenu
? "WM_INITMENU": "");
3317 /* another one but not NULL */
3318 SetLastError(0xdeadbeef);
3319 gflag_initmenupopup
= gflag_entermenuloop
= gflag_initmenu
= 0;
3320 ret
= MyTrackPopupMenu( Ex
, (HMENU
)hwnd
, TPM_RETURNCMD
, 100,100, hwnd
, NULL
);
3321 gle
= GetLastError();
3322 ok( !ret
, "TrackPopupMenu%s should have failed\n", Ex
? "Ex" : "");
3323 ok( gle
== ERROR_INVALID_MENU_HANDLE
3324 || broken (gle
== 0xdeadbeef) /* win95 */
3325 || broken (gle
== NO_ERROR
) /* win98/ME */
3326 ,"TrackPopupMenu%s error got %u expected %u\n",
3327 Ex
? "Ex" : "", gle
, ERROR_INVALID_MENU_HANDLE
);
3328 ok( !(gflag_initmenupopup
|| gflag_entermenuloop
|| gflag_initmenu
),
3329 "got unexpected message(s)%s%s%s\n",
3330 gflag_initmenupopup
? " WM_INITMENUPOPUP ": " ",
3331 gflag_entermenuloop
? "WM_INITMENULOOP ": "",
3332 gflag_initmenu
? "WM_INITMENU": "");
3334 /* invalid window */
3335 SetLastError(0xdeadbeef);
3336 gflag_initmenupopup
= gflag_entermenuloop
= gflag_initmenu
= 0;
3337 ret
= MyTrackPopupMenu( Ex
, hmenu
, TPM_RETURNCMD
, 100,100, 0, NULL
);
3338 gle
= GetLastError();
3339 ok( !ret
, "TrackPopupMenu%s should have failed\n", Ex
? "Ex" : "");
3340 ok( gle
== ERROR_INVALID_WINDOW_HANDLE
, "TrackPopupMenu%s error got %u\n", Ex
? "Ex" : "", gle
);
3341 ok( !(gflag_initmenupopup
|| gflag_entermenuloop
|| gflag_initmenu
),
3342 "got unexpected message(s)%s%s%s\n",
3343 gflag_initmenupopup
? " WM_INITMENUPOPUP ": " ",
3344 gflag_entermenuloop
? "WM_INITMENULOOP ": "",
3345 gflag_initmenu
? "WM_INITMENU": "");
3347 /* now a somewhat successful call */
3348 SetLastError(0xdeadbeef);
3349 gflag_initmenupopup
= gflag_entermenuloop
= gflag_initmenu
= 0;
3350 ret
= MyTrackPopupMenu( Ex
, hmenu
, TPM_RETURNCMD
, 100,100, hwnd
, NULL
);
3351 gle
= GetLastError();
3352 ok( ret
== 0, "TrackPopupMenu%s returned %d expected zero\n", Ex
? "Ex" : "", ret
);
3354 || gle
== ERROR_INVALID_MENU_HANDLE
/* NT4, win2k */
3355 || broken (gle
== 0xdeadbeef) /* win95 */
3356 ,"TrackPopupMenu%s error got %u expected %u or %u\n",
3357 Ex
? "Ex" : "", gle
, NO_ERROR
, ERROR_INVALID_MENU_HANDLE
);
3358 ok( gflag_initmenupopup
&& gflag_entermenuloop
&& gflag_initmenu
,
3359 "missed expected message(s)%s%s%s\n",
3360 !gflag_initmenupopup
? " WM_INITMENUPOPUP ": " ",
3361 !gflag_entermenuloop
? "WM_INITMENULOOP ": "",
3362 !gflag_initmenu
? "WM_INITMENU": "");
3364 ret
= AppendMenuA( hmenu
, MF_STRING
, 1, "winetest");
3365 ok( ret
, "AppendMenA has failed!\n");
3366 SetLastError(0xdeadbeef);
3367 gflag_initmenupopup
= gflag_entermenuloop
= gflag_initmenu
= 0;
3368 ret
= MyTrackPopupMenu( Ex
, hmenu
, TPM_RETURNCMD
, 100,100, hwnd
, NULL
);
3369 gle
= GetLastError();
3370 ok( ret
== 0, "TrackPopupMenu%s returned %d expected zero\n", Ex
? "Ex" : "", ret
);
3372 || gle
== ERROR_INVALID_MENU_HANDLE
/* NT4, win2k and Vista in the TrackPopupMenuEx case */
3373 || broken (gle
== 0xdeadbeef) /* win95 */
3374 ,"TrackPopupMenu%s error got %u expected %u or %u\n",
3375 Ex
? "Ex" : "", gle
, NO_ERROR
, ERROR_INVALID_MENU_HANDLE
);
3376 ok( gflag_initmenupopup
&& gflag_entermenuloop
&& gflag_initmenu
,
3377 "missed expected message(s)%s%s%s\n",
3378 !gflag_initmenupopup
? " WM_INITMENUPOPUP ": " ",
3379 !gflag_entermenuloop
? "WM_INITMENULOOP ": "",
3380 !gflag_initmenu
? "WM_INITMENU": "");
3384 DestroyWindow(hwnd
);
3387 static HMENU g_hmenu
;
3389 static LRESULT WINAPI
menu_track_again_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
3393 case WM_ENTERMENULOOP
:
3397 /* try a recursive call */
3398 SetLastError(0xdeadbeef);
3399 ret
= TrackPopupMenu(g_hmenu
, 0, 100, 100, 0, hwnd
, NULL
);
3400 ok(ret
== FALSE
, "got %d\n", ret
);
3401 ok(GetLastError() == ERROR_POPUP_ALREADY_ACTIVE
||
3402 broken(GetLastError() == 0xdeadbeef) /* W9x */, "got %d\n", GetLastError());
3404 /* exit menu modal loop
3405 * ( A SendMessage does not work on NT3.51 here ) */
3406 return PostMessageA(hwnd
, WM_CANCELMODE
, 0, 0);
3409 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
3412 static void test_menu_trackagain(void)
3417 hwnd
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
3418 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
3419 NULL
, NULL
, NULL
, NULL
);
3420 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
3422 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)menu_track_again_wnd_proc
);
3424 g_hmenu
= CreatePopupMenu();
3425 ok(g_hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
3427 ret
= AppendMenuA(g_hmenu
, MF_STRING
, 100, "item 1");
3428 ok(ret
, "AppendMenu failed.\n");
3429 ret
= AppendMenuA(g_hmenu
, MF_STRING
, 101, "item 2");
3430 ok(ret
, "AppendMenu failed.\n");
3432 ret
= TrackPopupMenu( g_hmenu
, 0, 100, 100, 0, hwnd
, NULL
);
3433 ok(ret
== TRUE
, "got %d\n", ret
);
3435 DestroyMenu(g_hmenu
);
3436 DestroyWindow(hwnd
);
3439 /* test handling of WM_CANCELMODE messages */
3440 static int g_got_enteridle
;
3441 static HWND g_hwndtosend
;
3442 static LRESULT WINAPI
menu_cancelmode_wnd_proc(HWND hwnd
, UINT msg
,
3443 WPARAM wparam
, LPARAM lparam
)
3447 case WM_ENTERMENULOOP
:
3448 g_got_enteridle
= 0;
3449 return SendMessageA( g_hwndtosend
, WM_CANCELMODE
, 0, 0);
3452 if( g_got_enteridle
++ == 0) {
3453 /* little hack to get another WM_ENTERIDLE message */
3454 PostMessageA( hwnd
, WM_MOUSEMOVE
, 0, 0);
3455 return SendMessageA( g_hwndtosend
, WM_CANCELMODE
, 0, 0);
3461 return DefWindowProcA( hwnd
, msg
, wparam
, lparam
);
3464 static void test_menu_cancelmode(void)
3467 HWND hwnd
, hwndchild
;
3468 HMENU menu
, menubar
;
3471 hwnd
= CreateWindowExA( 0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
3472 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
3473 NULL
, NULL
, NULL
, NULL
);
3474 hwndchild
= CreateWindowExA( 0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
3475 WS_VISIBLE
| WS_CHILD
, 10, 10, 20, 20,
3476 hwnd
, NULL
, NULL
, NULL
);
3477 ok( hwnd
!= NULL
&& hwndchild
!= NULL
,
3478 "CreateWindowEx failed with error %d\n", GetLastError());
3479 g_hwndtosend
= hwnd
;
3480 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)menu_cancelmode_wnd_proc
);
3481 SetWindowLongPtrA( hwndchild
, GWLP_WNDPROC
, (LONG_PTR
)menu_cancelmode_wnd_proc
);
3482 menu
= CreatePopupMenu();
3483 ok( menu
!= NULL
, "CreatePopupMenu failed with error %d\n", GetLastError());
3484 ret
= AppendMenuA( menu
, MF_STRING
, 1, "winetest");
3485 ok( ret
, "Functie failed lasterror is %u\n", GetLastError());
3486 /* seems to be needed only on wine :( */
3487 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
3488 DispatchMessageA(&msg
);
3489 /* test the effect of sending a WM_CANCELMODE message in the WM_INITMENULOOP
3490 * handler of the menu owner */
3491 /* test results is extracted from variable g_got_enteridle. Possible values:
3492 * 0 : complete conformance. Sending WM_CANCELMODE cancels a menu initializing tracking
3493 * 1 : Sending WM_CANCELMODE cancels a menu that is in tracking state
3494 * 2 : Sending WM_CANCELMODE does not work
3496 /* menu owner is top level window */
3497 g_hwndtosend
= hwnd
;
3498 TrackPopupMenu( menu
, TPM_RETURNCMD
, 100,100, 0, hwnd
, NULL
);
3499 ok( g_got_enteridle
== 0, "received %d WM_ENTERIDLE messages, none expected\n", g_got_enteridle
);
3500 /* menu owner is child window */
3501 g_hwndtosend
= hwndchild
;
3502 TrackPopupMenu( menu
, TPM_RETURNCMD
, 100,100, 0, hwndchild
, NULL
);
3503 ok(g_got_enteridle
== 0, "received %d WM_ENTERIDLE messages, none expected\n", g_got_enteridle
);
3504 /* now send the WM_CANCELMODE messages to the WRONG window */
3505 /* those should fail ( to have any effect) */
3506 g_hwndtosend
= hwnd
;
3507 TrackPopupMenu( menu
, TPM_RETURNCMD
, 100,100, 0, hwndchild
, NULL
);
3508 ok( g_got_enteridle
== 2, "received %d WM_ENTERIDLE messages, should be 2\n", g_got_enteridle
);
3510 /* test canceling tracking in a window's menu bar */
3511 menubar
= CreateMenu();
3512 ok( menubar
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
3513 ret
= AppendMenuA( menubar
, MF_POPUP
|MF_STRING
, (UINT_PTR
)menu
, "winetest");
3514 ok( ret
, "AppendMenuA failed lasterror is %u\n", GetLastError());
3515 ret
= SetMenu( hwnd
, menubar
);
3516 ok( ret
, "SetMenu failed lasterror is %u\n", GetLastError());
3517 /* initiate tracking */
3518 g_hwndtosend
= hwnd
;
3519 ret
= SendMessageA( hwnd
, WM_SYSCOMMAND
, SC_KEYMENU
, 0 );
3520 ok( ret
== 0, "Sending WM_SYSCOMMAND/SC_KEYMENU failed lasterror is %u\n", GetLastError());
3521 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
))
3522 DispatchMessageA(&msg
);
3523 ok(g_got_enteridle
== 0, "received %d WM_ENTERIDLE messages, none expected\n", g_got_enteridle
);
3526 DestroyMenu( menubar
);
3528 DestroyWindow( hwndchild
);
3529 DestroyWindow( hwnd
);
3532 /* show menu trees have a maximum depth */
3533 static void test_menu_maxdepth(void)
3535 #define NR_MENUS 100
3536 HMENU hmenus
[ NR_MENUS
];
3540 SetLastError(12345678);
3541 for( i
= 0; i
< NR_MENUS
; i
++) {
3542 hmenus
[i
] = CreatePopupMenu();
3543 if( !hmenus
[i
]) break;
3545 ok( i
== NR_MENUS
, "could not create more than %d menu's\n", i
);
3546 for( i
= 1; i
< NR_MENUS
; i
++) {
3547 ret
= AppendMenuA( hmenus
[i
], MF_POPUP
, (UINT_PTR
)hmenus
[i
-1],"test");
3550 trace("Maximum depth is %d\n", i
);
3551 ok( GetLastError() == 12345678, "unexpected error %d\n", GetLastError());
3553 broken( i
== NR_MENUS
), /* win98, NT */
3554 "no ( or very large) limit on menu depth!\n");
3556 for( i
= 0; i
< NR_MENUS
; i
++)
3557 DestroyMenu( hmenus
[i
]);
3561 static void test_menu_circref(void)
3566 menu1
= CreatePopupMenu();
3567 menu2
= CreatePopupMenu();
3568 ok( menu1
&& menu2
, "error creating menus.\n");
3569 ret
= AppendMenuA( menu1
, MF_POPUP
, (UINT_PTR
)menu2
, "winetest");
3570 ok( ret
, "AppendMenu failed, error is %d\n", GetLastError());
3571 ret
= AppendMenuA( menu1
, MF_STRING
| MF_HILITE
, 123, "winetest");
3572 ok( ret
, "AppendMenu failed, error is %d\n", GetLastError());
3573 /* app chooses an id that happens to clash with its own hmenu */
3574 ret
= AppendMenuA( menu2
, MF_STRING
, (UINT_PTR
)menu2
, "winetest");
3575 ok( ret
, "AppendMenu failed, error is %d\n", GetLastError());
3576 /* now attempt to change the string of the first item of menu1 */
3577 ret
= ModifyMenuA( menu1
, (UINT_PTR
)menu2
, MF_POPUP
, (UINT_PTR
)menu2
, "menu 2");
3579 broken( ret
), /* win98, NT */
3580 "ModifyMenu should have failed.\n");
3581 if( !ret
) { /* will probably stack fault if the ModifyMenu succeeded */
3582 ret
= GetMenuState( menu1
, 123, 0);
3583 ok( ret
== MF_HILITE
, "GetMenuState returned %x\n",ret
);
3585 DestroyMenu( menu2
);
3586 DestroyMenu( menu1
);
3589 /* test how the menu texts are aligned when the menu items have
3590 * different combinations of text and bitmaps (bug #13350) */
3591 static void test_menualign(void)
3595 HBITMAP hbm1
, hbm2
, hbm3
;
3596 MENUITEMINFOA mii
= { sizeof(MENUITEMINFOA
) };
3599 MENUINFO mi
= { sizeof( MENUINFO
)};
3601 if( !winetest_interactive
) {
3602 skip( "interactive alignment tests.\n");
3605 hwnd
= CreateWindowExA(0,
3607 "Menu text alignment Test\nPlease make a selection.",
3608 WS_OVERLAPPEDWINDOW
,
3611 NULL
, NULL
, 0, NULL
);
3612 ShowWindow( hwnd
, SW_SHOW
);
3613 /* create bitmaps */
3614 memset( bmfill
, 0xcc, sizeof( bmfill
));
3615 hbm1
= CreateBitmap( 10,10,1,1,bmfill
);
3616 hbm2
= CreateBitmap( 20,20,1,1,bmfill
);
3617 hbm3
= CreateBitmap( 50,6,1,1,bmfill
);
3618 ok( hbm1
&& hbm2
&& hbm3
, "Creating bitmaps failed\n");
3619 menu
= CreatePopupMenu();
3620 ok( menu
!= NULL
, "CreatePopupMenu() failed\n");
3622 mi
.fMask
= MIM_STYLE
;
3623 ret
= GetMenuInfo( menu
, &mi
);
3624 ok( ret
, "GetMenuInfo failed: %d\n", GetLastError());
3625 ok( menu
!= NULL
, "GetMenuInfo() failed\n");
3626 ok( 0 == mi
.dwStyle
, "menuinfo style is %x\n", mi
.dwStyle
);
3629 mii
.fMask
= MIIM_BITMAP
| MIIM_STRING
| MIIM_ID
;
3631 mii
.hbmpItem
= hbm1
;
3632 mii
.dwTypeData
= (LPSTR
) " OK: menu texts are correctly left-aligned.";
3633 ret
= InsertMenuItemA( menu
, -1, TRUE
, &mii
);
3634 ok( ret
, "InsertMenuItem() failed\n");
3635 mii
.fMask
= MIIM_BITMAP
| MIIM_STRING
| MIIM_ID
;
3637 mii
.hbmpItem
= hbm2
;
3638 mii
.dwTypeData
= (LPSTR
) " FAIL: menu texts are NOT left-aligned.";
3639 ret
= InsertMenuItemA( menu
, -1, TRUE
, &mii
);
3640 ok( ret
, "InsertMenuItem() failed\n");
3641 ret
= TrackPopupMenu( menu
, TPM_RETURNCMD
, 110, 200, 0, hwnd
, NULL
);
3642 ok( ret
!= 2, "User indicated that menu text alignment test 1 failed %d\n", ret
);
3644 mii
.fMask
= MIIM_BITMAP
| MIIM_STRING
| MIIM_ID
;
3646 mii
.hbmpItem
= hbm3
;
3647 mii
.dwTypeData
= NULL
;
3648 ret
= InsertMenuItemA( menu
, 0, TRUE
, &mii
);
3649 ok( ret
, "InsertMenuItem() failed\n");
3650 mii
.fMask
= MIIM_BITMAP
| MIIM_STRING
| MIIM_ID
;
3652 mii
.hbmpItem
= hbm1
;
3653 /* make the text a bit longer, to keep it readable */
3654 /* this bug is on winXP and reproduced on wine */
3655 mii
.dwTypeData
= (LPSTR
) " OK: menu texts are to the right of the bitmaps........";
3656 ret
= SetMenuItemInfoA( menu
, 1, TRUE
, &mii
);
3657 ok( ret
, "SetMenuItemInfo() failed\n");
3659 mii
.hbmpItem
= hbm2
;
3660 mii
.dwTypeData
= (LPSTR
) " FAIL: menu texts are below the first bitmap. ";
3661 ret
= SetMenuItemInfoA( menu
, 2, TRUE
, &mii
);
3662 ok( ret
, "SetMenuItemInfo() failed\n");
3663 ret
= TrackPopupMenu( menu
, TPM_RETURNCMD
, 110, 200, 0, hwnd
, NULL
);
3664 ok( ret
!= 2, "User indicated that menu text alignment test 2 failed %d\n", ret
);
3666 mii
.fMask
= MIIM_TYPE
| MIIM_ID
;
3668 mii
.fType
= MFT_BITMAP
;
3669 mii
.dwTypeData
= (LPSTR
) hbm3
;
3670 ret
= SetMenuItemInfoA( menu
, 0, TRUE
, &mii
);
3671 ok( ret
, "SetMenuItemInfo() failed\n");
3672 mii
.fMask
= MIIM_BITMAP
| MIIM_STRING
| MIIM_ID
;
3674 mii
.hbmpItem
= NULL
;
3675 mii
.dwTypeData
= (LPSTR
) " OK: menu texts are below the bitmap.";
3676 ret
= SetMenuItemInfoA( menu
, 1, TRUE
, &mii
);
3677 ok( ret
, "SetMenuItemInfo() failed\n");
3679 mii
.hbmpItem
= NULL
;
3680 mii
.dwTypeData
= (LPSTR
) " FAIL: menu texts are NOT below the bitmap.";
3681 ret
= SetMenuItemInfoA( menu
, 2, TRUE
, &mii
);
3682 ok( ret
, "SetMenuItemInfo() failed\n");
3683 ret
= TrackPopupMenu( menu
, TPM_RETURNCMD
, 110, 200, 0, hwnd
, NULL
);
3684 ok( ret
!= 2, "User indicated that menu text alignment test 3 failed %d\n", ret
);
3686 DeleteObject( hbm1
);
3687 DeleteObject( hbm2
);
3688 DeleteObject( hbm3
);
3690 DestroyWindow( hwnd
);
3693 static LRESULT WINAPI
menu_fill_in_init(HWND hwnd
, UINT msg
,
3694 WPARAM wparam
, LPARAM lparam
)
3700 case WM_INITMENUPOPUP
:
3701 gflag_initmenupopup
++;
3702 hmenupopup
= (HMENU
) wparam
;
3703 ret
= AppendMenuA(hmenupopup
, MF_STRING
, 100, "item 1");
3704 ok(ret
, "AppendMenu failed.\n");
3705 ret
= AppendMenuA(hmenupopup
, MF_STRING
, 101, "item 2");
3706 ok(ret
, "AppendMenu failed.\n");
3708 case WM_ENTERMENULOOP
:
3709 gflag_entermenuloop
++;
3716 PostMessageA(hwnd
, WM_CANCELMODE
, 0, 0);
3719 selectitem_wp
= wparam
;
3720 selectitem_lp
= lparam
;
3723 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
3726 static void test_emptypopup(void)
3731 HWND hwnd
= CreateWindowExA(0, (LPCSTR
)MAKEINTATOM(atomMenuCheckClass
), NULL
,
3732 WS_VISIBLE
, CW_USEDEFAULT
, CW_USEDEFAULT
, 200, 200,
3733 NULL
, NULL
, NULL
, NULL
);
3734 ok(hwnd
!= NULL
, "CreateWindowEx failed with error %d\n", GetLastError());
3735 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)menu_ownerdraw_wnd_proc
);
3737 hmenu
= CreatePopupMenu();
3738 ok(hmenu
!= NULL
, "CreateMenu failed with error %d\n", GetLastError());
3740 gflag_initmenupopup
= gflag_entermenuloop
= gflag_initmenu
= gflag_enteridle
= 0;
3741 selectitem_wp
= 0xdeadbeef;
3742 selectitem_lp
= 0xdeadbeef;
3744 ret
= TrackPopupMenu( hmenu
, TPM_RETURNCMD
, 100,100, 0, hwnd
, NULL
);
3745 ok(ret
== 0, "got %i\n", ret
);
3747 ok(gflag_initmenupopup
== 1, "got %i\n", gflag_initmenupopup
);
3748 ok(gflag_entermenuloop
== 1, "got %i\n", gflag_entermenuloop
);
3749 ok(gflag_initmenu
== 1, "got %i\n", gflag_initmenu
);
3750 ok(gflag_enteridle
== 0, "got %i\n", gflag_initmenu
);
3752 ok(selectitem_wp
== 0xdeadbeef, "got %lx\n", selectitem_wp
);
3753 ok(selectitem_lp
== 0xdeadbeef, "got %lx\n", selectitem_lp
);
3755 gflag_initmenupopup
= gflag_entermenuloop
= gflag_initmenu
= gflag_enteridle
= 0;
3756 selectitem_wp
= 0xdeadbeef;
3757 selectitem_lp
= 0xdeadbeef;
3759 ret
= TrackPopupMenu( hmenu
, 0, 100,100, 0, hwnd
, NULL
);
3760 ok(ret
== 0, "got %i\n", ret
);
3762 ok(gflag_initmenupopup
== 1, "got %i\n", gflag_initmenupopup
);
3763 ok(gflag_entermenuloop
== 1, "got %i\n", gflag_entermenuloop
);
3764 ok(gflag_initmenu
== 1, "got %i\n", gflag_initmenu
);
3765 ok(gflag_enteridle
== 0, "got %i\n", gflag_initmenu
);
3767 ok(selectitem_wp
== 0xdeadbeef, "got %lx\n", selectitem_wp
);
3768 ok(selectitem_lp
== 0xdeadbeef, "got %lx\n", selectitem_lp
);
3770 SetWindowLongPtrA( hwnd
, GWLP_WNDPROC
, (LONG_PTR
)menu_fill_in_init
);
3772 gflag_initmenupopup
= gflag_entermenuloop
= gflag_initmenu
= gflag_enteridle
= 0;
3773 selectitem_wp
= 0xdeadbeef;
3774 selectitem_lp
= 0xdeadbeef;
3776 ret
= TrackPopupMenu( hmenu
, 0, 100,100, 0, hwnd
, NULL
);
3777 ok(ret
== 1, "got %i\n", ret
);
3779 ok(gflag_initmenupopup
== 1, "got %i\n", gflag_initmenupopup
);
3780 ok(gflag_entermenuloop
== 1, "got %i\n", gflag_entermenuloop
);
3781 ok(gflag_initmenu
== 1, "got %i\n", gflag_initmenu
);
3782 ok(gflag_enteridle
== 1, "got %i\n", gflag_initmenu
);
3784 ok(selectitem_wp
== 0xffff0000, "got %lx\n", selectitem_wp
);
3785 ok(selectitem_lp
== 0, "got %lx\n", selectitem_lp
);
3787 DestroyWindow(hwnd
);
3789 ret
= DestroyMenu(hmenu
);
3790 ok(ret
, "DestroyMenu failed with error %d\n", GetLastError());
3793 static HMENU
get_bad_hmenu( UINT_PTR id
)
3795 while (IsMenu( (HMENU
)id
)) id
++;
3799 static void test_AppendMenu(void)
3801 static char string
[] = "string";
3803 HMENU hmenu
, hsubmenu
;
3808 hmenu
= CreateMenu();
3809 ok(hmenu
!= 0, "CreateMenu failed\n");
3810 ret
= AppendMenuA(hmenu
, MF_OWNERDRAW
, 201, "item 1");
3811 ok(ret
, "AppendMenu failed\n");
3812 check_menu_items(hmenu
, 201, MF_OWNERDRAW
, 0);
3815 hmenu
= CreateMenu();
3816 ok(hmenu
!= 0, "CreateMenu failed\n");
3817 hsubmenu
= get_bad_hmenu( 202 );
3818 ret
= AppendMenuA(hmenu
, MF_POPUP
, (UINT_PTR
)hsubmenu
, "item 1");
3819 ok(ret
, "AppendMenu failed\n");
3820 check_menu_items(hmenu
, (UINT_PTR
)hsubmenu
, MF_STRING
, 0);
3823 hmenu
= CreateMenu();
3824 ok(hmenu
!= 0, "CreateMenu failed\n");
3825 hsubmenu
= get_bad_hmenu( 203 );
3826 ret
= AppendMenuA(hmenu
, MF_OWNERDRAW
| MF_POPUP
, (UINT_PTR
)hsubmenu
, "item 1");
3827 ok(ret
, "AppendMenu failed\n");
3828 check_menu_items(hmenu
, (UINT_PTR
)hsubmenu
, MF_OWNERDRAW
, 0);
3831 hmenu
= CreateMenu();
3832 ok(hmenu
!= 0, "CreateMenu failed\n");
3833 hsubmenu
= CreateMenu();
3834 ok(hsubmenu
!= 0, "CreateMenu failed\n");
3835 ret
= AppendMenuA(hmenu
, MF_OWNERDRAW
, (UINT_PTR
)hsubmenu
, "item 1");
3836 ok(ret
, "AppendMenu failed\n");
3837 check_menu_items(hmenu
, (UINT_PTR
)hsubmenu
, MF_OWNERDRAW
, 0);
3839 DestroyMenu(hsubmenu
);
3841 hmenu
= CreateMenu();
3842 ok(hmenu
!= 0, "CreateMenu failed\n");
3843 hsubmenu
= CreateMenu();
3844 ok(hsubmenu
!= 0, "CreateMenu failed\n");
3845 ret
= AppendMenuA(hmenu
, MF_POPUP
, (UINT_PTR
)hsubmenu
, "item 1");
3846 ok(ret
, "AppendMenu failed\n");
3847 check_menu_items(hmenu
, (UINT_PTR
)hsubmenu
, MF_STRING
, 0);
3849 DestroyMenu(hsubmenu
);
3851 hmenu
= CreateMenu();
3852 ok(hmenu
!= 0, "CreateMenu failed\n");
3853 hsubmenu
= CreateMenu();
3854 ok(hsubmenu
!= 0, "CreateMenu failed\n");
3855 ret
= AppendMenuA(hmenu
, MF_OWNERDRAW
| MF_POPUP
, (UINT_PTR
)hsubmenu
, "item 1");
3856 ok(ret
, "AppendMenu failed\n");
3857 check_menu_items(hmenu
, (UINT_PTR
)hsubmenu
, MF_OWNERDRAW
, 0);
3859 DestroyMenu(hsubmenu
);
3861 hmenu
= CreateMenu();
3862 ok(hmenu
!= 0, "CreateMenu failed\n");
3863 hsubmenu
= CreatePopupMenu();
3864 ok(hsubmenu
!= 0, "CreatePopupMenu failed\n");
3865 ret
= AppendMenuA(hmenu
, MF_OWNERDRAW
, (UINT_PTR
)hsubmenu
, "item 1");
3866 ok(ret
, "AppendMenu failed\n");
3867 check_menu_items(hmenu
, (UINT_PTR
)hsubmenu
, MF_OWNERDRAW
, 0);
3869 DestroyMenu(hsubmenu
);
3871 hmenu
= CreateMenu();
3872 ok(hmenu
!= 0, "CreateMenu failed\n");
3873 hsubmenu
= CreatePopupMenu();
3874 ok(hsubmenu
!= 0, "CreatePopupMenu failed\n");
3875 ret
= AppendMenuA(hmenu
, MF_POPUP
, (UINT_PTR
)hsubmenu
, "item 1");
3876 ok(ret
, "AppendMenu failed\n");
3877 check_menu_items(hmenu
, (UINT_PTR
)hsubmenu
, MF_STRING
, 0);
3879 DestroyMenu(hsubmenu
);
3881 hmenu
= CreateMenu();
3882 ok(hmenu
!= 0, "CreateMenu failed\n");
3883 hsubmenu
= CreatePopupMenu();
3884 ok(hsubmenu
!= 0, "CreatePopupMenu failed\n");
3885 ret
= AppendMenuA(hmenu
, MF_OWNERDRAW
| MF_POPUP
, (UINT_PTR
)hsubmenu
, "item 1");
3886 ok(ret
, "AppendMenu failed\n");
3887 check_menu_items(hmenu
, (UINT_PTR
)hsubmenu
, MF_OWNERDRAW
, 0);
3889 DestroyMenu(hsubmenu
);
3891 hmenu
= CreateMenu();
3892 ok(hmenu
!= 0, "CreateMenu failed\n");
3893 ret
= AppendMenuA(hmenu
, MF_STRING
, 204, "item 1");
3894 ok(ret
, "AppendMenu failed\n");
3895 check_menu_items(hmenu
, 204, MF_STRING
, 0);
3896 hsubmenu
= get_bad_hmenu( 205 );
3897 ret
= ModifyMenuA(hmenu
, 0, MF_POPUP
| MF_BYPOSITION
, (UINT_PTR
)hsubmenu
, "item 2");
3898 ok(ret
, "ModifyMenu failed\n");
3899 check_menu_items(hmenu
, (UINT_PTR
)hsubmenu
, MF_STRING
, 0);
3900 memset(&mii
, 0, sizeof(mii
));
3901 mii
.cbSize
= sizeof(mii
);
3902 mii
.fMask
= MIIM_SUBMENU
;
3903 mii
.hSubMenu
= get_bad_hmenu( 204 );
3904 ret
= InsertMenuItemA(hmenu
, 0, TRUE
, &mii
);
3905 ok(!ret
, "InsertMenuItem should fail\n");
3906 ret
= SetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
3907 ok(!ret
, "SetMenuItemInfo should fail\n");
3908 mii
.fMask
= MIIM_ID
;
3910 ret
= InsertMenuItemA(hmenu
, 0, TRUE
, &mii
);
3911 ok(ret
, "InsertMenuItem failed\n");
3912 if (0) /* FIXME: uncomment once Wine is fixed */ {
3913 check_menu_items(hmenu
, 206, MF_SEPARATOR
, MFS_GRAYED
);
3916 ret
= SetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
3917 ok(ret
, "SetMenuItemInfo failed\n");
3918 if (0) /* FIXME: uncomment once Wine is fixed */ {
3919 check_menu_items(hmenu
, 207, MF_SEPARATOR
, MFS_GRAYED
);
3923 hbmp
= CreateBitmap(1, 1, 1, 1, NULL
);
3924 hmenu
= CreateMenu();
3925 ok(hmenu
!= 0, "CreateMenu failed\n");
3927 /* menu item with a string and a bitmap */
3928 memset(&mii
, 0, sizeof(mii
));
3929 mii
.cbSize
= sizeof(mii
);
3930 mii
.fMask
= MIIM_STRING
| MIIM_BITMAP
;
3931 mii
.dwTypeData
= string
;
3932 mii
.cch
= strlen(string
);
3933 mii
.hbmpItem
= hbmp
;
3934 ret
= InsertMenuItemA(hmenu
, 0, TRUE
, &mii
);
3935 ok(ret
, "InsertMenuItem failed\n");
3936 memset(&mii
, 0x81, sizeof(mii
));
3937 memset(buf
, 0x81, sizeof(buf
));
3938 mii
.cbSize
= sizeof(mii
);
3939 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
| MIIM_SUBMENU
| MIIM_STRING
| MIIM_BITMAP
;
3940 mii
.dwTypeData
= buf
;
3941 mii
.cch
= sizeof(buf
);
3942 mii
.dwItemData
= 0x81818181;
3943 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
3944 ok(ret
, "GetMenuItemInfo failed\n");
3945 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
3946 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
3947 ok(mii
.wID
== 0, "expected 0, got %#x\n", mii
.wID
);
3948 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
3949 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
3950 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
3951 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
3952 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
3953 ok(mii
.hbmpItem
== hbmp
, "expected %p, got %p\n", hbmp
, mii
.hbmpItem
);
3955 memset(&mii
, 0x81, sizeof(mii
));
3956 mii
.cbSize
= sizeof(mii
);
3957 mii
.fMask
= MIIM_TYPE
;
3958 mii
.dwItemData
= 0x81818181;
3959 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
3960 ok(ret
, "GetMenuItemInfo failed\n");
3961 ok(mii
.fType
== MF_BITMAP
, "expected MF_BITMAP, got %#x\n", mii
.fType
);
3962 ok(mii
.fState
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.fState
);
3963 ok(mii
.wID
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.wID
);
3964 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
3965 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
3966 ok(mii
.dwTypeData
== (LPSTR
)hbmp
, "expected %p, got %p\n", hbmp
, mii
.dwTypeData
);
3967 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
3968 ok(mii
.hbmpItem
== hbmp
, "expected %p, got %p\n", hbmp
, mii
.hbmpItem
);
3970 memset(&mii
, 0x81, sizeof(mii
));
3971 memset(buf
, 0x81, sizeof(buf
));
3972 mii
.cbSize
= sizeof(mii
);
3973 mii
.fMask
= MIIM_STATE
| MIIM_ID
| MIIM_TYPE
| MIIM_DATA
;
3974 mii
.dwTypeData
= buf
;
3975 mii
.cch
= sizeof(buf
);
3976 mii
.dwItemData
= 0x81818181;
3977 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
3978 ok(ret
, "GetMenuItemInfo failed\n");
3979 ok(mii
.fType
== MF_BITMAP
, "expected MF_BITMAP, got %#x\n", mii
.fType
);
3980 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
3981 ok(mii
.wID
== 0, "expected 0, got %#x\n", mii
.wID
);
3982 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
3983 ok(mii
.dwItemData
== 0, "expected 0, got %#lx\n", mii
.dwItemData
);
3984 ok(mii
.dwTypeData
== (LPSTR
)hbmp
, "expected %p, got %p\n", hbmp
, mii
.dwTypeData
);
3985 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
3986 ok(mii
.hbmpItem
== hbmp
, "expected %p, got %p\n", hbmp
, mii
.hbmpItem
);
3991 hmenu
= CreateMenu();
3992 ok(hmenu
!= 0, "CreateMenu failed\n");
3994 /* menu item with a string and a "magic" bitmap */
3995 memset(&mii
, 0, sizeof(mii
));
3996 mii
.cbSize
= sizeof(mii
);
3997 mii
.fMask
= MIIM_STRING
| MIIM_BITMAP
;
3998 mii
.dwTypeData
= string
;
3999 mii
.cch
= strlen(string
);
4000 mii
.hbmpItem
= HBMMENU_POPUP_RESTORE
;
4001 ret
= InsertMenuItemA(hmenu
, 0, TRUE
, &mii
);
4002 ok(ret
, "InsertMenuItem failed\n");
4003 memset(&mii
, 0x81, sizeof(mii
));
4004 memset(buf
, 0x81, sizeof(buf
));
4005 mii
.cbSize
= sizeof(mii
);
4006 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
| MIIM_SUBMENU
| MIIM_STRING
| MIIM_BITMAP
;
4007 mii
.dwTypeData
= buf
;
4008 mii
.cch
= sizeof(buf
);
4009 mii
.dwItemData
= 0x81818181;
4010 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4011 ok(ret
, "GetMenuItemInfo failed\n");
4012 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
4013 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
4014 ok(mii
.wID
== 0, "expected 0, got %#x\n", mii
.wID
);
4015 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4016 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
4017 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
4018 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4019 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
4020 ok(mii
.hbmpItem
== HBMMENU_POPUP_RESTORE
, "expected HBMMENU_POPUP_RESTORE, got %p\n", mii
.hbmpItem
);
4022 memset(&mii
, 0x81, sizeof(mii
));
4023 mii
.cbSize
= sizeof(mii
);
4024 mii
.fMask
= MIIM_TYPE
;
4025 mii
.dwTypeData
= buf
;
4026 mii
.cch
= sizeof(buf
);
4027 mii
.dwItemData
= 0x81818181;
4028 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4029 ok(ret
, "GetMenuItemInfo failed\n");
4030 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
4031 ok(mii
.fState
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.fState
);
4032 ok(mii
.wID
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.wID
);
4033 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4034 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
4035 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
4036 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4037 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
4038 ok(mii
.hbmpItem
== HBMMENU_POPUP_RESTORE
, "expected HBMMENU_POPUP_RESTORE, got %p\n", mii
.hbmpItem
);
4040 memset(&mii
, 0x81, sizeof(mii
));
4041 memset(buf
, 0x81, sizeof(buf
));
4042 mii
.cbSize
= sizeof(mii
);
4043 mii
.fMask
= MIIM_STATE
| MIIM_ID
| MIIM_TYPE
| MIIM_DATA
;
4044 mii
.dwTypeData
= buf
;
4045 mii
.cch
= sizeof(buf
);
4046 mii
.dwItemData
= 0x81818181;
4047 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4048 ok(ret
, "GetMenuItemInfo failed\n");
4049 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
4050 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
4051 ok(mii
.wID
== 0, "expected 0, got %#x\n", mii
.wID
);
4052 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4053 ok(mii
.dwItemData
== 0, "expected 0, got %#lx\n", mii
.dwItemData
);
4054 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
4055 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4056 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
4057 ok(mii
.hbmpItem
== HBMMENU_POPUP_RESTORE
, "expected HBMMENU_POPUP_RESTORE, got %p\n", mii
.hbmpItem
);
4061 hbmp
= CreateBitmap(1, 1, 1, 1, NULL
);
4062 hmenu
= CreateMenu();
4063 ok(hmenu
!= 0, "CreateMenu failed\n");
4065 /* menu item with a string */
4066 memset(&mii
, 0, sizeof(mii
));
4067 mii
.cbSize
= sizeof(mii
);
4068 mii
.fMask
= MIIM_STATE
| MIIM_ID
| MIIM_TYPE
| MIIM_DATA
;
4069 mii
.dwItemData
= (ULONG_PTR
)hbmp
;
4070 mii
.dwTypeData
= string
;
4071 mii
.cch
= strlen(string
);
4072 mii
.hbmpItem
= hbmp
;
4073 ret
= InsertMenuItemA(hmenu
, 0, TRUE
, &mii
);
4074 ok(ret
, "InsertMenuItem failed\n");
4075 memset(&mii
, 0x81, sizeof(mii
));
4076 memset(buf
, 0x81, sizeof(buf
));
4077 mii
.cbSize
= sizeof(mii
);
4078 mii
.fMask
= MIIM_STATE
| MIIM_ID
| MIIM_TYPE
| MIIM_DATA
;
4079 mii
.dwTypeData
= buf
;
4080 mii
.cch
= sizeof(buf
);
4081 mii
.dwItemData
= 0x81818181;
4082 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4083 ok(ret
, "GetMenuItemInfo failed\n");
4084 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
4085 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
4086 ok(mii
.wID
== 0, "expected 0, got %#x\n", mii
.wID
);
4087 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4088 ok(mii
.dwItemData
== (ULONG_PTR
)hbmp
, "expected %p, got %#lx\n", hbmp
, mii
.dwItemData
);
4089 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
4090 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4091 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
4092 ok(mii
.hbmpItem
== 0, "expected 0, got %p\n", mii
.hbmpItem
);
4094 memset(&mii
, 0x81, sizeof(mii
));
4095 memset(buf
, 0x81, sizeof(buf
));
4096 mii
.cbSize
= sizeof(mii
);
4097 mii
.fMask
= MIIM_TYPE
;
4098 mii
.dwTypeData
= buf
;
4099 mii
.cch
= sizeof(buf
);
4100 mii
.dwItemData
= 0x81818181;
4101 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4102 ok(ret
, "GetMenuItemInfo failed\n");
4103 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
4104 ok(mii
.fState
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.fState
);
4105 ok(mii
.wID
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.wID
);
4106 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4107 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
4108 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
4109 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4110 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
4111 ok(mii
.hbmpItem
== 0, "expected 0, got %p\n", mii
.hbmpItem
);
4116 /* menu item with a string */
4117 hbmp
= CreateBitmap(1, 1, 1, 1, NULL
);
4118 hmenu
= CreateMenu();
4119 ok(hmenu
!= 0, "CreateMenu failed\n");
4120 memset(&mii
, 0, sizeof(mii
));
4121 mii
.cbSize
= sizeof(mii
);
4122 mii
.fMask
= MIIM_STRING
;
4123 mii
.dwTypeData
= string
;
4124 mii
.cch
= strlen(string
);
4125 ret
= InsertMenuItemA(hmenu
, 0, TRUE
, &mii
);
4126 ok(ret
, "InsertMenuItem failed\n");
4127 memset(&mii
, 0x81, sizeof(mii
));
4128 memset(buf
, 0x81, sizeof(buf
));
4129 mii
.cbSize
= sizeof(mii
);
4130 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
| MIIM_SUBMENU
| MIIM_STRING
| MIIM_BITMAP
;
4131 mii
.dwTypeData
= buf
;
4132 mii
.cch
= sizeof(buf
);
4133 mii
.dwItemData
= 0x81818181;
4134 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4135 ok(ret
, "GetMenuItemInfo failed\n");
4136 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
4137 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
4138 ok(mii
.wID
== 0, "expected 0, got %#x\n", mii
.wID
);
4139 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4140 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
4141 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
4142 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4143 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
4144 ok(mii
.hbmpItem
== 0, "expected 0, got %p\n", mii
.hbmpItem
);
4146 /* add "magic" bitmap to a menu item */
4147 mii
.fMask
= MIIM_BITMAP
;
4148 mii
.hbmpItem
= HBMMENU_POPUP_RESTORE
;
4149 ret
= SetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4150 ok(ret
, "SetMenuItemInfo failed\n");
4151 memset(&mii
, 0x81, sizeof(mii
));
4152 memset(buf
, 0x81, sizeof(buf
));
4153 mii
.cbSize
= sizeof(mii
);
4154 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
| MIIM_SUBMENU
| MIIM_STRING
| MIIM_BITMAP
;
4155 mii
.dwTypeData
= buf
;
4156 mii
.cch
= sizeof(buf
);
4157 mii
.dwItemData
= 0x81818181;
4158 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4159 ok(ret
, "GetMenuItemInfo failed\n");
4160 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
4161 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
4162 ok(mii
.wID
== 0, "expected 0, got %#x\n", mii
.wID
);
4163 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4164 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
4165 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
4166 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4167 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
4168 ok(mii
.hbmpItem
== HBMMENU_POPUP_RESTORE
, "expected HBMMENU_POPUP_RESTORE, got %p\n", mii
.hbmpItem
);
4170 memset(&mii
, 0x81, sizeof(mii
));
4171 memset(buf
, 0x81, sizeof(buf
));
4172 mii
.cbSize
= sizeof(mii
);
4173 mii
.fMask
= MIIM_TYPE
;
4174 mii
.dwTypeData
= buf
;
4175 mii
.cch
= sizeof(buf
);
4176 mii
.dwItemData
= 0x81818181;
4177 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4178 ok(ret
, "GetMenuItemInfo failed\n");
4179 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
4180 ok(mii
.fState
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.fState
);
4181 ok(mii
.wID
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.wID
);
4182 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4183 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
4184 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
4185 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4186 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
4187 ok(mii
.hbmpItem
== HBMMENU_POPUP_RESTORE
, "expected HBMMENU_POPUP_RESTORE, got %p\n", mii
.hbmpItem
);
4189 /* replace "magic" bitmap by a normal one */
4190 mii
.fMask
= MIIM_BITMAP
;
4191 mii
.hbmpItem
= hbmp
;
4192 ret
= SetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4193 ok(ret
, "SetMenuItemInfo failed\n");
4194 memset(&mii
, 0x81, sizeof(mii
));
4195 memset(buf
, 0x81, sizeof(buf
));
4196 mii
.cbSize
= sizeof(mii
);
4197 mii
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
| MIIM_SUBMENU
| MIIM_STRING
| MIIM_BITMAP
;
4198 mii
.dwTypeData
= buf
;
4199 mii
.cch
= sizeof(buf
);
4200 mii
.dwItemData
= 0x81818181;
4201 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4202 ok(ret
, "GetMenuItemInfo failed\n");
4203 ok(mii
.fType
== MF_STRING
, "expected MF_STRING, got %#x\n", mii
.fType
);
4204 ok(mii
.fState
== MF_ENABLED
, "expected MF_ENABLED, got %#x\n", mii
.fState
);
4205 ok(mii
.wID
== 0, "expected 0, got %#x\n", mii
.wID
);
4206 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4207 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
4208 ok(mii
.dwTypeData
== buf
, "expected %p, got %p\n", buf
, mii
.dwTypeData
);
4209 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4210 ok(!strcmp(buf
, string
), "expected %s, got %s\n", string
, buf
);
4211 ok(mii
.hbmpItem
== hbmp
, "expected %p, got %p\n", hbmp
, mii
.hbmpItem
);
4213 memset(&mii
, 0x81, sizeof(mii
));
4214 memset(buf
, 0x81, sizeof(buf
));
4215 mii
.cbSize
= sizeof(mii
);
4216 mii
.fMask
= MIIM_TYPE
;
4217 mii
.dwTypeData
= buf
;
4218 mii
.cch
= sizeof(buf
);
4219 mii
.dwItemData
= 0x81818181;
4220 ret
= GetMenuItemInfoA(hmenu
, 0, TRUE
, &mii
);
4221 ok(ret
, "GetMenuItemInfo failed\n");
4222 ok(mii
.fType
== MF_BITMAP
, "expected MF_BITMAP, got %#x\n", mii
.fType
);
4223 ok(mii
.fState
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.fState
);
4224 ok(mii
.wID
== 0x81818181, "expected 0x81818181, got %#x\n", mii
.wID
);
4225 ok(mii
.hSubMenu
== 0, "expected 0, got %p\n", mii
.hSubMenu
);
4226 ok(mii
.dwItemData
== 0x81818181, "expected 0x81818181, got %#lx\n", mii
.dwItemData
);
4227 ok(mii
.dwTypeData
== (LPSTR
)hbmp
, "expected %p, got %p\n", hbmp
, mii
.dwTypeData
);
4228 ok(mii
.cch
== 6, "expected 6, got %u\n", mii
.cch
);
4229 ok(mii
.hbmpItem
== hbmp
, "expected %p, got %p\n", hbmp
, mii
.hbmpItem
);
4237 register_menu_check_class();
4239 test_menu_add_string();
4240 test_menu_iteminfo();
4241 test_menu_search_bycommand();
4242 test_CheckMenuRadioItem();
4243 test_menu_resource_layout();
4248 test_menu_locked_by_window();
4249 test_subpopup_locked_by_menu();
4250 test_menu_ownerdraw();
4251 test_getmenubarinfo();
4252 test_GetMenuItemRect();
4253 test_menu_bmp_and_string();
4254 test_menu_getmenuinfo();
4255 test_menu_setmenuinfo();
4259 test_menu_hilitemenuitem();
4260 test_menu_trackpopupmenu();
4261 test_menu_trackagain();
4262 test_menu_cancelmode();
4263 test_menu_maxdepth();
4264 test_menu_circref();