Skip to content

Commit 888d2a3

Browse files
committed
Fix ShellExtension project copy command, extract contextmenu into class
1 parent a156f30 commit 888d2a3

File tree

6 files changed

+119
-91
lines changed

6 files changed

+119
-91
lines changed

FastCopy/CopyDialog.cpp

Lines changed: 3 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,8 @@
99
#include "Taskbar.h"
1010
#include "Global.h"
1111
#include "SettingsChangeListener.h"
12-
#include "PathUtils.h"
13-
#include <ShlGuid.h>
14-
#include <ShlObj_core.h>
15-
#include <winrt/Windows.System.Threading.h>
16-
#include "ImageUtils.h"
17-
#include <Windows.h>
18-
#include <gdiplus.h>
12+
13+
#include "FileContextMenu.h"
1914
#pragma comment(lib, "gdiplus.lib")
2015

2116
using namespace winrt;
@@ -156,81 +151,7 @@ namespace winrt::FastCopy::implementation
156151

157152
void CopyDialog::ShowMenu(winrt::hstring path, winrt::Microsoft::UI::Xaml::Controls::MenuFlyout flyout)
158153
{
159-
160-
winrt::com_ptr<IShellItem> item, folderItem;
161-
SHCreateItemFromParsingName(ToBackslash(path).data(), NULL, IID_PPV_ARGS(item.put()));
162-
163-
item->GetParent(folderItem.put());
164-
165-
winrt::com_ptr<IShellFolder> folder;
166-
folderItem->BindToHandler(nullptr, BHID_SFObject, IID_PPV_ARGS(folder.put()));
167-
168-
169-
LPITEMIDLIST child{ };
170-
171-
SHGetIDListFromObject(item.get(), &child);
172-
auto last = ILFindLastID(child);
173-
174-
LPCITEMIDLIST idl[2]{ last };
175-
176-
winrt::com_ptr<IContextMenu> menu;
177-
auto hr = folder->GetUIObjectOf(NULL, 1, &idl[0], IID_IContextMenu, nullptr, menu.put_void());
178-
179-
auto hMenu = CreatePopupMenu();
180-
//menu->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_OPTIMIZEFORINVOKE);
181-
menu->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_NORMAL);
182-
183-
auto const itemCount = GetMenuItemCount(hMenu);
184-
MENUITEMINFO menuItemInfo{
185-
.cbSize = sizeof(menuItemInfo),
186-
.fMask = MIIM_BITMAP | MIIM_FTYPE | MIIM_STRING | MIIM_ID | MIIM_SUBMENU
187-
};
188-
for (int i = 0; i < itemCount; ++i)
189-
{
190-
TCHAR buffer[500]{};
191-
menuItemInfo.dwTypeData = buffer;
192-
menuItemInfo.cch = std::size(buffer);
193-
GetMenuItemInfo(hMenu, i, true, &menuItemInfo);
194-
if (!std::wstring_view{buffer}.empty() && menu)
195-
{
196-
winrt::Microsoft::UI::Xaml::Controls::MenuFlyoutItem item;
197-
item.Text(buffer);
198-
199-
if (menuItemInfo.hbmpItem)
200-
{
201-
winrt::Microsoft::UI::Xaml::Controls::ImageIcon icon;
202-
{
203-
auto pbitmap = Gdiplus::Bitmap::FromHBITMAP(menuItemInfo.hbmpItem, NULL);
204-
INT const height = pbitmap->GetHeight();
205-
INT const width = pbitmap->GetWidth();
206-
207-
Gdiplus::Color c{Gdiplus::Color::MakeARGB(255, 0, 0, 0)};
208-
209-
Gdiplus::Rect bmBounds{0, 0, (INT)width, (INT)height};
210-
Gdiplus::BitmapData data{};
211-
pbitmap->LockBits(&bmBounds, Gdiplus::ImageLockModeRead, PixelFormat32bppRGB, &data);
212-
213-
Gdiplus::Bitmap tmp{width, height, data.Stride, PixelFormat32bppARGB, (BYTE*)data.Scan0};
214-
Gdiplus::Bitmap clone{width, height, PixelFormat32bppARGB};
215-
216-
Gdiplus::Graphics* gr = Gdiplus::Graphics::FromImage(&clone);
217-
gr->DrawImage(&tmp, bmBounds);
218-
219-
HBITMAP hbitmap{};
220-
clone.GetHBITMAP(c, &hbitmap);
221-
if (auto source = HBitmapToWriteableBitmap(hbitmap); source != nullptr)
222-
{
223-
icon.Source(source);
224-
item.Icon(icon);
225-
}
226-
}
227-
}
228-
flyout.Items().Append(item);
229-
}
230-
OutputDebugString(buffer);
231-
OutputDebugString(L"\n");
232-
}
233-
154+
FileContextMenu(path).ShowAt(flyout);
234155
}
235156

236157
}
@@ -251,12 +172,4 @@ void winrt::FastCopy::implementation::CopyDialog::MenuFlyout_Opening(winrt::Wind
251172
.as<winrt::FastCopy::FileInfoViewModel>();
252173

253174
ShowMenu(fileInfoViewModel.Path(), menu);
254-
255-
//std::thread{
256-
// [this, path = fileInfoViewModel.Path()]
257-
// {
258-
// winrt::init_apartment(winrt::apartment_type::single_threaded);
259-
// ShowMenu(path, nullptr);
260-
// }
261-
//}.detach();
262175
}

