如何获取Windows Defender扫描右键菜单项的图标?
我正尝试将通过IContextMenu.QueryContextMenu()获取的HMENU转换为WPF的ContextMenu,以便使用自定义样式替代原生Windows菜单样式。大部分功能正常,但“使用Windows Defender扫描...”和谷歌云盘的“同步或备份此文件夹”这两个项,通过GetMenuItemInfo()获取的MENUITEMINFO结构中未返回图标,其他项的图标均可正常获取。我也查看了MIIM_DATA,但未找到相关内容。
编辑补充:这些项并非自绘。我已将TrackPopupMenuEx()与WndProc挂钩,检查消息流后未发现WM_DRAWITEM或WM_MEASUREITEM消息。
相关代码
Public Function GetContextMenu(items As IEnumerable(Of Item)) As ContextMenu Dim pidls(items.Count - 1) As IntPtr Dim lastpidls(items.Count - 1) As IntPtr For i = 0 To items.Count - 1 Functions.SHGetIDListFromObject(Marshal.GetIUnknownForObject(items(i).ShellItem2), pidls(i)) lastpidls(i) = Functions.ILFindLastID(pidls(i)) Next Dim ptr As IntPtr Me.ShellFolder.GetUIObjectOf(IntPtr.Zero, lastpidls.Length, lastpidls, GetType(IContextMenu).GUID, 0, ptr) Dim contextMenu As IContextMenu = Marshal.GetTypedObjectForIUnknown(ptr, GetType(IContextMenu)) Marshal.QueryInterface(ptr, GetType(IContextMenu2).GUID, ptr) Dim contextMenu2 As IContextMenu2, contextMenu3 As IContextMenu3 If Not ptr = IntPtr.Zero Then contextMenu2 = CType(Marshal.GetObjectForIUnknown(ptr), IContextMenu2) End If Marshal.QueryInterface(ptr, GetType(IContextMenu3).GUID, ptr) If Not ptr = IntPtr.Zero Then contextMenu3 = CType(Marshal.GetObjectForIUnknown(ptr), IContextMenu3) End If Dim hMenu As IntPtr = Functions.CreatePopupMenu() contextMenu.QueryContextMenu(hMenu, 0, 0, UInt32.MaxValue, CMF.CMF_NORMAL Or CMF.CMF_EXTENDEDVERBS) If _firstContextMenuCall Then ' somehow very first call doesn't return all items Functions.DestroyMenu(hMenu) hMenu = Functions.CreatePopupMenu() contextMenu.QueryContextMenu(hMenu, 0, 0, UInt32.MaxValue, CMF.CMF_NORMAL Or CMF.CMF_EXTENDEDVERBS) End If Dim getMenu As Func(Of IntPtr, List(Of Control)) = Function(hMenu2 As IntPtr) As List(Of Control) If Not contextMenu2 Is Nothing Then contextMenu2.HandleMenuMsg(WM.INITMENUPOPUP, hMenu2, IntPtr.Zero) End If If Not contextMenu3 Is Nothing Then Dim ptr2 As IntPtr contextMenu3.HandleMenuMsg2(WM.INITMENUPOPUP, hMenu2, IntPtr.Zero, ptr2) End If Dim result As List(Of Control) = New List(Of Control)() For i = 0 To Functions.GetMenuItemCount(hMenu2) - 1 Dim mii As MENUITEMINFO mii.cbSize = CUInt(Marshal.SizeOf(mii)) mii.fMask = MIIM.MIIM_STRING mii.dwTypeData = New String(" "c, 2048) mii.cch = mii.dwTypeData.Length Functions.GetMenuItemInfo(hMenu2, i, True, mii) Dim header As String = mii.dwTypeData.Substring(0, mii.cch) mii.fMask = MIIM.MIIM_BITMAP Or MIIM.MIIM_SUBMENU Or MIIM.MIIM_FTYPE Functions.GetMenuItemInfo(hMenu2, i, True, mii) Dim bitmapSource As BitmapSource If Not IntPtr.Zero.Equals(mii.hbmpItem) Then bitmapSource = Interop.Imaging.CreateBitmapSourceFromHBitmap(mii.hbmpItem, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()) Else bitmapSource = Nothing End If If mii.fType = MFT.SEPARATOR Then result.Add(New Separator()) Else Dim menuItem As MenuItem = New MenuItem() With { .Header = header.Replace("&", "_"), .Icon = New Image() With {.Source = bitmapSource} } If mii.hSubMenu Then Dim subMenu As List(Of Control) = getMenu(mii.hSubMenu) For Each subMenuItem In subMenu menuItem.Items.Add(subMenuItem) Next End If result.Add(menuItem) End If Next Return result End Function Dim result2 As List(Of Control) = getMenu(hMenu) Dim menuResult As ContextMenu = New ContextMenu() For Each item In result2 menuResult.Items.Add(item) Next Functions.DestroyMenu(hMenu) Return menuResult End Function
内容的提问来源于stack exchange,提问作者miss programmer
相关产品推荐
相关产品推荐

