source: trunk/src/shell32/shlmenu.cpp@ 4032

Last change on this file since 4032 was 4032, checked in by phaller, 25 years ago

Synchronized shell32 with wine

File size: 26.6 KB
Line 
1/* $Id: shlmenu.cpp,v 1.6 2000-08-18 02:01:25 phaller Exp $ */
2
3/*
4 * Win32 SHELL32 for OS/2
5 *
6 * Copyright 1999 Patrick Haller (haller@zebra.fh-weingarten.de)
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 * Path Functions
10 *
11 * Many of this functions are in SHLWAPI.DLL also
12 *
13 * Corel WINE 20000324 level
14 */
15
16/*
17 * see www.geocities.com/SiliconValley/4942/filemenu.html
18 */
19
20
21/*****************************************************************************
22 * Includes *
23 *****************************************************************************/
24
25#include <odin.h>
26#include <odinwrap.h>
27#include <os2sel.h>
28
29#include <assert.h>
30#include <string.h>
31#include <odin.h>
32
33#define ICOM_CINTERFACE 1
34#define CINTERFACE 1
35
36#include "wine/obj_base.h"
37#include "wine/obj_enumidlist.h"
38#include "wine/obj_shellfolder.h"
39#include "wine/undocshell.h"
40
41#include "heap.h"
42#include "debugtools.h"
43#include "winversion.h"
44#include "shell32_main.h"
45#include "shlguid.h"
46
47#include "pidl.h"
48
49#include <heapstring.h>
50#include <misc.h>
51
52
53ODINDEBUGCHANNEL(SHELL32-SHLMENU)
54
55
56/*****************************************************************************
57 * Implementation *
58 *****************************************************************************/
59
60BOOL WINAPI FileMenu_DeleteAllItems (HMENU hMenu);
61BOOL WINAPI FileMenu_AppendItemA(HMENU hMenu, LPCSTR lpText, UINT uID, int icon, HMENU hMenuPopup, int nItemHeight);
62
63typedef struct
64{
65 BOOL bInitialized;
66 BOOL bFixedItems;
67
68 /* create */
69 COLORREF crBorderColor;
70 int nBorderWidth;
71 HBITMAP hBorderBmp;
72
73 /* insert using pidl */
74 LPITEMIDLIST pidl;
75 UINT uID;
76 UINT uFlags;
77 UINT uEnumFlags;
78 LPFNFMCALLBACK lpfnCallback;
79} FMINFO, *LPFMINFO;
80
81typedef struct
82{ int cchItemText;
83 int iIconIndex;
84 HMENU hMenu;
85 char szItemText[1];
86} FMITEM, * LPFMITEM;
87
88static BOOL bAbortInit;
89
90#define CCH_MAXITEMTEXT 256
91
92LPFMINFO FM_GetMenuInfo(HMENU hmenu)
93{ MENUINFO MenuInfo;
94 LPFMINFO menudata;
95
96 MenuInfo.cbSize = sizeof(MENUINFO);
97 MenuInfo.fMask = MIM_MENUDATA;
98
99 if (! GetMenuInfo(hmenu, &MenuInfo))
100 return NULL;
101
102 menudata = (LPFMINFO)MenuInfo.dwMenuData;
103
104 assert ((menudata != 0) && (MenuInfo.cbSize == sizeof(MENUINFO)));
105
106 return menudata;
107
108}
109/*************************************************************************
110 * FM_SetMenuParameter [internal]
111 *
112 */
113static LPFMINFO FM_SetMenuParameter(
114 HMENU hmenu,
115 UINT uID,
116 LPCITEMIDLIST pidl,
117 UINT uFlags,
118 UINT uEnumFlags,
119 LPFNFMCALLBACK lpfnCallback)
120{
121 LPFMINFO menudata;
122
123 TRACE("\n");
124
125 menudata = FM_GetMenuInfo(hmenu);
126
127 if ( menudata->pidl)
128 { SHFree(menudata->pidl);
129 }
130
131 menudata->uID = uID;
132 menudata->pidl = ILClone(pidl);
133 menudata->uFlags = uFlags;
134 menudata->uEnumFlags = uEnumFlags;
135 menudata->lpfnCallback = lpfnCallback;
136
137 return menudata;
138}
139
140/*************************************************************************
141 * FM_InitMenuPopup [internal]
142 *
143 */
144static int FM_InitMenuPopup(HMENU hmenu, LPITEMIDLIST pAlternatePidl)
145{ IShellFolder *lpsf, *lpsf2;
146 ULONG ulItemAttr = SFGAO_FOLDER;
147 UINT uID, uFlags, uEnumFlags;
148 LPFNFMCALLBACK lpfnCallback;
149 LPITEMIDLIST pidl;
150 char sTemp[MAX_PATH];
151 int NumberOfItems = 0, iIcon;
152 MENUINFO MenuInfo;
153 LPFMINFO menudata;
154
155 TRACE("0x%04x %p\n", hmenu, pAlternatePidl);
156
157 MenuInfo.cbSize = sizeof(MENUINFO);
158 MenuInfo.fMask = MIM_MENUDATA;
159
160 if (! GetMenuInfo(hmenu, &MenuInfo))
161 return FALSE;
162
163 menudata = (LPFMINFO)MenuInfo.dwMenuData;
164
165 assert ((menudata != 0) && (MenuInfo.cbSize == sizeof(MENUINFO)));
166
167 if (menudata->bInitialized)
168 return 0;
169
170 pidl = ((pAlternatePidl) ? pAlternatePidl : menudata->pidl);
171 if (!pidl)
172 return 0;
173
174 uID = menudata->uID;
175 uFlags = menudata->uFlags;
176 uEnumFlags = menudata->uEnumFlags;
177 lpfnCallback = menudata->lpfnCallback;
178
179 menudata->bInitialized = FALSE;
180 SetMenuInfo(hmenu, &MenuInfo);
181
182 if (SUCCEEDED (SHGetDesktopFolder(&lpsf)))
183 {
184 if (SUCCEEDED(IShellFolder_BindToObject(lpsf, pidl,0,(REFIID)&IID_IShellFolder,(LPVOID *)&lpsf2)))
185 {
186 IEnumIDList *lpe = NULL;
187
188 if (SUCCEEDED (IShellFolder_EnumObjects(lpsf2, 0, uEnumFlags, &lpe )))
189 {
190
191 LPITEMIDLIST pidlTemp = NULL;
192 ULONG ulFetched;
193
194 while ((!bAbortInit) && (NOERROR == IEnumIDList_Next(lpe,1,&pidlTemp,&ulFetched)))
195 {
196 if (SUCCEEDED (IShellFolder_GetAttributesOf(lpsf, 1, &pidlTemp, &ulItemAttr)))
197 {
198 ILGetDisplayName( pidlTemp, sTemp);
199 if (! (PidlToSicIndex(lpsf, pidlTemp, FALSE, 0, (UINT*)&iIcon)))
200 iIcon = FM_BLANK_ICON;
201 if ( SFGAO_FOLDER & ulItemAttr)
202 {
203 LPFMINFO lpFmMi;
204 MENUINFO MenuInfo;
205 HMENU hMenuPopup = CreatePopupMenu();
206
207 lpFmMi = (LPFMINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
208
209 lpFmMi->pidl = ILCombine(pidl, pidlTemp);
210 lpFmMi->uEnumFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
211
212 MenuInfo.cbSize = sizeof(MENUINFO);
213 MenuInfo.fMask = MIM_MENUDATA;
214 MenuInfo.dwMenuData = (DWORD) lpFmMi;
215 SetMenuInfo (hMenuPopup, &MenuInfo);
216
217 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, hMenuPopup, FM_DEFAULT_HEIGHT);
218 }
219 else
220 {
221 ((LPSTR)PathFindExtensionA(sTemp))[0] = 0x00;
222 FileMenu_AppendItemA (hmenu, sTemp, uID, iIcon, 0, FM_DEFAULT_HEIGHT);
223 }
224 }
225
226 if (lpfnCallback)
227 {
228 TRACE("enter callback\n");
229 lpfnCallback ( pidl, pidlTemp);
230 TRACE("leave callback\n");
231 }
232
233 NumberOfItems++;
234 }
235 IEnumIDList_Release (lpe);
236 }
237 IShellFolder_Release(lpsf2);
238 }
239 IShellFolder_Release(lpsf);
240 }
241
242 if ( GetMenuItemCount (hmenu) == 0 )
243 { FileMenu_AppendItemA (hmenu, "(empty)", uID, FM_BLANK_ICON, 0, FM_DEFAULT_HEIGHT);
244 NumberOfItems++;
245 }
246
247 menudata->bInitialized = TRUE;
248 SetMenuInfo(hmenu, &MenuInfo);
249
250 return NumberOfItems;
251}
252/*************************************************************************
253 * FileMenu_Create [SHELL32.114]
254 *
255 * NOTES
256 * for non-root menus values are
257 * (ffffffff,00000000,00000000,00000000,00000000)
258 */
259ODINFUNCTION5(HMENU, FileMenu_Create,
260 COLORREF, crBorderColor,
261 int, nBorderWidth,
262 HBITMAP, hBorderBmp,
263 int, nSelHeight,
264 UINT, uFlags)
265{
266 MENUINFO MenuInfo;
267 LPFMINFO menudata;
268
269 HMENU hMenu = CreatePopupMenu();
270
271 TRACE("0x%08lx 0x%08x 0x%08x 0x%08x 0x%08x hMenu=0x%08x\n",
272 crBorderColor, nBorderWidth, hBorderBmp, nSelHeight, uFlags, hMenu);
273
274 menudata = (LPFMINFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FMINFO));
275 menudata->crBorderColor = crBorderColor;
276 menudata->nBorderWidth = nBorderWidth;
277 menudata->hBorderBmp = hBorderBmp;
278
279 MenuInfo.cbSize = sizeof(MENUINFO);
280 MenuInfo.fMask = MIM_MENUDATA;
281 MenuInfo.dwMenuData = (DWORD) menudata;
282 SetMenuInfo (hMenu, &MenuInfo);
283
284 return hMenu;
285}
286
287/*************************************************************************
288 * FileMenu_Destroy [SHELL32.118]
289 *
290 * NOTES
291 * exported by name
292 */
293ODINPROCEDURE1(FileMenu_Destroy,
294 HMENU, hmenu)
295{
296 LPFMINFO menudata;
297
298 TRACE("0x%08x\n", hmenu);
299
300 FileMenu_DeleteAllItems (hmenu);
301
302 menudata = FM_GetMenuInfo(hmenu);
303
304 if ( menudata->pidl)
305 { SHFree( menudata->pidl);
306 }
307 HeapFree(GetProcessHeap(), 0, menudata);
308
309 DestroyMenu (hmenu);
310}
311
312/*************************************************************************
313 * FileMenu_AppendItemAW [SHELL32.115]
314 *
315 */
316ODINFUNCTION6(BOOL, FileMenu_AppendItemA,
317 HMENU, hMenu,
318 LPCSTR, lpText,
319 UINT, uID,
320 int, icon,
321 HMENU, hMenuPopup,
322 int, nItemHeight)
323{
324 LPSTR lpszText = (LPSTR)lpText;
325 MENUITEMINFOA mii;
326 LPFMITEM myItem;
327 LPFMINFO menudata;
328 MENUINFO MenuInfo;
329
330 TRACE("0x%08x %s 0x%08x 0x%08x 0x%08x 0x%08x\n",
331 hMenu, (lpszText!=FM_SEPARATOR) ? lpText: NULL,
332 uID, icon, hMenuPopup, nItemHeight);
333
334 ZeroMemory (&mii, sizeof(MENUITEMINFOA));
335
336 mii.cbSize = sizeof(MENUITEMINFOA);
337
338 if (lpText != FM_SEPARATOR)
339 { int len = strlen (lpText);
340 myItem = (LPFMITEM) SHAlloc( sizeof(FMITEM) + len);
341 strcpy (myItem->szItemText, lpText);
342 myItem->cchItemText = len;
343 myItem->iIconIndex = icon;
344 myItem->hMenu = hMenu;
345 mii.fMask = MIIM_DATA;
346 mii.dwItemData = (DWORD) myItem;
347 }
348
349 if ( hMenuPopup )
350 { /* sub menu */
351 mii.fMask |= MIIM_TYPE | MIIM_SUBMENU;
352 mii.fType = MFT_OWNERDRAW;
353 mii.hSubMenu = hMenuPopup;
354 }
355 else if (lpText == FM_SEPARATOR )
356 { mii.fMask |= MIIM_ID | MIIM_TYPE;
357 mii.fType = MFT_SEPARATOR;
358 }
359 else
360 { /* normal item */
361 mii.fMask |= MIIM_ID | MIIM_TYPE | MIIM_STATE;
362 mii.fState = MFS_ENABLED | MFS_DEFAULT;
363 mii.fType = MFT_OWNERDRAW;
364 }
365 mii.wID = uID;
366
367 InsertMenuItemA (hMenu, (UINT)-1, TRUE, &mii);
368
369 /* set bFixedItems to true */
370 MenuInfo.cbSize = sizeof(MENUINFO);
371 MenuInfo.fMask = MIM_MENUDATA;
372
373 if (! GetMenuInfo(hMenu, &MenuInfo))
374 return FALSE;
375
376 menudata = (LPFMINFO)MenuInfo.dwMenuData;
377 assert ((menudata != 0) && (MenuInfo.cbSize == sizeof(MENUINFO)));
378 menudata->bFixedItems = TRUE;
379 SetMenuInfo(hMenu, &MenuInfo);
380
381 return TRUE;
382
383}
384ODINFUNCTION6(BOOL, FileMenu_AppendItemAW,
385 HMENU, hMenu,
386 LPCVOID, lpText,
387 UINT, uID,
388 int, icon,
389 HMENU, hMenuPopup,
390 int, nItemHeight)
391{
392 BOOL ret;
393 LPSTR lpszText=NULL;
394
395 if (VERSION_OsIsUnicode() && (lpText!=FM_SEPARATOR))
396 lpszText = (LPSTR)HEAP_strdupWtoA ( GetProcessHeap(),0, (LPCWSTR)lpText);
397
398 ret = FileMenu_AppendItemA(hMenu, (lpszText) ? lpszText : (LPCSTR)lpText, uID, icon, hMenuPopup, nItemHeight);
399
400 if (lpszText)
401 HeapFree( GetProcessHeap(), 0, lpszText );
402
403 return ret;
404}
405/*************************************************************************
406 * FileMenu_InsertUsingPidl [SHELL32.110]
407 *
408 * NOTES
409 * uEnumFlags any SHCONTF flag
410 */
411ODINFUNCTION6(int, FileMenu_InsertUsingPidl,
412 HMENU, hmenu,
413 UINT, uID,
414 LPCITEMIDLIST, pidl,
415 UINT, uFlags,
416 UINT, uEnumFlags,
417 LPFNFMCALLBACK, lpfnCallback)
418{
419 TRACE("0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
420 hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
421
422 pdump (pidl);
423
424 bAbortInit = FALSE;
425
426 FM_SetMenuParameter(hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
427
428 return FM_InitMenuPopup(hmenu, NULL);
429}
430
431/*************************************************************************
432 * FileMenu_ReplaceUsingPidl [SHELL32.113]
433 *
434 * FIXME: the static items are deleted but wont be refreshed
435 */
436ODINFUNCTION5(int, FileMenu_ReplaceUsingPidl,
437 HMENU, hmenu,
438 UINT, uID,
439 LPCITEMIDLIST, pidl,
440 UINT, uEnumFlags,
441 LPFNFMCALLBACK, lpfnCallback)
442{
443 TRACE("0x%08x 0x%08x %p 0x%08x %p\n",
444 hmenu, uID, pidl, uEnumFlags, lpfnCallback);
445
446 FileMenu_DeleteAllItems (hmenu);
447
448 FM_SetMenuParameter(hmenu, uID, pidl, 0, uEnumFlags, lpfnCallback);
449
450 return FM_InitMenuPopup(hmenu, NULL);
451}
452
453/*************************************************************************
454 * FileMenu_Invalidate [SHELL32.111]
455 */
456ODINPROCEDURE1(FileMenu_Invalidate,
457 HMENU, hMenu)
458{
459 FIXME("0x%08x\n",hMenu);
460}
461
462/*************************************************************************
463 * FileMenu_FindSubMenuByPidl [SHELL32.106]
464 */
465ODINFUNCTION2(HMENU, FileMenu_FindSubMenuByPidl,
466 HMENU, hMenu,
467 LPCITEMIDLIST, pidl)
468{
469 FIXME("0x%08x %p\n",hMenu, pidl);
470 return 0;
471}
472
473/*************************************************************************
474 * FileMenu_AppendFilesForPidl [SHELL32.124]
475 */
476ODINFUNCTION3(int, FileMenu_AppendFilesForPidl,
477 HMENU, hmenu,
478 LPCITEMIDLIST, pidl,
479 BOOL, bAddSeperator)
480{
481 LPFMINFO menudata;
482
483 menudata = FM_GetMenuInfo(hmenu);
484
485 menudata->bInitialized = FALSE;
486
487 FM_InitMenuPopup(hmenu, pidl);
488
489 if (bAddSeperator)
490 FileMenu_AppendItemA (hmenu, FM_SEPARATOR, 0, 0, 0, FM_DEFAULT_HEIGHT);
491
492 TRACE("0x%08x %p 0x%08x\n",hmenu, pidl,bAddSeperator);
493
494 return 0;
495}
496/*************************************************************************
497 * FileMenu_AddFilesForPidl [SHELL32.125]
498 *
499 * NOTES
500 * uEnumFlags any SHCONTF flag
501 */
502ODINFUNCTION7(int, FileMenu_AddFilesForPidl,
503 HMENU, hmenu,
504 UINT, uReserved,
505 UINT, uID,
506 LPCITEMIDLIST, pidl,
507 UINT, uFlags,
508 UINT, uEnumFlags,
509 LPFNFMCALLBACK, lpfnCallback)
510{
511 TRACE("0x%08x 0x%08x 0x%08x %p 0x%08x 0x%08x %p\n",
512 hmenu, uReserved, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
513
514 return FileMenu_InsertUsingPidl ( hmenu, uID, pidl, uFlags, uEnumFlags, lpfnCallback);
515
516}
517
518
519/*************************************************************************
520 * FileMenu_TrackPopupMenuEx [SHELL32.116]
521 */
522ODINFUNCTION6(BOOL, FileMenu_TrackPopupMenuEx,
523 HMENU, hMenu,
524 UINT, uFlags,
525 int, x,
526 int, y,
527 HWND, hWnd,
528 LPTPMPARAMS, lptpm)
529{
530 TRACE("0x%08x 0x%08x 0x%x 0x%x 0x%08x %p\n",
531 hMenu, uFlags, x, y, hWnd, lptpm);
532 return TrackPopupMenuEx(hMenu, uFlags, x, y, hWnd, lptpm);
533}
534
535/*************************************************************************
536 * FileMenu_GetLastSelectedItemPidls [SHELL32.107]
537 */
538ODINFUNCTION3(BOOL, FileMenu_GetLastSelectedItemPidls,
539 UINT, uReserved,
540 LPCITEMIDLIST *, ppidlFolder,
541 LPCITEMIDLIST *, ppidlItem)
542{
543 FIXME("0x%08x %p %p\n",uReserved, ppidlFolder, ppidlItem);
544 return 0;
545}
546
547#define FM_ICON_SIZE 16
548#define FM_Y_SPACE 4
549#define FM_SPACE1 4
550#define FM_SPACE2 2
551#define FM_LEFTBORDER 2
552#define FM_RIGHTBORDER 8
553/*************************************************************************
554 * FileMenu_MeasureItem [SHELL32.112]
555 */
556ODINFUNCTION2(LRESULT, FileMenu_MeasureItem,
557 HWND, hWnd,
558 LPMEASUREITEMSTRUCT, lpmis)
559{
560 LPFMITEM pMyItem = (LPFMITEM)(lpmis->itemData);
561 HDC hdc = GetDC(hWnd);
562 SIZE size;
563 LPFMINFO menuinfo;
564
565 TRACE("0x%08x %p %s\n", hWnd, lpmis, pMyItem->szItemText);
566
567 GetTextExtentPoint32A(hdc, pMyItem->szItemText, pMyItem->cchItemText, &size);
568
569 lpmis->itemWidth = size.cx + FM_LEFTBORDER + FM_ICON_SIZE + FM_SPACE1 + FM_SPACE2 + FM_RIGHTBORDER;
570 lpmis->itemHeight = (size.cy > (FM_ICON_SIZE + FM_Y_SPACE)) ? size.cy : (FM_ICON_SIZE + FM_Y_SPACE);
571
572 /* add the menubitmap */
573 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
574 if (menuinfo->nBorderWidth)
575 lpmis->itemWidth += menuinfo->nBorderWidth;
576
577 TRACE("-- 0x%04x 0x%04x\n", lpmis->itemWidth, lpmis->itemHeight);
578 ReleaseDC (hWnd, hdc);
579 return 0;
580}
581/*************************************************************************
582 * FileMenu_DrawItem [SHELL32.105]
583 */
584ODINFUNCTION2(LRESULT, FileMenu_DrawItem,
585 HWND, hWnd,
586 LPDRAWITEMSTRUCT, lpdis)
587{
588 LPFMITEM pMyItem = (LPFMITEM)(lpdis->itemData);
589 COLORREF clrPrevText, clrPrevBkgnd;
590 int xi,yi,xt,yt;
591 HIMAGELIST hImageList;
592 RECT TextRect, BorderRect;
593 LPFMINFO menuinfo;
594
595 TRACE("0x%08x %p %s\n", hWnd, lpdis, pMyItem->szItemText);
596
597 if (lpdis->itemState & ODS_SELECTED)
598 {
599 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHTTEXT));
600 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_HIGHLIGHT));
601 }
602 else
603 {
604 clrPrevText = SetTextColor(lpdis->hDC, GetSysColor (COLOR_MENUTEXT));
605 clrPrevBkgnd = SetBkColor(lpdis->hDC, GetSysColor (COLOR_MENU));
606 }
607
608 CopyRect(&TextRect, &(lpdis->rcItem));
609
610 /* add the menubitmap */
611 menuinfo = FM_GetMenuInfo(pMyItem->hMenu);
612 if (menuinfo->nBorderWidth)
613 TextRect.left += menuinfo->nBorderWidth;
614
615 BorderRect.right = menuinfo->nBorderWidth;
616/* FillRect(lpdis->hDC, &BorderRect, CreateSolidBrush( menuinfo->crBorderColor));
617*/
618 TextRect.left += FM_LEFTBORDER;
619 xi = TextRect.left + FM_SPACE1;
620 yi = TextRect.top + FM_Y_SPACE/2;
621 TextRect.bottom -= FM_Y_SPACE/2;
622
623 xt = xi + FM_ICON_SIZE + FM_SPACE2;
624 yt = yi;
625
626 ExtTextOutA (lpdis->hDC, xt , yt, ETO_OPAQUE, &TextRect, pMyItem->szItemText, pMyItem->cchItemText, NULL);
627
628 Shell_GetImageList(0, &hImageList);
629 pImageList_Draw(hImageList, pMyItem->iIconIndex, lpdis->hDC, xi, yi, ILD_NORMAL);
630
631 TRACE("-- 0x%04x 0x%04x 0x%04x 0x%04x\n", TextRect.left, TextRect.top, TextRect.right, TextRect.bottom);
632
633 SetTextColor(lpdis->hDC, clrPrevText);
634 SetBkColor(lpdis->hDC, clrPrevBkgnd);
635
636 return TRUE;
637}
638
639/*************************************************************************
640 * FileMenu_InitMenuPopup [SHELL32.109]
641 *
642 * NOTES
643 * The filemenu is a ownerdrawn menu. Call this function responding to
644 * WM_INITPOPUPMENU
645 *
646 */
647ODINFUNCTION1(BOOL, FileMenu_InitMenuPopup,
648 HMENU, hmenu)
649{
650 FM_InitMenuPopup(hmenu, NULL);
651 return TRUE;
652}
653
654/*************************************************************************
655 * FileMenu_HandleMenuChar [SHELL32.108]
656 */
657ODINFUNCTION2(LRESULT, FileMenu_HandleMenuChar,
658 HMENU, hMenu,
659 WPARAM, wParam)
660{
661 FIXME("0x%08x 0x%08x\n",hMenu,wParam);
662 return 0;
663}
664
665/*************************************************************************
666 * FileMenu_DeleteAllItems [SHELL32.104]
667 *
668 * NOTES
669 * exported by name
670 */
671ODINFUNCTION1(BOOL, FileMenu_DeleteAllItems,
672 HMENU, hmenu)
673{
674 MENUITEMINFOA mii;
675 LPFMINFO menudata;
676
677 int i;
678
679 TRACE("0x%08x\n", hmenu);
680
681 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
682 mii.cbSize = sizeof(MENUITEMINFOA);
683 mii.fMask = MIIM_SUBMENU|MIIM_DATA;
684
685 for (i = 0; i < GetMenuItemCount( hmenu ); i++)
686 { GetMenuItemInfoA(hmenu, i, TRUE, &mii );
687
688 if (mii.dwItemData)
689 SHFree((LPFMINFO)mii.dwItemData);
690
691 if (mii.hSubMenu)
692 FileMenu_Destroy(mii.hSubMenu);
693 }
694
695 while (DeleteMenu (hmenu, 0, MF_BYPOSITION)){};
696
697 menudata = FM_GetMenuInfo(hmenu);
698
699 menudata->bInitialized = FALSE;
700
701 return TRUE;
702}
703
704/*************************************************************************
705 * FileMenu_DeleteItemByCmd [SHELL32.]
706 *
707 */
708ODINFUNCTION2(BOOL, FileMenu_DeleteItemByCmd,
709 HMENU, hMenu,
710 UINT, uID)
711{
712 MENUITEMINFOA mii;
713
714 TRACE("0x%08x 0x%08x\n", hMenu, uID);
715
716 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
717 mii.cbSize = sizeof(MENUITEMINFOA);
718 mii.fMask = MIIM_SUBMENU;
719
720 GetMenuItemInfoA(hMenu, uID, FALSE, &mii );
721 if ( mii.hSubMenu );
722
723 DeleteMenu(hMenu, MF_BYCOMMAND, uID);
724 return TRUE;
725}
726
727/*************************************************************************
728 * FileMenu_DeleteItemByIndex [SHELL32.140]
729 */
730ODINFUNCTION2(BOOL, FileMenu_DeleteItemByIndex,
731 HMENU, hMenu,
732 UINT, uPos)
733{
734 MENUITEMINFOA mii;
735
736 TRACE("0x%08x 0x%08x\n", hMenu, uPos);
737
738 ZeroMemory ( &mii, sizeof(MENUITEMINFOA));
739 mii.cbSize = sizeof(MENUITEMINFOA);
740 mii.fMask = MIIM_SUBMENU;
741
742 GetMenuItemInfoA(hMenu, uPos, TRUE, &mii );
743 if ( mii.hSubMenu );
744
745 DeleteMenu(hMenu, MF_BYPOSITION, uPos);
746 return TRUE;
747}
748
749/*************************************************************************
750 * FileMenu_DeleteItemByFirstID [SHELL32.141]
751 */
752ODINFUNCTION2(BOOL, FileMenu_DeleteItemByFirstID,
753 HMENU, hMenu,
754 UINT, uID)
755{
756 TRACE("0x%08x 0x%08x\n", hMenu, uID);
757 return 0;
758}
759
760/*************************************************************************
761 * FileMenu_DeleteSeparator [SHELL32.142]
762 */
763ODINFUNCTION1(BOOL, FileMenu_DeleteSeparator,
764 HMENU, hMenu)
765{
766 TRACE("0x%08x\n", hMenu);
767 return 0;
768}
769
770/*************************************************************************
771 * FileMenu_EnableItemByCmd [SHELL32.143]
772 */
773ODINFUNCTION3(BOOL, FileMenu_EnableItemByCmd,
774 HMENU, hMenu,
775 UINT, uID,
776 BOOL, bEnable)
777{
778 TRACE("0x%08x 0x%08x 0x%08x\n", hMenu, uID,bEnable);
779 return 0;
780}
781
782/*************************************************************************
783 * FileMenu_GetItemExtent [SHELL32.144]
784 *
785 * NOTES
786 * if the menu is to big, entrys are getting cut away!!
787 */
788ODINFUNCTION2(DWORD, FileMenu_GetItemExtent,
789 HMENU, hMenu,
790 UINT, uPos)
791{ RECT rect;
792
793 FIXME("0x%08x 0x%08x\n", hMenu, uPos);
794
795 if (GetMenuItemRect(0, hMenu, uPos, &rect))
796 { FIXME("0x%04x 0x%04x 0x%04x 0x%04x\n",
797 rect.right, rect.left, rect.top, rect.bottom);
798 return ((rect.right-rect.left)<<16) + (rect.top-rect.bottom);
799 }
800 return 0x00100010; /*fixme*/
801}
802
803/*************************************************************************
804 * FileMenu_AbortInitMenu [SHELL32.120]
805 *
806 */
807ODINPROCEDURE0(FileMenu_AbortInitMenu)
808{
809 bAbortInit = TRUE;
810}
811
812/*************************************************************************
813 * SHFind_InitMenuPopup [SHELL32.149]
814 *
815 *
816 * PARAMETERS
817 * hMenu [in] handle of menu previously created
818 * hWndParent [in] parent window
819 * w [in] no pointer (0x209 over here) perhaps menu IDs ???
820 * x [in] no pointer (0x226 over here)
821 *
822 * RETURNS
823 * LPXXXXX pointer to struct containing a func addr at offset 8
824 * or NULL at failure.
825 */
826ODINFUNCTION4(HRESULT, SHFind_InitMenuPopup,
827 HMENU, hMenu,
828 HWND, hWndParent,
829 DWORD, w,
830 DWORD, x)
831{ FIXME("hmenu=0x%08x hwnd=0x%08x 0x%08lx 0x%08lx stub\n",
832 hMenu,hWndParent,w,x);
833 return NULL; /* this is supposed to be a pointer */
834}
835
836/*************************************************************************
837 * Shell_MergeMenus [SHELL32.67]
838 *
839 */
840BOOL _SHIsMenuSeparator(HMENU hm, int i)
841{
842 MENUITEMINFOA mii;
843
844 mii.cbSize = sizeof(MENUITEMINFOA);
845 mii.fMask = MIIM_TYPE;
846 mii.cch = 0; /* WARNING: We MUST initialize it to 0*/
847 if (!GetMenuItemInfoA(hm, i, TRUE, &mii))
848 {
849 return(FALSE);
850 }
851
852 if (mii.fType & MFT_SEPARATOR)
853 {
854 return(TRUE);
855 }
856
857 return(FALSE);
858}
859
860ODINFUNCTION6(HRESULT, Shell_MergeMenus,
861 HMENU, hmDst,
862 HMENU, hmSrc,
863 UINT, uInsert,
864 UINT, uIDAdjust,
865 UINT, uIDAdjustMax,
866 ULONG, uFlags)
867{ int nItem;
868 HMENU hmSubMenu;
869 BOOL bAlreadySeparated;
870 MENUITEMINFOA miiSrc;
871 char szName[256];
872 UINT uTemp, uIDMax = uIDAdjust;
873
874 TRACE("hmenu1=0x%04x hmenu2=0x%04x 0x%04x 0x%04x 0x%04x 0x%04lx\n",
875 hmDst, hmSrc, uInsert, uIDAdjust, uIDAdjustMax, uFlags);
876
877 if (!hmDst || !hmSrc)
878 { return uIDMax;
879 }
880
881 nItem = GetMenuItemCount(hmDst);
882
883 if (uInsert >= (UINT)nItem) /* insert position inside menu? */
884 {
885 uInsert = (UINT)nItem; /* append on the end */
886 bAlreadySeparated = TRUE;
887 }
888 else
889 {
890 bAlreadySeparated = _SHIsMenuSeparator(hmDst, uInsert);;
891 }
892
893 if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
894 {
895 /* Add a separator between the menus */
896 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
897 bAlreadySeparated = TRUE;
898 }
899
900
901 /* Go through the menu items and clone them*/
902 for (nItem = GetMenuItemCount(hmSrc) - 1; nItem >= 0; nItem--)
903 {
904 miiSrc.cbSize = sizeof(MENUITEMINFOA);
905 miiSrc.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA;
906
907 /* We need to reset this every time through the loop in case menus DON'T have IDs*/
908 miiSrc.fType = MFT_STRING;
909 miiSrc.dwTypeData = szName;
910 miiSrc.dwItemData = 0;
911 miiSrc.cch = sizeof(szName);
912
913 if (!GetMenuItemInfoA(hmSrc, nItem, TRUE, &miiSrc))
914 {
915 continue;
916 }
917
918/* TRACE("found menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmSrc, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu);
919*/
920 if (miiSrc.fType & MFT_SEPARATOR)
921 {
922 /* This is a separator; don't put two of them in a row */
923 if (bAlreadySeparated)
924 continue;
925
926 bAlreadySeparated = TRUE;
927 }
928 else if (miiSrc.hSubMenu)
929 {
930 if (uFlags & MM_SUBMENUSHAVEIDS)
931 {
932 miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */
933
934 if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */
935 continue;
936
937 if (uIDMax <= miiSrc.wID) /* remember the highest ID */
938 uIDMax = miiSrc.wID + 1;
939 }
940 else
941 {
942 miiSrc.fMask &= ~MIIM_ID; /* Don't set IDs for submenus that didn't have them already */
943 }
944 hmSubMenu = miiSrc.hSubMenu;
945
946 miiSrc.hSubMenu = CreatePopupMenu();
947
948 if (!miiSrc.hSubMenu) return(uIDMax);
949
950 uTemp = Shell_MergeMenus(miiSrc.hSubMenu, hmSubMenu, 0, uIDAdjust, uIDAdjustMax, uFlags & MM_SUBMENUSHAVEIDS);
951
952 if (uIDMax <= uTemp)
953 uIDMax = uTemp;
954
955 bAlreadySeparated = FALSE;
956 }
957 else /* normal menu item */
958 {
959 miiSrc.wID += uIDAdjust; /* add uIDAdjust to the ID */
960
961 if (miiSrc.wID > uIDAdjustMax) /* skip ID's higher uIDAdjustMax */
962 continue;
963
964 if (uIDMax <= miiSrc.wID) /* remember the highest ID */
965 uIDMax = miiSrc.wID + 1;
966
967 bAlreadySeparated = FALSE;
968 }
969
970/* TRACE("inserting menu=0x%04x %s id=0x%04x mask=0x%08x smenu=0x%04x\n", hmDst, debugstr_a(miiSrc.dwTypeData), miiSrc.wID, miiSrc.fMask, miiSrc.hSubMenu);
971*/
972 if (!InsertMenuItemA(hmDst, uInsert, TRUE, &miiSrc))
973 {
974 return(uIDMax);
975 }
976 }
977
978 /* Ensure the correct number of separators at the beginning of the
979 inserted menu items*/
980 if (uInsert == 0)
981 {
982 if (bAlreadySeparated)
983 {
984 DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
985 }
986 }
987 else
988 {
989 if (_SHIsMenuSeparator(hmDst, uInsert-1))
990 {
991 if (bAlreadySeparated)
992 {
993 DeleteMenu(hmDst, uInsert, MF_BYPOSITION);
994 }
995 }
996 else
997 {
998 if ((uFlags & MM_ADDSEPARATOR) && !bAlreadySeparated)
999 {
1000 /* Add a separator between the menus*/
1001 InsertMenuA(hmDst, uInsert, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
1002 }
1003 }
1004 }
1005 return(uIDMax);
1006}
1007
Note: See TracBrowser for help on using the repository browser.