77#include < Windows.h>
88#include < gdiplus.h>
99
10- void FileContextMenu::ShowAt ( winrt::Microsoft::UI::Xaml::Controls::MenuFlyout& flyout )
10+ winrt::Microsoft::UI::Xaml::Media::ImageSource FileContextMenu::getIconFromWin32Menu (HBITMAP menuItemInfoBitmap )
1111{
12- winrt::com_ptr<IShellItem> item, folderItem;
13- SHCreateItemFromParsingName (m_path.data (), NULL , IID_PPV_ARGS (item.put ()));
12+ if (!menuItemInfoBitmap)
13+ return nullptr ;
14+
15+ auto pbitmap = Gdiplus::Bitmap::FromHBITMAP (menuItemInfoBitmap, NULL );
16+ INT const height = pbitmap->GetHeight ();
17+ INT const width = pbitmap->GetWidth ();
18+
19+ Gdiplus::Color c{Gdiplus::Color::MakeARGB (255 , 0 , 0 , 0 )};
20+
21+ Gdiplus::Rect bmBounds{0 , 0 , (INT)width, (INT)height};
22+ Gdiplus::BitmapData data{};
23+ pbitmap->LockBits (&bmBounds, Gdiplus::ImageLockModeRead, PixelFormat32bppRGB, &data);
24+
25+ Gdiplus::Bitmap tmp{width, height, data.Stride , PixelFormat32bppARGB, (BYTE*)data.Scan0 };
26+ Gdiplus::Bitmap clone{width, height, PixelFormat32bppARGB};
1427
28+ Gdiplus::Graphics* gr = Gdiplus::Graphics::FromImage (&clone);
29+ gr->DrawImage (&tmp, bmBounds);
30+
31+ HBITMAP hbitmap{};
32+ clone.GetHBITMAP (c, &hbitmap);
33+ return HBitmapToWriteableBitmap (hbitmap);
34+ }
35+
36+ winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItem FileContextMenu::makeMenuFlyout (MENUITEMINFO const & menuItemInfo)
37+ {
38+ winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItem item;
39+ item.Text (menuItemInfo.dwTypeData );
40+
41+ item.Click ([thisPtr = shared_from_this ()](auto self, ...) {
42+ int const id = winrt::unbox_value<decltype (m_menuData.size ())>(self.as <winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItem>().Tag ());
43+ auto const & data = thisPtr->m_menuData [id];
44+ CMINVOKECOMMANDINFOEX invokeInfo
45+ {
46+ .cbSize = sizeof (invokeInfo),
47+ .lpVerb = reinterpret_cast <decltype (invokeInfo.lpVerb )>(MAKEINTRESOURCEW (data.menuId )),
48+ .nShow = SW_SHOWNORMAL,
49+ };
50+ thisPtr->m_menu ->InvokeCommand (reinterpret_cast <CMINVOKECOMMANDINFO*>(&invokeInfo));
51+ });
52+
53+ if (auto source = getIconFromWin32Menu (menuItemInfo.hbmpItem ))
54+ {
55+ winrt::Microsoft::UI::Xaml::Controls::ImageIcon icon;
56+ icon.Source (source);
57+ item.Icon (icon);
58+ }
59+ item.Tag (winrt::box_value (m_menuData.size ()));
60+ return item;
61+ }
62+
63+ void FileContextMenu::ShowAt (winrt::Microsoft::UI::Xaml::Controls::MenuFlyout& flyout)
64+ {
65+ winrt::com_ptr<IShellItem> item = CreateItemFromParsingName (m_path.data ()), folderItem;
1566 item->GetParent (folderItem.put ());
1667
1768 winrt::com_ptr<IShellFolder> folder;
@@ -25,12 +76,10 @@ void FileContextMenu::ShowAt(winrt::Microsoft::UI::Xaml::Controls::MenuFlyout& f
2576
2677 LPCITEMIDLIST idl[2 ]{ last };
2778
28- winrt::com_ptr<IContextMenu> menu;
29- auto hr = folder->GetUIObjectOf (NULL , 1 , &idl[0 ], IID_IContextMenu, nullptr , menu.put_void ());
79+ auto hr = folder->GetUIObjectOf (NULL , 1 , &idl[0 ], IID_IContextMenu, nullptr , m_menu.put_void ());
3080
3181 auto hMenu = CreatePopupMenu ();
32- // menu->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_OPTIMIZEFORINVOKE);
33- menu->QueryContextMenu (hMenu, 0 , 1 , 0x7fff , CMF_NORMAL);
82+ m_menu->QueryContextMenu (hMenu, 0 , 1 , 0x7fff , CMF_NORMAL);
3483
3584 auto const itemCount = GetMenuItemCount (hMenu);
3685 MENUITEMINFO menuItemInfo{
@@ -43,43 +92,12 @@ void FileContextMenu::ShowAt(winrt::Microsoft::UI::Xaml::Controls::MenuFlyout& f
4392 menuItemInfo.dwTypeData = buffer;
4493 menuItemInfo.cch = std::size (buffer);
4594 GetMenuItemInfo (hMenu, i, true , &menuItemInfo);
46- if (!std::wstring_view{buffer}.empty () && menu )
95+ if (!std::wstring_view{buffer}.empty () && m_menu )
4796 {
48- winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItem item;
49- item.Text (buffer);
50-
51- if (menuItemInfo.hbmpItem )
52- {
53- winrt::Microsoft::UI::Xaml::Controls::ImageIcon icon;
54- {
55- auto pbitmap = Gdiplus::Bitmap::FromHBITMAP (menuItemInfo.hbmpItem , NULL );
56- INT const height = pbitmap->GetHeight ();
57- INT const width = pbitmap->GetWidth ();
58-
59- Gdiplus::Color c{Gdiplus::Color::MakeARGB (255 , 0 , 0 , 0 )};
60-
61- Gdiplus::Rect bmBounds{0 , 0 , (INT)width, (INT)height};
62- Gdiplus::BitmapData data{};
63- pbitmap->LockBits (&bmBounds, Gdiplus::ImageLockModeRead, PixelFormat32bppRGB, &data);
64-
65- Gdiplus::Bitmap tmp{width, height, data.Stride , PixelFormat32bppARGB, (BYTE*)data.Scan0 };
66- Gdiplus::Bitmap clone{width, height, PixelFormat32bppARGB};
67-
68- Gdiplus::Graphics* gr = Gdiplus::Graphics::FromImage (&clone);
69- gr->DrawImage (&tmp, bmBounds);
70-
71- HBITMAP hbitmap{};
72- clone.GetHBITMAP (c, &hbitmap);
73- if (auto source = HBitmapToWriteableBitmap (hbitmap); source != nullptr )
74- {
75- icon.Source (source);
76- item.Icon (icon);
77- }
78- }
79- }
80- flyout.Items ().Append (item);
97+ flyout.Items ().Append (makeMenuFlyout (menuItemInfo));
98+ std::wstring command (100 , {});
99+ m_menu->GetCommandString (menuItemInfo.wID - 1 , GCS_VERB, nullptr , reinterpret_cast <char *>(command.data ()), command.size ());
100+ m_menuData.push_back (MenuData{ .menuId = menuItemInfo.wID - 1 , .verb = std::move (command) });
81101 }
82- OutputDebugString (buffer);
83- OutputDebugString (L" \n " );
84102 }
85103}
0 commit comments