FastCopy/FastCopy.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@
166166
<DependentUpon>FileCompareViewModel.idl</DependentUpon>
167167
<SubType>Code</SubType>
168168
</ClInclude>
169+
<ClInclude Include="FileContextMenu.h" />
169170
<ClInclude Include="FileInfoViewModel.h">
170171
<DependentUpon>FileInfoViewModel.idl</DependentUpon>
171172
<SubType>Code</SubType>
@@ -308,6 +309,7 @@
308309
<DependentUpon>FileCompareViewModel.idl</DependentUpon>
309310
<SubType>Code</SubType>
310311
</ClCompile>
312+
<ClCompile Include="FileContextMenu.cpp" />
311313
<ClCompile Include="FileInfoViewModel.cpp">
312314
<DependentUpon>FileInfoViewModel.idl</DependentUpon>
313315
<SubType>Code</SubType>

FastCopy/FastCopy.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@
141141
<Filter>Utils</Filter>
142142
</ClCompile>
143143
<ClCompile Include="FileTime.cpp" />
144+
<ClCompile Include="FileContextMenu.cpp">
145+
<Filter>Views\Controls</Filter>
146+
</ClCompile>
144147
</ItemGroup>
145148
<ItemGroup>
146149
<ClInclude Include="pch.h" />
@@ -229,6 +232,9 @@
229232
<Filter>Utils</Filter>
230233
</ClInclude>
231234
<ClInclude Include="FileTime.h" />
235+
<ClInclude Include="FileContextMenu.h">
236+
<Filter>Views\Controls</Filter>
237+
</ClInclude>
232238
</ItemGroup>
233239
<ItemGroup>
234240
<Image Include="Assets\Wide310x150Logo.scale-200.png">

FastCopy/FileContextMenu.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#include "pch.h"
2+
#include "FileContextMenu.h"
3+
#include "PathUtils.h"
4+
#include <ShlGuid.h>
5+
#include <ShlObj_core.h>
6+
#include "ImageUtils.h"
7+
#include <Windows.h>
8+
#include <gdiplus.h>
9+
10+
void FileContextMenu::ShowAt(winrt::Microsoft::UI::Xaml::Controls::MenuFlyout& flyout)
11+
{
12+
winrt::com_ptr<IShellItem> item, folderItem;
13+
SHCreateItemFromParsingName(m_path.data(), NULL, IID_PPV_ARGS(item.put()));
14+
15+
item->GetParent(folderItem.put());
16+
17+
winrt::com_ptr<IShellFolder> folder;
18+
folderItem->BindToHandler(nullptr, BHID_SFObject, IID_PPV_ARGS(folder.put()));
19+
20+
21+
LPITEMIDLIST child{ };
22+
23+
SHGetIDListFromObject(item.get(), &child);
24+
auto last = ILFindLastID(child);
25+
26+
LPCITEMIDLIST idl[2]{ last };
27+
28+
winrt::com_ptr<IContextMenu> menu;
29+
auto hr = folder->GetUIObjectOf(NULL, 1, &idl[0], IID_IContextMenu, nullptr, menu.put_void());
30+
31+
auto hMenu = CreatePopupMenu();
32+
//menu->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_OPTIMIZEFORINVOKE);
33+
menu->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_NORMAL);
34+
35+
auto const itemCount = GetMenuItemCount(hMenu);
36+
MENUITEMINFO menuItemInfo{
37+
.cbSize = sizeof(menuItemInfo),
38+
.fMask = MIIM_BITMAP | MIIM_FTYPE | MIIM_STRING | MIIM_ID | MIIM_SUBMENU
39+
};
40+
for (int i = 0; i < itemCount; ++i)
41+
{
42+
TCHAR buffer[500]{};
43+
menuItemInfo.dwTypeData = buffer;
44+
menuItemInfo.cch = std::size(buffer);
45+
GetMenuItemInfo(hMenu, i, true, &menuItemInfo);
46+
if (!std::wstring_view{buffer}.empty() && menu)
47+
{
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);
81+
}
82+
OutputDebugString(buffer);
83+
OutputDebugString(L"\n");
84+
}
85+
}

FastCopy/FileContextMenu.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
#include <winrt/Windows.Foundation.h>
3+
#include <winrt/Microsoft.UI.Xaml.Controls.h>
4+
#include <vector>
5+
#include "PathUtils.h"
6+
7+
struct MenuData
8+
{
9+
int menuId;
10+
std::wstring verb;
11+
};
12+
13+
class FileContextMenu
14+
{
15+
std::vector<MenuData> m_menuData;
16+
std::wstring m_path;
17+
void onMenuItemClick() {}
18+
public:
19+
FileContextMenu(winrt::hstring path) : m_path{ ToBackslash(path)} {}
20+
21+
void ShowAt(winrt::Microsoft::UI::Xaml::Controls::MenuFlyout& flyout);
22+
};

FastCopyShellExtension/FastCopyShellExtension.vcxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@
139139
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
140140
</Link>
141141
<PostBuildEvent>
142-
<Command>xcopy "$(SolutionDir)$(Platform)\Release\FastCopy\$(ProjectName).dll" "$(SolutionDir)$(Platform)\Debug\FastCopy\$(ProjectName).dll" /Y /-I</Command>
142+
<Command>xcopy "$(SolutionDir)$(Platform)\Release\FastCopy\$(ProjectName).dll" "$(SolutionDir)$(Platform)\Debug\FastCopy\" /Y</Command>
143143
</PostBuildEvent>
144144
<ResourceCompile>
145145
<ResourceOutputFileName>FastCopyShellExtension.res</ResourceOutputFileName>

0 commit comments

Comments
 (0)