source: trunk/src/shell32/shlmenu.c@ 5087

Last change on this file since 5087 was 4121, checked in by sandervl, 25 years ago

complete merge with shell32 from wine 20000801

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