Release 940510
[wine/multimedia.git] / controls / menu.c
blob9ef90f4147be2d9abefab36a1eb4c670470c5ca9
1 /*
2 * Menus functions
3 */
4 static char RCSId[] = "$Id$";
5 static char Copyright[] = "Copyright Martin Ayotte, 1993";
7 /*
8 #define DEBUG_MENU
9 */
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include "windows.h"
14 #include "sysmetrics.h"
15 #include "prototypes.h"
16 #include "menu.h"
17 #include "heap.h"
18 #include "win.h"
20 #define SC_ABOUTWINE SC_SCREENSAVE+1
21 #define SC_SYSMENU SC_SCREENSAVE+2
22 #define SC_ABOUTWINEDLG SC_SCREENSAVE+3
24 extern HINSTANCE hSysRes;
25 HMENU hSysMenu = 0;
26 HBITMAP hStdCheck = 0;
27 HBITMAP hStdMnArrow = 0;
28 static BOOL MenuHasFocus = FALSE;
30 LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd);
31 LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr);
32 void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop,
33 BOOL suppress_draw);
34 BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
35 void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
36 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y);
37 void StdDrawPopupMenu(HWND hwnd);
38 void ResetHiliteFlags(LPPOPUPMENU lppop);
39 BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop);
40 void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex);
41 LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet);
42 LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet);
43 BOOL ActivateMenuBarFocus(HWND hWnd);
44 BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu);
45 void PopupMenuCalcSize(HWND hwnd);
46 void MenuBarCalcSize(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop);
47 LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags);
48 LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos);
49 WORD GetSelectionKey(LPSTR str);
50 LPSTR GetShortCutString(LPSTR str);
51 WORD GetShortCutPos(LPSTR str);
52 BOOL HideAllSubPopupMenu(LPPOPUPMENU menu);
53 HMENU CopySysMenu();
54 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu);
55 void SetMenuLogicalParent(HMENU hMenu, HWND hWnd);
57 BOOL FAR PASCAL AboutWine_Proc(HWND hDlg, WORD msg, WORD wParam, LONG lParam);
59 /***********************************************************************
60 * PopupMenuWndProc
62 LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
64 CREATESTRUCT *createStruct;
65 WORD wRet;
66 short x, y;
67 WND *wndPtr;
68 LPPOPUPMENU lppop, lppop2;
69 LPMENUITEM lpitem, lpitem2;
70 HMENU hSubMenu;
71 RECT rect;
72 HDC hDC;
73 PAINTSTRUCT ps;
74 switch(message) {
75 case WM_CREATE:
76 #ifdef DEBUG_MENU
77 printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
78 #endif
79 createStruct = (CREATESTRUCT *)lParam;
80 lppop = (LPPOPUPMENU)createStruct->lpCreateParams;
81 if (lppop == NULL) break;
82 wndPtr = WIN_FindWndPtr(hwnd);
83 *((LPPOPUPMENU *)&wndPtr->wExtra[1]) = lppop;
84 #ifdef DEBUG_MENU
85 printf("PopupMenu WM_CREATE lppop=%08X !\n", lppop);
86 #endif
87 if (hStdCheck == (HBITMAP)NULL)
88 hStdCheck = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_CHECK);
89 if (hStdMnArrow == (HBITMAP)NULL)
90 hStdMnArrow = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_MNARROW);
91 #ifdef DEBUG_MENU
92 printf("PopupMenu End of WM_CREATE !\n");
93 #endif
94 return 0;
95 case WM_DESTROY:
96 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
97 #ifdef DEBUG_MENU
98 printf("PopupMenu WM_DESTROY %lX !\n", lppop);
99 #endif
100 return 0;
101 case WM_COMMAND:
102 #ifdef DEBUG_MENU
103 printf("PopupMenuWndProc // WM_COMMAND received !\n");
104 #endif
105 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
106 if (lppop == NULL) break;
107 /* if (!lppop->BarFlag) ShowWindow(hwnd, SW_HIDE); */
108 if (lppop->SysFlag) {
109 MenuHasFocus = FALSE;
110 if (wParam == SC_ABOUTWINE) {
111 printf("SysMenu // Show 'About Wine ...' !\n");
112 /* DialogBox(hSysRes, MAKEINTRESOURCE(SC_ABOUTWINEDLG), */
113 DialogBox(hSysRes, MAKEINTRESOURCE(2),
114 GetParent(hwnd), (FARPROC)AboutWine_Proc);
116 else
117 #ifdef DEBUG_MENU
118 printf("PopupMenuWndProc // push to Owner WM_SYSCOMMAND !\n");
119 #endif
120 PostMessage(lppop->ownerWnd, WM_SYSCOMMAND, wParam, lParam);
121 /* PostMessage(lppop->hWndParent, WM_SYSCOMMAND, wParam, lParam); */
122 break;
124 #ifdef DEBUG_MENU
125 printf("PopupMenuWndProc // push to Owner WM_COMMAND !\n");
126 #endif
127 MenuHasFocus = FALSE;
128 PostMessage(lppop->hWndParent, WM_COMMAND, wParam, lParam);
129 /* PostMessage(lppop->ownerWnd, WM_COMMAND, wParam, lParam); */
130 break;
131 case WM_SHOWWINDOW:
132 #ifdef DEBUG_MENU
133 printf("PopupMenuWndProc // WM_SHOWWINDOW received !\n");
134 #endif
135 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
136 if (lppop == NULL) break;
137 if (wParam == 0 && lParam == 0L) {
138 HideAllSubPopupMenu(lppop);
139 #ifdef DEBUG_MENU
140 printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW -> HIDE!\n", hwnd);
141 #endif
142 if (lppop->SysFlag) MenuHasFocus = FALSE;
143 SetFocus(lppop->hWndPrev);
144 if (GetCapture() != 0) ReleaseCapture();
145 break;
147 lppop->FocusedItem = (WORD)-1;
148 if (!lppop->BarFlag) {
149 PopupMenuCalcSize(hwnd);
150 ResetHiliteFlags(lppop);
151 #ifdef DEBUG_MENU
152 printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW Width=%d Height=%d !\n",
153 hwnd, lppop->Width, lppop->Height);
154 #endif
155 SetWindowPos(hwnd, 0, 0, 0, lppop->Width + 2, lppop->Height,
156 SWP_NOZORDER | SWP_NOMOVE);
157 #ifdef DEBUG_MENU
158 printf("PopupMenuWndProc // End of WM_SHOWWINDOW !\n");
159 #endif
161 break;
162 case WM_LBUTTONDOWN:
163 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
164 if (lppop == NULL) break;
165 SetCapture(hwnd);
166 MenuButtonDown(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
167 break;
168 case WM_LBUTTONUP:
169 lppop = PopupMenuGetStorageHeader(hwnd);
170 if (lppop == NULL) break;
171 ReleaseCapture();
172 MenuButtonUp(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
173 break;
174 case WM_MOUSEMOVE:
175 lppop = PopupMenuGetStorageHeader(hwnd);
176 if (lppop == NULL) break;
177 MenuMouseMove(hwnd, lppop, wParam, LOWORD(lParam), HIWORD(lParam));
178 break;
180 case WM_KEYUP:
181 #ifdef DEBUG_MENU
182 printf("PopupMenuWndProc hWnd=%04X WM_KEYUP w=%04X l=%08X !\n",
183 hwnd, wParam, lParam);
184 #endif
185 break;
186 case WM_KEYDOWN:
187 #ifdef DEBUG_MENU
188 printf("PopupMenuWndProc hWnd=%04X WM_KEYDOWN w=%04X l=%08X !\n",
189 hwnd, wParam, lParam);
190 #endif
191 if (lParam < 0L) break;
192 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
193 if (lppop == NULL) break;
194 switch(wParam) {
195 case VK_HOME:
196 if (lppop->FocusedItem == 0) break;
197 MenuItemSelect(hwnd, lppop, 0);
198 break;
199 case VK_UP:
200 if (lppop->BarFlag) break;
201 if (lppop->FocusedItem < 1) break;
202 MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
203 break;
204 case VK_DOWN:
205 if (lppop->BarFlag) goto ProceedSPACE;
206 if (lppop->FocusedItem == (WORD)-1) {
207 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
208 break;
210 if (lppop->FocusedItem >= lppop->nItems - 1) break;
211 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
212 break;
213 case VK_LEFT:
214 if (lppop->SysFlag != 0) {
215 ShowWindow(hwnd, SW_HIDE);
216 hwnd = lppop->hWndParent;
217 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
218 if (lppop == NULL) break;
219 MenuItemSelect(hwnd, lppop, lppop->nItems - 1);
220 break;
222 if (lppop->BarFlag) {
223 if (lppop->FocusedItem < 1) {
224 MenuItemSelect(hwnd, lppop, -1);
225 NC_TrackSysMenu(hwnd);
226 break;
228 if (HideAllSubPopupMenu(lppop)) {
229 MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
230 goto ProceedSPACE;
233 if (lppop->hWndParent != 0) {
234 PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
235 break;
237 MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
238 break;
239 case VK_RIGHT:
240 if (lppop->SysFlag != 0) {
241 ShowWindow(hwnd, SW_HIDE);
242 hwnd = lppop->hWndParent;
243 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
244 if (lppop == NULL) break;
245 MenuItemSelect(hwnd, lppop, 0);
246 break;
248 if (lppop->BarFlag) {
249 if (lppop->FocusedItem >= lppop->nItems - 1) {
250 MenuItemSelect(hwnd, lppop, -1);
251 NC_TrackSysMenu(hwnd);
252 break;
254 if (HideAllSubPopupMenu(lppop)) {
255 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
256 goto ProceedSPACE;
259 if (lppop->hWndParent != 0) {
260 PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
261 break;
263 MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
264 break;
265 case VK_RETURN:
266 case VK_SPACE:
267 ProceedSPACE: lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
268 ExecFocusedMenuItem(hwnd, lppop);
269 break;
270 default:
271 break;
273 break;
274 case WM_CHAR:
275 #ifdef DEBUG_MENU
276 printf("PopupMenuWndProc hWnd=%04X WM_CHAR wParam=%04X !\n", hwnd, wParam);
277 #endif
278 if (lParam < 0L) break;
279 hwnd = GetFocus();
280 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
281 if (lppop == NULL) break;
282 switch(wParam) {
283 case VK_ESCAPE:
284 if (lppop->BarFlag) {
285 #ifdef DEBUG_MENU
286 printf("VK_ESCAPE // Unselect all MenuBar's Items !\n");
287 #endif
288 if (lppop->FocusedItem != (WORD)-1)
289 MenuItemSelect(hwnd, lppop, -1);
291 if (lppop->SysFlag) {
292 #ifdef DEBUG_MENU
293 printf("VK_ESCAPE // SysMenu !\n");
294 #endif
295 ShowWindow(hwnd, SW_HIDE);
296 break;
298 if (lppop->hWndParent != 0) {
299 #ifdef DEBUG_MENU
300 printf("VK_ESCAPE // Hide only SubPopup !\n");
301 #endif
302 lppop2 = PopupMenuGetWindowAndStorage(lppop->hWndParent, &wndPtr);
303 if (lppop2 == NULL) break;
304 HideAllSubPopupMenu(lppop2);
305 break;
307 else {
308 #ifdef DEBUG_MENU
309 printf("VK_ESCAPE // Hide Root Popup !\n");
310 #endif
311 ShowWindow(hwnd, SW_HIDE);
312 MenuHasFocus = FALSE;
314 break;
315 default:
316 if (wParam >= 'a' && wParam <= 'z') wParam -= 'a' - 'A';
317 lpitem = MenuFindItemBySelKey(lppop, wParam, &wRet);
318 if (lpitem != NULL) {
319 printf("ShortKey Found wRet=%d !\n", wRet);
320 MenuItemSelect(hwnd, lppop, wRet);
321 lppop->FocusedItem = wRet;
322 goto ProceedSPACE;
324 printf("ShortKey Not Found wParam=%04X wRet=%d lpitem=%08X !\n",
325 wParam, wRet, lpitem);
326 if (lppop->hWndParent != (HWND)NULL)
327 SendMessage(lppop->hWndParent, WM_MENUCHAR, wParam,
328 MAKELONG(0, 0));
329 else
330 SendMessage(lppop->ownerWnd, WM_MENUCHAR, wParam,
331 MAKELONG(0, 0));
332 break;
334 break;
335 case WM_PAINT:
336 #ifdef DEBUG_MENU
337 printf("PopupMenuWndProc // WM_PAINT received !\n");
338 #endif
339 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
340 if (lppop == NULL) break;
341 if (!lppop->BarFlag) {
342 PopupMenuCalcSize(hwnd);
343 StdDrawPopupMenu(hwnd);
345 break;
346 default:
347 return DefWindowProc(hwnd, message, wParam, lParam);
349 return 0;
353 BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop)
355 short x, y;
356 LPPOPUPMENU lppop2;
357 LPMENUITEM lpitem;
358 HMENU hSubMenu;
359 RECT rect;
360 lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
361 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
362 hSubMenu = (HMENU)lpitem->item_id;
363 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
364 if (lppop2 == NULL) return FALSE;
365 lppop2->hWndParent = hWnd;
366 GetClientRect(hWnd, &rect);
367 if (lppop->BarFlag) {
368 GetWindowRect(hWnd, &rect);
369 y = rect.top + lppop->rect.bottom;
370 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
371 rect.left + lpitem->rect.left,
372 y, 0, lppop->ownerWnd, (LPRECT)NULL);
374 else {
375 x = lppop->rect.right;
376 GetWindowRect(hWnd, &rect);
377 x += rect.left;
378 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
379 x, rect.top + lpitem->rect.top,
380 0, lppop->ownerWnd, (LPRECT)NULL);
382 GlobalUnlock(hSubMenu);
383 return TRUE;
385 if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
386 ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
387 MenuHasFocus = FALSE;
388 if (lppop->BarFlag) {
389 PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
391 else {
392 ShowWindow(lppop->hWnd, SW_HIDE);
393 SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
396 return TRUE;
401 BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
403 HDC hDC;
404 LPMENUITEM lpitem, lpitem2;
405 RECT rect;
406 HMENU hSubMenu;
407 WORD wRet;
408 LPPOPUPMENU lppop2;
409 if (lppop == NULL) return;
410 lpitem = MenuFindItem(lppop, x, y, &wRet);
411 #ifdef DEBUG_MENU
412 printf("MenuButtonDown hWnd=%04X x=%d y=%d // wRet=%d lpitem=%08X !\n",
413 hWnd, x, y, wRet, lpitem);
414 #endif
415 if (lpitem != NULL) {
416 MenuItemSelect(hWnd, lppop, wRet);
417 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
418 hSubMenu = (HMENU)lpitem->item_id;
419 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
420 if (lppop2 == NULL) return;
421 lppop2->hWndParent = hWnd;
422 if (lppop->BarFlag) {
423 GetWindowRect(hWnd, &rect);
424 y = rect.top + lppop->rect.bottom;
425 ReleaseCapture();
426 if (MenuHasFocus) {
427 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
428 rect.left + lpitem->rect.left,
429 y, 0, lppop->ownerWnd, (LPRECT)NULL);
431 else {
432 MenuHasFocus = TRUE;
433 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
434 rect.left + lpitem->rect.left,
435 y, 0, lppop->ownerWnd, (LPRECT)NULL);
436 MenuHasFocus = FALSE;
437 MenuFocusLoop(hWnd, lppop);
438 return TRUE;
441 else {
442 x = lppop->rect.right;
443 GetWindowRect(hWnd, &rect);
444 x += rect.left;
445 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
446 x, rect.top + lpitem->rect.top,
447 0, lppop->ownerWnd, (LPRECT)NULL);
449 GlobalUnlock(hSubMenu);
450 return TRUE;
452 if (lppop->BarFlag && !MenuHasFocus) {
453 MenuFocusLoop(hWnd, lppop);
455 return TRUE;
457 printf("MenuButtonDown // x=%d y=%d // Not Found !\n", x, y);
458 MenuHasFocus = FALSE;
459 ShowWindow(lppop->hWnd, SW_HIDE);
460 return FALSE;
465 void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
467 HDC hDC;
468 LPMENUITEM lpitem, lpitem2;
469 RECT rect;
470 HMENU hSubMenu;
471 WORD wRet;
472 LPPOPUPMENU lppop2;
473 if (lppop == NULL) return;
474 lpitem = MenuFindItem(lppop, x, y, &wRet);
475 #ifdef DEBUG_MENU
476 printf("MenuButtonUp // x=%d y=%d // wRet=%d lpitem=%08X !\n",
477 x, y, wRet, lpitem);
478 #endif
479 if (lpitem != NULL) {
480 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
481 return;
483 if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
484 ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
485 MenuHasFocus = FALSE;
486 if (lppop->BarFlag) {
487 PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
489 else {
490 ShowWindow(lppop->hWnd, SW_HIDE);
491 SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
493 return;
496 if (lppop->FocusedItem != (WORD)-1) {
497 MenuItemSelect(hWnd, lppop, lppop->FocusedItem);
503 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y)
505 HDC hDC;
506 RECT rect;
507 HMENU hSubMenu;
508 LPMENUITEM lpitem, lpitem2;
509 LPPOPUPMENU lppop2;
510 WORD wRet;
511 /* if ((wParam & MK_LBUTTON) != 0) { */
512 if (GetKeyState(VK_LBUTTON) != 0) {
513 lpitem = MenuFindItem(lppop, x, y, &wRet);
514 #ifdef DEBUG_MENU
515 printf("MenuMouseMove // x=%d y=%d // wRet=%d lpitem=%08X !\n",
516 x, y, wRet, lpitem);
517 #endif
518 if ((lpitem != NULL) && (lppop->FocusedItem != wRet)) {
519 lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
520 hDC = GetWindowDC(hWnd);
521 if ((lpitem2->item_flags & MF_POPUP) == MF_POPUP) {
522 HideAllSubPopupMenu(lppop);
524 MenuItemSelect(hWnd, lppop, wRet);
525 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
526 hSubMenu = (HMENU)lpitem->item_id;
527 lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
528 if (lppop2 == NULL) {
529 ReleaseDC(hWnd, hDC);
530 return;
532 if (lppop->BarFlag) {
533 lppop2->hWndParent = hWnd;
534 GetWindowRect(hWnd, &rect);
535 rect.top += lppop->rect.bottom;
536 TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
537 rect.left + lpitem->rect.left, rect.top,
538 0, lppop->ownerWnd, (LPRECT)NULL);
540 GlobalUnlock(hSubMenu);
542 ReleaseDC(hWnd, hDC);
548 void ResetHiliteFlags(LPPOPUPMENU lppop)
550 LPMENUITEM lpitem;
551 int i;
552 if (lppop == NULL) return;
553 lpitem = lppop->firstItem;
554 for(i = 0; i < lppop->nItems; i++) {
555 if (lpitem == NULL) return;
556 lpitem->item_flags &= MF_HILITE ^ 0xFFFF;
557 lpitem = (LPMENUITEM)lpitem->next;
562 void MenuItemSelect0(HWND hWnd, LPPOPUPMENU lppop,
563 LPMENUITEM lpitem, WORD wIndex)
565 LPMENUITEM lpprev;
566 if (lppop == NULL) return;
567 if (lppop->FocusedItem != (WORD)-1) {
568 lpprev = GetMenuItemPtr(lppop, lppop->FocusedItem);
569 if (lpprev != NULL) {
570 lpprev->item_flags &= MF_HILITE ^ 0xFFFF;
571 if ((lpprev->item_flags & MF_POPUP) == MF_POPUP)
572 HideAllSubPopupMenu(lppop);
573 if (lppop->BarFlag)
574 DrawMenuBar(hWnd);
575 else {
576 InvalidateRect(hWnd, &lpprev->rect, TRUE);
577 UpdateWindow(hWnd);
581 lppop->FocusedItem = wIndex;
582 if (lpitem == NULL || wIndex == (WORD)-1) {
583 ResetHiliteFlags(lppop);
584 if (lppop->BarFlag) DrawMenuBar(hWnd);
586 else {
587 lpitem->item_flags |= MF_HILITE;
588 if (lppop->BarFlag)
589 DrawMenuBar(hWnd);
590 else {
591 InvalidateRect(hWnd, &lpitem->rect, TRUE);
592 UpdateWindow(hWnd);
595 SendMessage(hWnd, WM_MENUSELECT, lpitem->item_id,
596 MAKELONG(0, lpitem->item_flags));
600 void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex)
602 LPMENUITEM lpitem;
603 lpitem = GetMenuItemPtr(lppop, wIndex);
604 MenuItemSelect0(hWnd, lppop, lpitem, wIndex);
608 LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr)
610 WND *Ptr;
611 LPPOPUPMENU lppop;
612 *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
613 if (Ptr == 0) {
614 printf("PopupMenuGetWindowAndStorage // Bad Window handle !\n");
615 return NULL;
617 lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
618 if (lppop == NULL) {
619 lppop = (LPPOPUPMENU) GlobalLock(Ptr->wIDmenu);
620 if (lppop == NULL) {
621 printf("PopupMenuGetWindowAndStorage // Bad Menu Handle !\n");
622 return NULL;
625 return lppop;
629 LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd)
631 WND *Ptr;
632 LPPOPUPMENU lppop;
633 Ptr = WIN_FindWndPtr(hwnd);
634 if (Ptr == 0) {
635 printf("Bad Window handle on PopupMenu !\n");
636 return 0;
638 lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
639 return lppop;
643 void SetMenuLogicalParent(HMENU hMenu, HWND hWnd)
645 LPPOPUPMENU lppop;
646 lppop = (LPPOPUPMENU)GlobalLock(hMenu);
647 lppop->hWndParent = hWnd;
648 GlobalUnlock(hMenu);
652 void StdDrawPopupMenu(HWND hwnd)
654 WND *wndPtr;
655 LPPOPUPMENU lppop;
656 LPMENUITEM lpitem;
657 PAINTSTRUCT ps;
658 HBRUSH hBrush;
659 HPEN hOldPen;
660 HWND hWndParent;
661 HDC hDC, hMemDC;
662 RECT rect, rect2, rect3;
663 DWORD OldTextColor;
664 int OldBkMode;
665 HFONT hOldFont;
666 HBITMAP hBitMap;
667 BITMAP bm;
668 UINT i, x;
669 hDC = BeginPaint(hwnd, &ps);
670 if (!IsWindowVisible(hwnd)) {
671 EndPaint(hwnd, &ps);
672 return;
674 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
675 if (lppop == NULL) goto EndOfPaint;
676 hBrush = GetStockObject(WHITE_BRUSH);
677 GetClientRect(hwnd, &rect);
678 GetClientRect(hwnd, &rect2);
679 FillRect(hDC, &rect, hBrush);
680 FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
681 if (lppop->nItems == 0) goto EndOfPaint;
682 lpitem = lppop->firstItem;
683 if (lpitem == NULL) goto EndOfPaint;
684 for(i = 0; i < lppop->nItems; i++) {
685 CopyRect(&rect2, &lpitem->rect);
686 if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
687 hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
688 MoveTo(hDC, rect2.left, rect2.top + 1);
689 LineTo(hDC, rect2.right, rect2.top + 1);
690 SelectObject(hDC, hOldPen);
692 if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
693 hMemDC = CreateCompatibleDC(hDC);
694 if (lpitem->hCheckBit == 0) {
695 SelectObject(hMemDC, hStdCheck);
696 GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
698 else {
699 SelectObject(hMemDC, lpitem->hCheckBit);
700 GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
702 BitBlt(hDC, rect2.left, rect2.top + 1,
703 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
704 DeleteDC(hMemDC);
706 else {
707 if (lpitem->hUnCheckBit != 0) {
708 hMemDC = CreateCompatibleDC(hDC);
709 SelectObject(hMemDC, lpitem->hUnCheckBit);
710 GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
711 BitBlt(hDC, rect2.left, rect2.top + 1,
712 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
713 DeleteDC(hMemDC);
716 if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
717 hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
718 rect2.left += lppop->CheckWidth;
719 hMemDC = CreateCompatibleDC(hDC);
720 SelectObject(hMemDC, hBitMap);
721 GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
722 BitBlt(hDC, rect2.left, rect2.top,
723 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
724 DeleteDC(hMemDC);
725 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
726 InvertRect(hDC, &lpitem->rect);
728 if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
729 ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
730 ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
731 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
732 OldBkMode = SetBkMode(hDC, TRANSPARENT);
733 if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
734 OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
735 else {
736 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
737 OldTextColor = SetTextColor(hDC, 0x00FFFFFFL);
738 else
739 OldTextColor = SetTextColor(hDC, 0x00000000L);
741 CopyRect(&rect3, &lpitem->rect);
742 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
743 FillRect(hDC, &rect3, GetStockObject(BLACK_BRUSH));
744 InflateRect(&rect3, 0, -2);
745 rect3.left += lppop->CheckWidth;
746 hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
747 if ((x = GetShortCutPos(lpitem->item_text)) != (WORD)-1) {
748 DrawText(hDC, lpitem->item_text, x, &rect3,
749 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
750 DrawText(hDC, &lpitem->item_text[x], -1, &rect3,
751 DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
753 else
754 DrawText(hDC, lpitem->item_text, -1, &rect3,
755 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
756 SelectObject(hDC, hOldPen);
757 SetTextColor(hDC, OldTextColor);
758 SetBkMode(hDC, OldBkMode);
759 SelectObject(hDC, hOldFont);
760 CopyRect(&rect2, &lpitem->rect);
762 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
763 CopyRect(&rect3, &lpitem->rect);
764 rect3.left = rect3.right - lppop->PopWidth;
765 hMemDC = CreateCompatibleDC(hDC);
766 SelectObject(hMemDC, hStdMnArrow);
767 GetObject(hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm);
768 BitBlt(hDC, rect3.left, rect3.top + 1,
769 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
770 DeleteDC(hMemDC);
772 if (lpitem->next == NULL) goto EndOfPaint;
773 lpitem = (LPMENUITEM)lpitem->next;
775 EndOfPaint:
776 EndPaint( hwnd, &ps );
781 void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop,
782 BOOL suppress_draw)
784 LPMENUITEM lpitem;
785 HBRUSH hBrush;
786 HPEN hOldPen;
787 HDC hMemDC;
788 RECT rect, rect2, rect3;
789 HFONT hOldFont;
790 DWORD OldTextColor;
791 int OldBkMode;
792 HBITMAP hBitMap;
793 BITMAP bm;
794 UINT i, textwidth;
795 if (lppop == NULL || lprect == NULL) return;
796 #ifdef DEBUG_MENU
797 printf("StdDrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop);
798 #endif
799 MenuBarCalcSize(hDC, lprect, lppop);
800 if (suppress_draw)
801 return;
803 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
804 hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
805 hBrush = GetStockObject(WHITE_BRUSH);
806 CopyRect(&rect, lprect);
807 FillRect(hDC, &rect, hBrush);
808 FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
809 if (lppop->nItems == 0) goto EndOfPaint;
810 lpitem = lppop->firstItem;
811 if (lpitem == NULL) goto EndOfPaint;
812 for(i = 0; i < lppop->nItems; i++) {
813 CopyRect(&rect2, &lpitem->rect);
814 if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
815 hMemDC = CreateCompatibleDC(hDC);
816 if (lpitem->hCheckBit == 0) {
817 SelectObject(hMemDC, hStdCheck);
818 GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
820 else {
821 SelectObject(hMemDC, lpitem->hCheckBit);
822 GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
824 BitBlt(hDC, rect2.left, rect2.top + 1,
825 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
826 DeleteDC(hMemDC);
828 else {
829 if (lpitem->hUnCheckBit != 0) {
830 hMemDC = CreateCompatibleDC(hDC);
831 SelectObject(hMemDC, lpitem->hUnCheckBit);
832 GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
833 BitBlt(hDC, rect2.left, rect2.top + 1,
834 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
835 DeleteDC(hMemDC);
838 if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
839 hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
840 hMemDC = CreateCompatibleDC(hDC);
841 SelectObject(hMemDC, hBitMap);
842 GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
843 BitBlt(hDC, rect2.left, rect2.top,
844 bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
845 DeleteDC(hMemDC);
847 if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
848 ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
849 ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
850 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
851 OldBkMode = SetBkMode(hDC, TRANSPARENT);
852 if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
853 OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
854 else {
855 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
856 OldTextColor = SetTextColor(hDC, 0x00FFFFFFL);
857 else
858 OldTextColor = SetTextColor(hDC, 0x00000000L);
860 if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
861 FillRect(hDC, &rect2, GetStockObject(BLACK_BRUSH));
862 DrawText(hDC, lpitem->item_text, -1, &rect2,
863 DT_LEFT | DT_VCENTER | DT_SINGLELINE);
864 SetTextColor(hDC, OldTextColor);
865 SetBkMode(hDC, OldBkMode);
866 SelectObject(hDC, hOldFont);
868 if (lpitem->next == NULL) goto EndOfPaint;
869 lpitem = (LPMENUITEM)lpitem->next;
871 EndOfPaint:
872 SelectObject(hDC, hOldPen);
873 SelectObject(hDC, hOldFont);
878 LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet)
880 LPMENUITEM lpitem;
881 UINT i;
882 if (lpRet != NULL) *lpRet = 0;
883 if (lppop == NULL) return NULL;
884 if (lppop->nItems == 0) return NULL;
885 lpitem = lppop->firstItem;
886 for(i = 0; i < lppop->nItems; i++) {
887 if (lpitem == NULL) return NULL;
888 #ifdef DEBUG_MENUFINDITEM
889 printf("FindItem // left=%d top=%d right=%d bottom=%d\n",
890 lpitem->rect.left, lpitem->rect.top,
891 lpitem->rect.right, lpitem->rect.bottom);
892 #endif
893 if (x > lpitem->rect.left && x < lpitem->rect.right &&
894 y > lpitem->rect.top && y < lpitem->rect.bottom) {
895 if (lpRet != NULL) *lpRet = i;
896 return lpitem;
898 lpitem = (LPMENUITEM)lpitem->next;
900 return NULL;
904 LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet)
906 LPMENUITEM lpitem;
907 UINT i;
908 if (lppop == NULL) return NULL;
910 if (lppop->nItems == 0) return NULL;
911 lpitem = lppop->firstItem;
912 for(i = 0; i < lppop->nItems; i++) {
913 if (lpitem == NULL) return NULL;
914 #ifdef DEBUG_MENUFINDITEM
915 printf("FindItemBySelKey // key=%04X lpitem->sel_key=%04X\n",
916 key, lpitem->sel_key);
917 #endif
918 if (key == lpitem->sel_key) {
919 if (lpRet != NULL) *lpRet = i;
920 return lpitem;
922 lpitem = (LPMENUITEM)lpitem->next;
924 return NULL;
928 void PopupMenuCalcSize(HWND hwnd)
930 WND *wndPtr;
931 LPPOPUPMENU lppop;
932 LPMENUITEM lpitem;
933 HDC hDC;
934 RECT rect;
935 HBITMAP hBitMap;
936 BITMAP bm;
937 HFONT hOldFont;
938 UINT i, OldWidth, TempWidth;
939 DWORD dwRet;
940 #ifdef DEBUG_MENUCALC
941 printf("PopupMenuCalcSize hWnd=%04X !\n", hWnd);
942 #endif
943 lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
944 if (lppop == NULL) return;
945 if (lppop->nItems == 0) return;
946 hDC = GetDC(hwnd);
947 lppop->Width = 20;
948 lppop->CheckWidth = lppop->PopWidth = 0;
949 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
950 CalcAGAIN:
951 OldWidth = lppop->Width;
952 SetRect(&rect, 1, 1, OldWidth, 0);
953 lpitem = lppop->firstItem;
954 for(i = 0; i < lppop->nItems; i++) {
955 if (lpitem == NULL) break;
956 #ifdef DEBUG_MENUCALC
957 printf("PopupMenuCalcSize item #%d !\n", i);
958 #endif
959 rect.right = rect.left + lppop->Width;
960 if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
961 if (lpitem->hCheckBit != 0)
962 GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
963 else
964 GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
965 lppop->CheckWidth = max(lppop->CheckWidth, bm.bmWidth);
967 else {
968 if (lpitem->hUnCheckBit != 0) {
969 GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
970 lppop->CheckWidth = max(lppop->CheckWidth, bm.bmWidth);
973 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
974 GetObject(hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm);
975 lppop->PopWidth = max(lppop->PopWidth, bm.bmWidth);
977 if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
978 rect.bottom = rect.top + 3;
980 if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
981 hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
982 GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
983 rect.bottom = rect.top + bm.bmHeight;
984 lppop->Width = max(lppop->Width, bm.bmWidth);
986 if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
987 ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
988 ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
989 dwRet = GetTextExtent(hDC, (char *)lpitem->item_text,
990 strlen((char *)lpitem->item_text));
991 rect.bottom = rect.top + HIWORD(dwRet);
992 InflateRect(&rect, 0, 2);
993 TempWidth = LOWORD(dwRet);
994 if (GetShortCutPos(lpitem->item_text) != (WORD)-1)
995 TempWidth += 15;
996 TempWidth += lppop->CheckWidth;
997 TempWidth += lppop->PopWidth;
998 lppop->Width = max(lppop->Width, TempWidth);
1000 CopyRect(&lpitem->rect, &rect);
1001 rect.top = rect.bottom;
1002 lpitem = (LPMENUITEM)lpitem->next;
1004 if (OldWidth < lppop->Width) goto CalcAGAIN;
1005 lppop->Height = rect.bottom;
1006 SetRect(&lppop->rect, 1, 1, lppop->Width, lppop->Height);
1007 #ifdef DEBUG_MENUCALC
1008 printf("PopupMenuCalcSize w=%d h=%d !\n", lppop->Width, lppop->Height);
1009 #endif
1010 SelectObject(hDC, hOldFont);
1011 ReleaseDC(hwnd, hDC);
1016 void MenuBarCalcSize(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop)
1018 LPMENUITEM lpitem;
1019 RECT rect;
1020 HBITMAP hBitMap;
1021 BITMAP bm;
1022 HFONT hOldFont;
1023 UINT i, OldHeight;
1024 DWORD dwRet;
1025 if (lppop == NULL) return;
1026 if (lppop->nItems == 0) return;
1027 #ifdef DEBUG_MENUCALC
1028 printf("MenuBarCalcSize left=%d top=%d right=%d bottom=%d !\n",
1029 lprect->left, lprect->top, lprect->right, lprect->bottom);
1030 #endif
1031 hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
1032 lppop->Height = lprect->bottom - lprect->top;
1033 CalcAGAIN:
1034 OldHeight = lppop->Height;
1035 SetRect(&rect, lprect->left, lprect->top, 0, lprect->top + OldHeight);
1036 lpitem = lppop->firstItem;
1037 for(i = 0; i < lppop->nItems; i++) {
1038 if (lpitem == NULL) break;
1039 rect.bottom = lprect->top + lppop->Height;
1040 if (rect.right > lprect->right)
1041 SetRect(&rect, lprect->left, rect.bottom,
1042 0, rect.bottom + SYSMETRICS_CYMENU);
1043 if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
1044 hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
1045 GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
1046 rect.right = rect.left + bm.bmWidth;
1047 lppop->Height = max(lppop->Height, bm.bmHeight);
1049 if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
1050 ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
1051 ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
1052 dwRet = GetTextExtent(hDC, (char *)lpitem->item_text,
1053 strlen((char *)lpitem->item_text));
1054 rect.right = rect.left + LOWORD(dwRet) + 10;
1055 dwRet = max(SYSMETRICS_CYMENU, (HIWORD(dwRet) + 6));
1056 lppop->Height = max(lppop->Height, (WORD)dwRet);
1058 CopyRect(&lpitem->rect, &rect);
1059 rect.left = rect.right;
1060 lpitem = (LPMENUITEM)lpitem->next;
1062 if (OldHeight < lppop->Height) goto CalcAGAIN;
1063 lppop->Width = rect.right;
1064 lprect->bottom = lprect->top + lppop->Height;
1065 CopyRect(&lppop->rect, lprect);
1066 #ifdef DEBUG_MENUCALC
1067 printf("MenuBarCalcSize w=%d h=%d !\n", lppop->Width, lppop->Height);
1068 #endif
1069 SelectObject(hDC, hOldFont);
1074 /***********************************************************************
1075 * FindMenuItem
1077 LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags)
1079 LPPOPUPMENU menu;
1080 LPMENUITEM lpitem;
1081 int i;
1082 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1083 if (menu == NULL) {
1084 GlobalUnlock(hMenu);
1085 return FALSE;
1087 lpitem = menu->firstItem;
1088 if (wFlags & MF_BYPOSITION) {
1089 for (i = 0; i < nPos; i++, lpitem = lpitem->next)
1090 if (lpitem == NULL) return NULL;
1092 else {
1093 for (i = 0; i < menu->nItems && lpitem != NULL; i++) {
1094 if (lpitem->item_id == nPos) return lpitem;
1095 lpitem = lpitem->next;
1097 return NULL;
1099 return lpitem;
1103 LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos)
1105 LPMENUITEM lpitem;
1106 int i;
1107 if (menu == NULL) return NULL;
1108 lpitem = menu->firstItem;
1109 for (i = 0; i < menu->nItems; i++) {
1110 if (lpitem == NULL) return NULL;
1111 if (i == nPos) return(lpitem);
1112 lpitem = (LPMENUITEM)lpitem->next;
1114 return NULL;
1118 WORD GetSelectionKey(LPSTR str)
1120 int i;
1121 WORD sel_key;
1122 for (i = 0; i < strlen(str); i++) {
1123 if (str[i] == '&' && str[i + 1] != '&') {
1124 sel_key = str[i + 1];
1125 if (sel_key >= 'a' && sel_key <= 'z') sel_key -= 'a' - 'A';
1126 #ifdef DEBUG_MENU
1127 printf("GetSelectionKey // %04X\n", sel_key);
1128 #endif
1129 return sel_key;
1132 #ifdef DEBUG_MENU
1133 printf("GetSelectionKey NULL \n");
1134 #endif
1135 return 0;
1140 LPSTR GetShortCutString(LPSTR str)
1142 int i;
1143 LPSTR str2;
1144 for (i = 0; i < strlen(str); i++) {
1145 if (str[i] == '\t' && str[i + 1] != '\t') {
1146 str2 = &str[i + 1];
1147 #ifdef DEBUG_MENUSHORTCUT
1148 printf("GetShortCutString // '%s' \n", str2);
1149 #endif
1150 return str2;
1153 #ifdef DEBUG_MENUSHORTCUT
1154 printf("GetShortCutString NULL \n");
1155 #endif
1156 return NULL;
1161 WORD GetShortCutPos(LPSTR str)
1163 int i;
1164 for (i = 0; i < strlen(str); i++) {
1165 if (str[i] == '\t' && str[i + 1] != '\t') {
1166 #ifdef DEBUG_MENUSHORTCUT
1167 printf("GetShortCutPos = %d \n", i);
1168 #endif
1169 return i;
1172 #ifdef DEBUG_MENUSHORTCUT
1173 printf("GetShortCutString NULL \n");
1174 #endif
1175 return -1;
1180 BOOL HideAllSubPopupMenu(LPPOPUPMENU menu)
1182 LPPOPUPMENU submenu;
1183 LPMENUITEM lpitem;
1184 BOOL someClosed = FALSE;
1185 int i;
1186 if (menu == NULL) return;
1187 lpitem = menu->firstItem;
1188 for (i = 0; i < menu->nItems; i++) {
1189 if (lpitem == NULL) return;
1190 if (lpitem->item_flags & MF_POPUP) {
1191 submenu = (LPPOPUPMENU) GlobalLock((HMENU)lpitem->item_id);
1192 if (submenu != NULL) {
1193 if (IsWindowVisible(submenu->hWnd)) {
1194 ShowWindow(submenu->hWnd, SW_HIDE);
1195 someClosed = TRUE;
1197 GlobalUnlock((HMENU)lpitem->item_id);
1200 lpitem = (LPMENUITEM)lpitem->next;
1202 return someClosed;
1208 /**********************************************************************
1209 * ChangeMenu [USER.153]
1211 BOOL ChangeMenu(HMENU hMenu, WORD nPos, LPSTR lpNewItem,
1212 WORD wItemID, WORD wFlags)
1214 if (wFlags & MF_APPEND)
1215 return AppendMenu(hMenu, wFlags, wItemID, lpNewItem);
1216 if (wFlags & MF_DELETE)
1217 return DeleteMenu(hMenu, wItemID, wFlags);
1218 if (wFlags & MF_INSERT)
1219 return InsertMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
1220 if (wFlags & MF_CHANGE)
1221 return ModifyMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
1222 if (wFlags & MF_REMOVE)
1223 return RemoveMenu(hMenu, wItemID, wFlags);
1224 return FALSE;
1228 /**********************************************************************
1229 * CheckMenuItem [USER.154]
1231 BOOL CheckMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
1233 WND *wndPtr;
1234 LPPOPUPMENU menu;
1235 LPMENUITEM lpitem;
1236 int i;
1237 #ifdef DEBUG_MENU
1238 printf("CheckMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
1239 #endif
1240 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1241 if (menu == NULL) return FALSE;
1242 lpitem = menu->firstItem;
1243 for (i = 0; i < menu->nItems; i++) {
1244 if (lpitem == NULL) break;
1245 if (i == wItemID) {
1246 if (wFlags && MF_CHECKED)
1247 lpitem->item_flags |= MF_CHECKED;
1248 else
1249 lpitem->item_flags &= ((WORD)-1 ^ MF_CHECKED);
1250 GlobalUnlock(hMenu);
1251 return(TRUE);
1253 lpitem = (LPMENUITEM)lpitem->next;
1255 GlobalUnlock(hMenu);
1256 return FALSE;
1260 /**********************************************************************
1261 * EnableMenuItem [USER.155]
1263 BOOL EnableMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
1265 WND *wndPtr;
1266 LPPOPUPMENU menu;
1267 LPMENUITEM lpitem;
1268 int i;
1269 #ifdef DEBUG_MENU
1270 printf("EnableMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
1271 #endif
1272 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1273 if (menu == NULL) return FALSE;
1274 lpitem = menu->firstItem;
1275 for (i = 0; i < menu->nItems; i++) {
1276 if (lpitem == NULL) break;
1277 if (i == wItemID) {
1278 if (wFlags && MF_DISABLED)
1279 lpitem->item_flags |= MF_DISABLED;
1280 else
1281 lpitem->item_flags &= ((WORD)-1 ^ MF_DISABLED);
1282 GlobalUnlock(hMenu);
1283 return(TRUE);
1285 lpitem = (LPMENUITEM)lpitem->next;
1287 GlobalUnlock(hMenu);
1288 return FALSE;
1292 /**********************************************************************
1293 * InsertMenu [USER.410]
1295 BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
1297 WND *wndPtr;
1298 LPPOPUPMENU menu;
1299 HANDLE hNewItem;
1300 LPMENUITEM lpitem, lpitem2;
1301 int i;
1302 #ifdef DEBUG_MENU
1303 if (wFlags & MF_STRING)
1304 printf("InsertMenu (%04X, %04X, %04X, '%s') !\n",
1305 hMenu, wFlags, wItemID, lpNewItem);
1306 else
1307 printf("InsertMenu (%04X, %04X, %04X, %04X, %08X) !\n",
1308 hMenu, nPos, wFlags, wItemID, lpNewItem);
1309 #endif
1310 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1311 if (menu == NULL) return FALSE;
1312 lpitem = FindMenuItem(hMenu, nPos, wFlags);
1313 if (lpitem == NULL) lpitem = menu->firstItem;
1314 hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
1315 if (hNewItem == 0) {
1316 GlobalUnlock(hMenu);
1317 return FALSE;
1319 lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
1320 if (lpitem2 == NULL) {
1321 GlobalFree(hNewItem);
1322 GlobalUnlock(hMenu);
1323 return FALSE;
1325 lpitem2->hItem = hNewItem;
1326 lpitem2->item_flags = wFlags;
1327 lpitem2->item_id = wItemID;
1328 if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1329 MF_MENUBREAK | MF_SEPARATOR))) {
1330 lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
1331 lpitem2->item_text = GlobalLock(lpitem2->hText);
1332 if (lpitem2->item_text != NULL)
1333 strcpy(lpitem2->item_text, lpNewItem);
1334 else {
1335 printf("InsertMenu // Bad Alloc !\n");
1336 return FALSE;
1338 lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
1340 else {
1341 lpitem2->item_text = lpNewItem;
1343 if (lpitem == NULL) {
1344 menu->firstItem = lpitem2;
1345 lpitem2->prev = NULL;
1346 lpitem2->next = NULL;
1348 else {
1349 lpitem2->prev = lpitem;
1350 lpitem2->next = lpitem->next;
1351 if (lpitem2->next != NULL) lpitem2->next->prev = lpitem2;
1352 lpitem->next = lpitem2;
1354 menu->nItems++;
1355 GlobalUnlock(hMenu);
1356 return TRUE;
1360 /**********************************************************************
1361 * AppendMenu [USER.411]
1363 BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
1365 WND *wndPtr;
1366 LPPOPUPMENU menu;
1367 HANDLE hNewItem;
1368 LPMENUITEM lpitem, lpitem2;
1369 #ifdef DEBUG_MENU
1370 if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
1371 printf("AppendMenu (%04X, %04X, %04X, '%s') !\n",
1372 hMenu, wFlags, wItemID, lpNewItem);
1373 else
1374 printf("AppendMenu (%04X, %04X, %04X, %08X) !\n",
1375 hMenu, wFlags, wItemID, lpNewItem);
1376 #endif
1377 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1378 if (menu == NULL) return FALSE;
1379 lpitem = menu->firstItem;
1380 if (lpitem != NULL) {
1381 while (lpitem->next != NULL) {
1382 lpitem = (LPMENUITEM)lpitem->next;
1385 hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
1386 if (hNewItem == 0) {
1387 GlobalUnlock(hMenu);
1388 return FALSE;
1390 lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
1391 lpitem2->hItem = hNewItem;
1392 if (lpitem2 == NULL) {
1393 GlobalFree(hNewItem);
1394 GlobalUnlock(hMenu);
1395 return FALSE;
1397 lpitem2->item_flags = wFlags;
1398 lpitem2->item_id = wItemID;
1399 if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1400 MF_MENUBREAK | MF_SEPARATOR))) {
1401 lpitem2->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
1402 lpitem2->item_text = GlobalLock(lpitem2->hText);
1403 if (lpitem2->item_text != NULL)
1404 strcpy(lpitem2->item_text, lpNewItem);
1405 else {
1406 printf("AppendMenu // Bad Alloc !\n");
1407 return FALSE;
1409 lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
1411 else {
1412 lpitem2->item_text = lpNewItem;
1414 if (lpitem == NULL)
1415 menu->firstItem = lpitem2;
1416 else
1417 lpitem->next = lpitem2;
1418 lpitem2->prev = lpitem;
1419 lpitem2->next = NULL;
1420 lpitem2->hCheckBit = (HBITMAP)NULL;
1421 lpitem2->hUnCheckBit = (HBITMAP)NULL;
1422 menu->nItems++;
1423 GlobalUnlock(hMenu);
1424 return TRUE;
1428 /**********************************************************************
1429 * RemoveMenu [USER.412]
1431 BOOL RemoveMenu(HMENU hMenu, WORD nPos, WORD wFlags)
1433 WND *wndPtr;
1434 LPPOPUPMENU menu;
1435 LPMENUITEM lpitem;
1436 int i;
1437 #ifdef DEBUG_MENU
1438 printf("RemoveMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
1439 #endif
1440 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1441 if (menu == NULL) return FALSE;
1442 lpitem = menu->firstItem;
1443 for (i = 0; i < menu->nItems; i++) {
1444 if (lpitem == NULL) break;
1445 if (i == nPos) {
1446 lpitem->prev->next = lpitem->next;
1447 lpitem->next->prev = lpitem->prev;
1448 if (!(lpitem->item_flags &
1449 (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1450 MF_MENUBREAK | MF_SEPARATOR))) {
1451 GlobalUnlock(lpitem->hText);
1452 GlobalFree(lpitem->hText);
1454 GlobalFree(lpitem->hItem);
1455 GlobalUnlock(hMenu);
1456 return TRUE;
1458 lpitem = (LPMENUITEM)lpitem->next;
1459 printf("RemoveMenu // during loop items !\n");
1461 printf("RemoveMenu // after loop items !\n");
1462 GlobalUnlock(hMenu);
1463 return FALSE;
1467 /**********************************************************************
1468 * DeleteMenu [USER.413]
1470 BOOL DeleteMenu(HMENU hMenu, WORD nPos, WORD wFlags)
1472 LPPOPUPMENU menu;
1473 LPMENUITEM lpitem;
1474 int i;
1475 #ifdef DEBUG_MENU
1476 printf("DeleteMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
1477 #endif
1478 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1479 if (menu == NULL) {
1480 GlobalUnlock(hMenu);
1481 return FALSE;
1483 lpitem = FindMenuItem(hMenu, nPos, wFlags);
1484 if (lpitem != NULL) {
1485 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
1486 DestroyMenu((HMENU)lpitem->item_id);
1487 if (!(lpitem->item_flags &
1488 (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1489 MF_MENUBREAK | MF_SEPARATOR))) {
1490 GlobalUnlock(lpitem->hText);
1491 GlobalFree(lpitem->hText);
1493 if (lpitem->prev) lpitem->prev->next = lpitem->next;
1494 if (lpitem->next) lpitem->next->prev = lpitem->prev;
1495 GlobalFree(lpitem->hItem);
1496 GlobalUnlock(hMenu);
1497 return TRUE;
1499 GlobalUnlock(hMenu);
1500 return FALSE;
1504 /**********************************************************************
1505 * ModifyMenu [USER.414]
1507 BOOL ModifyMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
1509 WND *wndPtr;
1510 LPPOPUPMENU menu;
1511 LPMENUITEM lpitem;
1512 int i;
1513 #ifdef DEBUG_MENU
1514 printf("ModifyMenu (%04X, %04X, %04X, %04X, %08X) !\n",
1515 hMenu, nPos, wFlags, wItemID, lpNewItem);
1516 #endif
1517 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1518 if (menu == NULL) return FALSE;
1519 lpitem = menu->firstItem;
1520 for (i = 0; i < menu->nItems; i++) {
1521 if (lpitem == NULL) break;
1522 if (i == nPos) {
1523 lpitem->item_flags = wFlags;
1524 lpitem->item_id = wItemID;
1525 if (!(lpitem->item_flags &
1526 (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK |
1527 MF_MENUBREAK | MF_SEPARATOR))) {
1528 GlobalUnlock(lpitem->hText);
1529 GlobalFree(lpitem->hText);
1530 lpitem->hText = GlobalAlloc(GMEM_MOVEABLE, strlen(lpNewItem) + 1);
1531 lpitem->item_text = GlobalLock(lpitem->hText);
1532 printf("ModifyMenu %08X %08X '%s') !\n",
1533 lpitem->item_text, lpNewItem, lpNewItem);
1534 if (lpitem->item_text != NULL)
1535 strcpy(lpitem->item_text, lpNewItem);
1536 else
1537 printf("ModifyMenu // Bad Alloc !\n");
1539 else
1540 lpitem->item_text = lpNewItem;
1541 GlobalUnlock(hMenu);
1542 return(TRUE);
1544 lpitem = (LPMENUITEM)lpitem->next;
1546 GlobalUnlock(hMenu);
1547 return FALSE;
1551 /**********************************************************************
1552 * CreatePopupMenu [USER.415]
1554 HMENU CreatePopupMenu()
1556 HANDLE hItem;
1557 HMENU hMenu;
1558 LPPOPUPMENU menu;
1559 #ifdef DEBUG_MENU
1560 printf("CreatePopupMenu !\n");
1561 #endif
1562 hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
1563 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1564 if (menu == NULL) {
1565 GlobalFree(hMenu);
1566 return 0;
1568 menu->nItems = 0;
1569 menu->firstItem = NULL;
1570 menu->ownerWnd = 0;
1571 menu->hWndPrev = 0;
1572 menu->hWnd = 0;
1573 menu->hWndParent = 0;
1574 menu->MouseFlags = 0;
1575 menu->BarFlag = FALSE;
1576 menu->SysFlag = FALSE;
1577 menu->ChildFlag = TRUE;
1578 menu->Width = 100;
1579 menu->Height = 0;
1580 GlobalUnlock(hMenu);
1581 return hMenu;
1585 /**********************************************************************
1586 * TrackPopupMenu [USER.416]
1588 BOOL TrackPopupMenu(HMENU hMenu, WORD wFlags, short x, short y,
1589 short nReserved, HWND hWnd, LPRECT lpRect)
1591 WND *wndPtr;
1592 LPPOPUPMENU lppop;
1593 RECT rect;
1594 #ifdef DEBUG_MENU
1595 printf("TrackPopupMenu (%04X, %04X, %d, %d, %04X, %04X, %08X) !\n",
1596 hMenu, wFlags, x, y, nReserved, hWnd, lpRect);
1597 #endif
1598 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
1599 if (lppop == NULL) {
1600 printf("TrackPopupMenu // Bad menu handle %04X !\n", hMenu);
1601 return FALSE;
1603 wndPtr = WIN_FindWndPtr(hWnd);
1604 if (wndPtr == NULL) {
1605 printf("TrackPopupMenu // Bad window handle %04X !\n", hWnd);
1606 return FALSE;
1608 lppop->ownerWnd = hWnd;
1609 lppop->hWndPrev = GetFocus();
1610 if (lppop->hWnd == (HWND)NULL) {
1611 lppop->hWnd = CreateWindow("POPUPMENU", "", WS_POPUP | WS_VISIBLE,
1612 x, y, lppop->Width, lppop->Height, (HWND)NULL, 0,
1613 wndPtr->hInstance, (LPSTR)lppop);
1614 if (lppop->hWnd == 0) {
1615 printf("TrackPopupMenu // Can't create PopupMenu window !\n");
1616 return FALSE;
1619 else {
1620 ShowWindow(lppop->hWnd, SW_SHOW);
1622 if (!lppop->BarFlag) {
1623 PopupMenuCalcSize(lppop->hWnd);
1624 #ifdef DEBUG_MENU
1625 printf("TrackPopupMenu // x=%d y=%d Width=%d Height=%d\n",
1626 x, y, lppop->Width, lppop->Height);
1627 #endif
1628 SetWindowPos(lppop->hWnd, 0, x, y, lppop->Width + 2, lppop->Height,
1629 SWP_NOZORDER);
1631 SetFocus(lppop->hWnd);
1632 if (!MenuHasFocus) {
1633 #ifdef DEBUG_MENU
1634 printf("TrackPopupMenu // before MenuFocusLoop !\n");
1635 #endif
1636 MenuFocusLoop(hWnd, NULL);
1637 #ifdef DEBUG_MENU
1638 printf("TrackPopupMenu // after MenuFocusLoop !\n");
1639 #endif
1641 GlobalUnlock(hMenu);
1642 return TRUE;
1646 BOOL ActivateMenuBarFocus(HWND hWnd)
1648 WND *wndPtr;
1649 LPPOPUPMENU lpmenu;
1650 BOOL bRet;
1651 MSG msg;
1652 if (MenuHasFocus) return FALSE;
1653 wndPtr = WIN_FindWndPtr(hWnd);
1654 if (wndPtr == NULL) return FALSE;
1655 #ifdef DEBUG_MENU
1656 printf("ActivateMenuBarFocus (%04X) !\n", hWnd);
1657 #endif
1658 while((wndPtr->dwStyle & WS_CHILD) == WS_CHILD) {
1659 hWnd = GetParent(hWnd);
1660 printf("ActivateMenuBarFocus // next Parent=%04X !\n", hWnd);
1661 wndPtr = WIN_FindWndPtr(hWnd);
1662 if (wndPtr == NULL) return FALSE;
1664 if ((wndPtr->dwStyle & WS_CHILD) == 0 && wndPtr->wIDmenu != 0) {
1665 lpmenu = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
1666 if (lpmenu == NULL) return FALSE;
1667 lpmenu->hWndPrev = GetFocus();
1668 SetFocus(hWnd);
1669 MenuItemSelect(hWnd, lpmenu, 0);
1670 bRet = MenuFocusLoop(hWnd, lpmenu);
1671 GlobalUnlock(wndPtr->wIDmenu);
1672 return bRet;
1674 return FALSE;
1678 BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu)
1680 WND *wndPtr;
1681 MSG msg;
1682 #ifdef DEBUG_MENU
1683 printf("Enter in Menu Focus Loop !\n");
1684 #endif
1685 MenuHasFocus = TRUE;
1686 while(TRUE) {
1687 if (!MenuHasFocus) break;
1688 if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break;
1689 TranslateMessage(&msg);
1690 if (hWnd == msg.hwnd && lpmenu != NULL) {
1691 if ((msg.message == WM_SYSKEYDOWN && msg.wParam == VK_MENU) ||
1692 (msg.message == WM_CHAR && msg.wParam == VK_ESCAPE)) {
1693 HideAllSubPopupMenu(lpmenu);
1694 break;
1696 ScreenToClient(hWnd, &msg.pt);
1697 msg.pt.y += lpmenu->rect.bottom;
1698 switch(msg.message) {
1699 case WM_LBUTTONDOWN:
1700 case WM_NCLBUTTONDOWN:
1701 SetCapture(hWnd);
1702 MenuButtonDown(hWnd, lpmenu, msg.pt.x, msg.pt.y);
1703 break;
1704 case WM_LBUTTONUP:
1705 case WM_NCLBUTTONUP:
1706 MenuButtonUp(hWnd, lpmenu, msg.pt.x, msg.pt.y);
1707 ReleaseCapture();
1708 break;
1709 case WM_MOUSEMOVE:
1710 case WM_NCMOUSEMOVE:
1711 MenuMouseMove(hWnd, lpmenu, msg.wParam, msg.pt.x, msg.pt.y);
1712 break;
1713 case WM_KEYDOWN:
1714 case WM_KEYUP:
1715 case WM_CHAR:
1716 PopupMenuWndProc(hWnd, msg.message, msg.wParam, msg.lParam);
1717 default:
1718 DispatchMessage(&msg);
1721 else
1722 DispatchMessage(&msg);
1724 EndOfFocus:
1725 MenuHasFocus = FALSE;
1726 if (lpmenu != NULL) MenuItemSelect(hWnd, lpmenu, -1);
1727 #ifdef DEBUG_MENU
1728 printf("End of Menu Focus Loop !\n");
1729 #endif
1730 return TRUE;
1734 /**********************************************************************
1735 * NC_TrackSysMenu [Internal]
1737 void NC_TrackSysMenu(HWND hWnd)
1739 RECT rect;
1740 LPPOPUPMENU lpsys;
1741 WND *wndPtr = WIN_FindWndPtr(hWnd);
1742 #ifdef DEBUG_MENU
1743 printf("NC_TrackSysMenu hWnd=%04X !\n", hWnd);
1744 #endif
1745 if (!wndPtr) return;
1746 lpsys = (LPPOPUPMENU)GlobalLock(wndPtr->hSysMenu);
1747 #ifdef DEBUG_MENU
1748 printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
1749 #endif
1750 if (lpsys == NULL) return;
1751 #ifdef DEBUG_MENU
1752 printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
1753 #endif
1754 lpsys->BarFlag = FALSE;
1755 lpsys->SysFlag = TRUE;
1756 lpsys->ChildFlag = FALSE;
1757 lpsys->hWndParent = hWnd;
1758 if (!IsWindowVisible(lpsys->hWnd)) {
1759 GetWindowRect(hWnd, &rect);
1760 #ifdef DEBUG_MENU
1761 printf("NC_TrackSysMenu lpsys->hWnd=%04X !\n", lpsys->hWnd);
1762 #endif
1763 if (MenuHasFocus) {
1764 TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON,
1765 rect.left, rect.top + SYSMETRICS_CYSIZE,
1766 0, hWnd, (LPRECT)NULL);
1768 else {
1769 MenuHasFocus = TRUE;
1770 TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON,
1771 rect.left, rect.top + SYSMETRICS_CYSIZE,
1772 0, hWnd, (LPRECT)NULL);
1773 MenuHasFocus = FALSE;
1774 #ifdef DEBUG_MENU
1775 printf("NC_TrackSysMenu // before MenuFocusLoop !\n");
1776 #endif
1777 MenuFocusLoop(hWnd, NULL);
1778 #ifdef DEBUG_MENU
1779 printf("NC_TrackSysMenu // after MenuFocusLoop !\n");
1780 #endif
1783 else {
1784 ShowWindow(lpsys->hWnd, SW_HIDE);
1786 GlobalUnlock(wndPtr->hSysMenu);
1790 /**********************************************************************
1791 * GetMenuCheckMarkDimensions [USER.417]
1793 DWORD GetMenuCheckMarkDimensions()
1795 BITMAP bm;
1796 if (hStdCheck == (HBITMAP)NULL)
1797 hStdCheck = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_CHECK);
1798 GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
1799 return MAKELONG(bm.bmWidth, bm.bmHeight);
1803 /**********************************************************************
1804 * SetMenuItemBitmaps [USER.418]
1806 BOOL SetMenuItemBitmaps(HMENU hMenu, WORD nPos, WORD wFlags,
1807 HBITMAP hNewCheck, HBITMAP hNewUnCheck)
1809 WND *wndPtr;
1810 LPPOPUPMENU menu;
1811 LPMENUITEM lpitem;
1812 int i;
1813 #ifdef DEBUG_MENU
1814 printf("SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n",
1815 hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
1816 #endif
1817 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1818 if (menu == NULL) return FALSE;
1819 lpitem = menu->firstItem;
1820 for (i = 0; i < menu->nItems; i++) {
1821 if (lpitem == NULL) break;
1822 if (i == nPos) {
1823 lpitem->hCheckBit = hNewCheck;
1824 lpitem->hUnCheckBit = hNewUnCheck;
1825 GlobalUnlock(hMenu);
1826 return TRUE;
1828 lpitem = (LPMENUITEM)lpitem->next;
1830 GlobalUnlock(hMenu);
1831 return FALSE;
1835 /**********************************************************************
1836 * CreateMenu [USER.151]
1838 HMENU CreateMenu()
1840 HANDLE hItem;
1841 HMENU hMenu;
1842 LPPOPUPMENU menu;
1843 #ifdef DEBUG_MENU
1844 printf("CreatePopupMenu !\n");
1845 #endif
1846 hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
1847 menu = (LPPOPUPMENU) GlobalLock(hMenu);
1848 if (menu == NULL) {
1849 GlobalFree(hMenu);
1850 return 0;
1852 menu->nItems = 0;
1853 menu->firstItem = NULL;
1854 menu->hWndPrev = 0;
1855 menu->ownerWnd = 0;
1856 menu->hWnd = 0;
1857 menu->hWndParent = 0;
1858 menu->MouseFlags = 0;
1859 menu->BarFlag = TRUE;
1860 menu->SysFlag = FALSE;
1861 menu->ChildFlag = TRUE;
1862 menu->Width = 100;
1863 menu->Height = 0;
1864 GlobalUnlock(hMenu);
1865 return hMenu;
1869 /**********************************************************************
1870 * DestroyMenu [USER.152]
1872 BOOL DestroyMenu(HMENU hMenu)
1874 LPPOPUPMENU lppop;
1875 LPMENUITEM lpitem, lpitem2;
1876 #ifdef DEBUG_MENU
1877 printf("DestroyMenu (%04X) !\n", hMenu);
1878 #endif
1879 if (hMenu == 0) return FALSE;
1880 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
1881 if (lppop == NULL) return FALSE;
1882 if (lppop->hWnd) DestroyWindow (lppop->hWnd);
1883 lpitem = lppop->firstItem;
1884 while (lpitem != NULL) {
1885 #ifdef DEBUG_MENU
1886 printf("DestroyMenu (%04X) // during loop items !\n", hMenu);
1887 #endif
1888 if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
1889 DestroyMenu((HMENU)lpitem->item_id);
1891 lpitem = (LPMENUITEM)lpitem->next;
1893 GlobalUnlock(hMenu);
1894 GlobalFree(hMenu);
1895 #ifdef DEBUG_MENU
1896 printf("DestroyMenu (%04X) // End !\n", hMenu);
1897 #endif
1898 return TRUE;
1902 /**********************************************************************
1903 * LoadMenu [USER.150]
1905 HMENU LoadMenu(HINSTANCE instance, char *menu_name)
1907 HMENU hMenu;
1908 HANDLE hMenu_desc;
1909 MENU_HEADER *menu_desc;
1910 #ifdef DEBUG_MENU
1911 if ((LONG)menu_name & 0xFFFF0000L)
1912 printf("LoadMenu: instance %02x, menu '%s'\n", instance, menu_name);
1913 else
1914 printf("LoadMenu: instance %02x, menu '%04X'\n", instance, menu_name);
1915 #endif
1916 if (instance == (HANDLE)NULL) instance = hSysRes;
1917 if (menu_name == NULL ||
1918 (hMenu_desc = RSC_LoadMenu(instance, menu_name)) == 0 ||
1919 (menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc)) == NULL) {
1920 return 0;
1922 hMenu = LoadMenuIndirect((LPSTR)menu_desc);
1923 return hMenu;
1927 /**********************************************************************
1928 * GetSystemMenu [USER.156]
1930 HMENU GetSystemMenu(HWND hWnd, BOOL bRevert)
1932 WND *wndPtr;
1933 wndPtr = WIN_FindWndPtr(hWnd);
1934 if (!bRevert) {
1935 return wndPtr->hSysMenu;
1937 else {
1938 DestroyMenu(wndPtr->hSysMenu);
1939 wndPtr->hSysMenu = CopySysMenu();
1941 return wndPtr->hSysMenu;
1944 /**********************************************************************
1945 * SetSystemMenu [USER.280]
1947 BOOL SetSystemMenu(HWND hWnd, HMENU newHmenu)
1949 WND *wndPtr;
1951 if ((wndPtr = WIN_FindWndPtr(hWnd)) != NULL)
1952 wndPtr->hSysMenu = newHmenu;
1956 /**********************************************************************
1957 * GetMenu [USER.157]
1959 HMENU GetMenu(HWND hWnd)
1961 WND * wndPtr = WIN_FindWndPtr(hWnd);
1962 if (wndPtr == NULL) return 0;
1963 return wndPtr->wIDmenu;
1966 /**********************************************************************
1967 * SetMenu [USER.158]
1969 BOOL SetMenu(HWND hWnd, HMENU hMenu)
1971 LPPOPUPMENU lpmenu;
1972 WND * wndPtr = WIN_FindWndPtr(hWnd);
1973 if (wndPtr == NULL) {
1974 printf("SetMenu(%04X, %04X) // Bad window handle !\n", hWnd, hMenu);
1975 return FALSE;
1977 #ifdef DEBUG_MENU
1978 printf("SetMenu(%04X, %04X);\n", hWnd, hMenu);
1979 #endif
1980 wndPtr->wIDmenu = hMenu;
1981 lpmenu = (LPPOPUPMENU) GlobalLock(hMenu);
1982 if (lpmenu == NULL) {
1983 printf("SetMenu(%04X, %04X) // Bad menu handle !\n", hWnd, hMenu);
1984 return FALSE;
1986 lpmenu->ownerWnd = hWnd;
1987 printf("SetMenu(%04X, %04X) // %04X\n", hWnd, hMenu, lpmenu->ownerWnd);
1988 ResetHiliteFlags(lpmenu);
1989 if (GetCapture() == hWnd) ReleaseCapture();
1990 GlobalUnlock(hMenu);
1991 return TRUE;
1996 /**********************************************************************
1997 * GetSubMenu [USER.159]
1999 HMENU GetSubMenu(HMENU hMenu, short nPos)
2001 HMENU hSubMenu;
2002 LPPOPUPMENU lppop;
2003 LPMENUITEM lpitem;
2004 int i;
2005 #ifdef DEBUG_MENU
2006 printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos);
2007 #endif
2008 if (hMenu == 0) return 0;
2009 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
2010 if (lppop == NULL) return 0;
2011 lpitem = lppop->firstItem;
2012 for (i = 0; i < lppop->nItems; i++) {
2013 if (lpitem == NULL) break;
2014 if (i == nPos) {
2015 #ifdef DEBUG_MENU
2016 printf(" found %04x\n", lpitem->item_id);
2017 #endif
2018 if (lpitem->item_flags & MF_POPUP)
2019 return lpitem->item_id;
2020 else
2021 return 0;
2023 lpitem = (LPMENUITEM)lpitem->next;
2025 return 0;
2029 /**********************************************************************
2030 * DrawMenuBar [USER.160]
2032 void DrawMenuBar(HWND hWnd)
2034 WND *wndPtr;
2035 LPPOPUPMENU lppop;
2036 HDC hDC;
2037 #ifdef DEBUG_MENU
2038 printf("DrawMenuBar (%04X)\n", hWnd);
2039 #endif
2040 wndPtr = WIN_FindWndPtr(hWnd);
2041 if (wndPtr != NULL && (wndPtr->dwStyle & WS_CHILD) == 0 &&
2042 wndPtr->wIDmenu != 0) {
2043 #ifdef DEBUG_MENU
2044 printf("DrawMenuBar wIDmenu=%04X \n", wndPtr->wIDmenu);
2045 #endif
2046 lppop = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
2047 if (lppop == NULL) return;
2048 if ((lppop->rect.bottom - lppop->rect.top) != 0) {
2049 hDC = GetWindowDC(hWnd);
2050 StdDrawMenuBar(hDC, &lppop->rect, lppop, FALSE);
2051 ReleaseDC(hWnd, hDC);
2053 else
2054 SendMessage(hWnd, WM_NCPAINT, 1, 0L);
2055 GlobalUnlock(wndPtr->wIDmenu);
2060 /**********************************************************************
2061 * LoadMenuIndirect [USER.220]
2063 HMENU LoadMenuIndirect(LPSTR menu_template)
2065 HMENU hMenu;
2066 MENU_HEADER *menu_desc;
2067 LPPOPUPMENU lppop;
2068 #ifdef DEBUG_MENU
2069 printf("LoadMenuIndirect: menu_template '%08X'\n", menu_template);
2070 #endif
2071 hMenu = CreateMenu();
2072 menu_desc = (MENU_HEADER *)menu_template;
2073 ParseMenuResource((WORD *)(menu_desc + 1), 0, hMenu);
2074 lppop = (LPPOPUPMENU) GlobalLock(hMenu);
2075 ResetHiliteFlags(lppop);
2076 GlobalUnlock(hMenu);
2077 return hMenu;
2081 /**********************************************************************
2082 * CopySysMenu (Internal)
2084 HMENU CopySysMenu()
2086 HMENU hMenu;
2087 LPPOPUPMENU menu;
2088 LPPOPUPMENU sysmenu;
2089 #ifdef DEBUG_MENU
2090 printf("CopySysMenu entry !\n");
2091 #endif
2092 if (hSysMenu == 0) {
2093 hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(1));
2094 /* hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(SC_SYSMENU));*/
2095 /* hSysMenu = LoadMenu((HINSTANCE)NULL, "SYSMENU"); */
2096 if (hSysMenu == 0) {
2097 printf("SysMenu not found in system resources !\n");
2098 return (HMENU)NULL;
2100 #ifdef DEBUG_MENU
2101 else
2102 printf("SysMenu loaded from system resources %04X !\n", hSysMenu);
2103 #endif
2105 hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
2106 menu = (LPPOPUPMENU) GlobalLock(hMenu);
2107 sysmenu = (LPPOPUPMENU) GlobalLock(hSysMenu);
2108 if (menu != NULL && sysmenu != NULL) {
2109 sysmenu->BarFlag = FALSE;
2110 sysmenu->SysFlag = TRUE;
2111 memcpy(menu, sysmenu, sizeof(POPUPMENU));
2113 else {
2114 printf("CopySysMenu // Bad SysMenu pointers !\n");
2115 if (menu != NULL) {
2116 GlobalUnlock(hMenu);
2117 GlobalFree(hMenu);
2119 return (HMENU)NULL;
2121 GlobalUnlock(hMenu);
2122 GlobalUnlock(hSysMenu);
2123 #ifdef DEBUG_MENU
2124 printf("CopySysMenu hMenu=%04X !\n", hMenu);
2125 #endif
2126 return hMenu;
2130 /**********************************************************************
2131 * ParseMenuResource (from Resource or Template)
2133 WORD * ParseMenuResource(WORD *first_item, int level, HMENU hMenu)
2135 WORD *item;
2136 WORD *next_item;
2137 HMENU hSubMenu;
2138 int i;
2140 level++;
2141 next_item = first_item;
2142 i = 0;
2143 do {
2144 i++;
2145 item = next_item;
2146 if (*item & MF_POPUP) {
2147 MENU_POPUPITEM *popup_item = (MENU_POPUPITEM *) item;
2148 next_item = (WORD *) (popup_item->item_text +
2149 strlen(popup_item->item_text) + 1);
2150 hSubMenu = CreatePopupMenu();
2151 next_item = ParseMenuResource(next_item, level, hSubMenu);
2152 AppendMenu(hMenu, popup_item->item_flags,
2153 hSubMenu, popup_item->item_text);
2155 else {
2156 MENUITEMTEMPLATE *normal_item = (MENUITEMTEMPLATE *) item;
2157 next_item = (WORD *) (normal_item->item_text +
2158 strlen(normal_item->item_text) + 1);
2159 if (strlen(normal_item->item_text) == 0 && normal_item->item_id == 0)
2160 normal_item->item_flags |= MF_SEPARATOR;
2161 AppendMenu(hMenu, normal_item->item_flags,
2162 normal_item->item_id, normal_item->item_text);
2165 while (!(*item & MF_END));
2166 return next_item;