dahall / Vanara

A set of .NET libraries for Windows implementing PInvoke calls to many native Windows APIs with supporting wrappers.
MIT License
1.75k stars 190 forks source link

How to use native Win32 Shell ImageList in WinUI3 - Implementing ExplorerBrowser for WinUI3 #444

Open tajbender opened 4 months ago

tajbender commented 4 months ago

Is your feature request related to a problem? Please describe

I'm using WinAppSDK for some months now. I wonder how to use a native System Win32 API ImageList in UWP / WinUI? No changes to Vanara needed, i guess.

Any Idea, David? Thx.

Describe the additions or enhancements you'd like

// convert system wide shellItemList into xaml based type var winUIxamlObject = Vanara.*.SysImageList as || .SomeConversion()

dahall commented 3 months ago

@tajbender I haven't done much with WinUI. There is a package called Vanara.WinUI.Extensions where we can land anything you want to add. Right now, that assembly is pretty light. I'll accept any PR you post.

tajbender commented 3 months ago

@dahall Thank you very much. I really appreciate this.

I thought about aligning the interfaces of the WinUI3 ExplorerBrowser aka ShellListView / ShellTreeView that I'll implement the next days to those of Vanaras Win32 Ones.

That way Migrating that stuff from there to the WinUI-Version within Vanara would just be a piece of cake.

I'll let you know as soon there's something to talk about.

Have a nice Easter!

dahall commented 3 months ago

Cool! Thanks. Happy Easter to you too!

tajbender commented 3 months ago

@tajbender I haven't done much with WinUI.

btw, they have done an excellent job with WinUI3, in my humble opinion.

I've never worked with WPF and UWP before, but WinUI3 is straightforward as soon you get the point. They generate code-behind for the UI while compiling, this way, the UI-stuff is amazingly fast.

They also use DirectX / DirectDraw for rendering stuff. On the other side, you can use WinRT for the abstraction layer to OS for DOS, manipulating HWND settings / Messaging and so on: ๐Ÿ”

๐Ÿ‘

tajbender commented 3 months ago

Done so far.

tajbender commented 3 months ago

addendum: These classes my help out:

https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/win32/microsoft.ui.interop/

tajbender commented 3 months ago

addendum: This should do it, for single images:

    Bitmap bitmap1 = Bitmap.FromHicon(SystemIcons.Hand.Handle);
    Graphics formGraphics = this.CreateGraphics();
    GraphicsUnit units = GraphicsUnit.Point;

    RectangleF bmpRectangleF = bitmap1.GetBounds(ref units);
    Rectangle bmpRectangle = Rectangle.Round(bmpRectangleF);
    formGraphics.DrawRectangle(Pens.Blue, bmpRectangle);
    formGraphics.Dispose();

https://learn.microsoft.com/en-us/dotnet/api/system.drawing.systemicons?view=windowsdesktop-3.1

dahall commented 1 month ago

@tajbender What type(s) do you want converted from and to? I don't have a SysImageList class. Do you mean a native image list handle (HIMAGELIST)? What is the output type under WinUI3?

tajbender commented 1 month ago

@tajbender What type(s) do you want converted from and to? I don't have a SysImageList class. Do you mean a native image list handle (HIMAGELIST)? What is the output type under WinUI3?

@dahall Thanks for Reply, but you don't have to care about the Notes above. I just wrote down what I've found so far, so they're just a reminder for myself ๐Ÿงท

You're right, with SysImageList I refer to the Win32 - HIMAGELIST handle, you could get with SHGFI_SYSICONINDEX flag, which returns the Index to the Shell Icon you're looking for.

Using Win32 you can pass this Handle to your ListView or TreeView controls directly, to avoid copying the images around from System space to your own Heap.

Anyway, you don't have to care about these comments, these are reminders for myself.

Sorry for confusion and bothering, anyways Thank you very much, regards, tajbender

dahall commented 1 month ago

I think you may be able to use Vanara.Windows.Shell.ShellImageList (in Vanara.Windows.Shell.Common) to expose the SafeHICON of system files or folders and wrap that into a class the derives from IconSource to provide the converted icon handle to a bitmap.

tajbender commented 1 month ago

I think you may be able to use Vanara.Windows.Shell.ShellImageList (in Vanara.Windows.Shell.Common) to expose the SafeHICON of system files or folders and wrap that into a class the derives from IconSource to provide the converted icon handle to a bitmap.

public static ImageSource ToImageSource(this Icon icon)
{
    ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon(
        icon.Handle,
        Int32Rect.Empty,
        BitmapSizeOptions.FromEmptyOptions());
    return imageSource;
}

That's what Copilot says ๐Ÿ‘Œ

I'll try this asap. Thank you very much ๐Ÿ‘

tajbender commented 1 month ago

@dahall: I uploaded an YouTube-Video

That's the current state of the WinUI3 Shell - Components I'm working on, using Vanara.

Screenshot 2024-06-04 101413

You may look at the current branch here.

I still may need your help on some occasions, but I'm satisfied for now ๐Ÿ˜€

Just for your Info, regards, tajbender

dahall commented 1 month ago

I just committed a class I'll use for this: Vanara.Windows.Shell.ShellIconExtractor

tajbender commented 1 month ago

I just committed a class I'll use for this: Vanara.Windows.Shell.ShellIconExtractor

Thank you very much. This will help a lot. ๐Ÿฅ‡

tajbender commented 1 week ago

Dear @dahall

Love 4 support ๐Ÿง‘โ€โš•๏ธ

Currently, โšฝ European Championships take place in Germany, so no time no money ๐Ÿฐ

I used the new code already, it works stable ๐Ÿฅ‡

The next days, I will create a Pull Request for merging the stuff I have so far to Vanara. It still is WIP. But some review would help a lot.

Regards,

tajbender

tajbender commented 3 days ago

I just committed a class I'll use for this: Vanara.Windows.Shell.ShellIconExtractor

Hi, @dahall

I used the ShellIconExtractor for some days now.

I'm new to that multithreading stuff, but anyway I get some strange behavior: Enumerating the same Folder again and again when navigating through the pages and views, ShellIconExtractor in my App may result in different findings:

08:40:10:034    'electrifier.exe' (CoreCLR: DefaultDomain): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.19\System.Private.CoreLib.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:10:389    'electrifier.exe' (CoreCLR: clrhost): Loaded 'Snippets'. 
08:40:10:892    'electrifier.exe' (CoreCLR: clrhost): Loaded 'D:\gitHub\tajbender\electrifier.v1.24\src\electrifier\bin\x64\Debug\net7.0-windows10.0.19041.0\AppX\runtimes\win\lib\net7.0\System.Diagnostics.EventLog.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:10:892    'electrifier.exe' (CoreCLR: clrhost): Loaded 'D:\gitHub\tajbender\electrifier.v1.24\src\electrifier\bin\x64\Debug\net7.0-windows10.0.19041.0\AppX\Vanara.Windows.Shell.Common.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:10:892    'electrifier.exe' (CoreCLR: clrhost): Loaded 'D:\gitHub\tajbender\electrifier.v1.24\src\electrifier\bin\x64\Debug\net7.0-windows10.0.19041.0\AppX\Vanara.PInvoke.Ole.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:10:892    'electrifier.exe' (CoreCLR: clrhost): Loaded 'D:\gitHub\tajbender\electrifier.v1.24\src\electrifier\bin\x64\Debug\net7.0-windows10.0.19041.0\AppX\Vanara.PInvoke.Shell32.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:10:892    'electrifier.exe' (CoreCLR: clrhost): Loaded 'D:\gitHub\tajbender\electrifier.v1.24\src\electrifier\bin\x64\Debug\net7.0-windows10.0.19041.0\AppX\Vanara.PInvoke.Shared.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:11:883    Error: Converter failed to convert value of type 'Windows.Foundation.IReference`1<Microsoft.UI.Xaml.GridLength>' to type 'Double'; BindingExpression: Path='TemplateSettings.CompactPaneGridLength' DataItem='Microsoft.UI.Xaml.Controls.SplitView'; target element is 'Microsoft.UI.Xaml.Media.Animation.SplineDoubleKeyFrame' (Name='null'); target property is 'Value' (type 'Double'). 
08:40:14:383    'electrifier.exe' (CoreCLR: clrhost): Loaded 'D:\gitHub\tajbender\electrifier.v1.24\src\electrifier\bin\x64\Debug\net7.0-windows10.0.19041.0\AppX\Vanara.Core.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:14:631    'electrifier.exe' (CoreCLR: clrhost): Loaded 'D:\gitHub\tajbender\electrifier.v1.24\src\electrifier\bin\x64\Debug\net7.0-windows10.0.19041.0\AppX\Vanara.PInvoke.Gdi32.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:14:631    'electrifier.exe' (CoreCLR: clrhost): Loaded 'D:\gitHub\tajbender\electrifier.v1.24\src\electrifier\bin\x64\Debug\net7.0-windows10.0.19041.0\AppX\Vanara.Windows.Extensions.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:14:631    'electrifier.exe' (CoreCLR: clrhost): Loaded 'D:\gitHub\tajbender\electrifier.v1.24\src\electrifier\bin\x64\Debug\net7.0-windows10.0.19041.0\AppX\Vanara.PInvoke.User32.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:15:144    .IconExtOnComplete(): 63 items
08:40:15:144    .SetItemsSource(): `Desktop` 63 items.
08:40:16:630    .IconExtOnComplete(): 61 items
08:40:16:630    .SetItemsSource(): `Desktop` 61 items.
08:40:16:630    .GridViewVisibility = Visible
08:40:23:882    'electrifier.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.19\System.Reflection.Emit.Lightweight.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:23:882    'electrifier.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.19\System.Reflection.Emit.ILGeneration.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:23:882    'electrifier.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.19\System.Reflection.Primitives.dll'. Symbol loading disabled by Include/Exclude setting.
08:40:24:130    .IconExtOnComplete(): 64 items
08:40:24:130    .SetItemsSource(): `Desktop` 64 items.
08:40:27:631    .IconExtOnComplete(): 64 items
08:40:27:631    .SetItemsSource(): `Desktop` 64 items.
08:40:27:631    .GridViewVisibility = Visible
08:40:47:395    The thread '[Thread Destroyed]' (12448) has exited with code 0 (0x0).
08:40:47:645    The thread '[Thread Destroyed]' (27936) has exited with code 0 (0x0).
08:40:50:430    .IconExtOnComplete(): 63 items
08:40:50:430    .SetItemsSource(): `Desktop` 63 items.
08:40:52:736    .IconExtOnComplete(): 64 items
08:40:52:736    .SetItemsSource(): `Desktop` 64 items.
08:40:52:984    .GridViewVisibility = Visible
08:40:55:740    .IconExtOnComplete(): 64 items
08:40:55:740    .SetItemsSource(): `Desktop` 64 items.
08:40:57:780    .IconExtOnComplete(): 64 items
08:40:57:780    .SetItemsSource(): `Desktop` 64 items.
08:40:57:780    .GridViewVisibility = Visible
08:41:00:578    .IconExtOnComplete(): 64 items
08:41:00:578    .SetItemsSource(): `Desktop` 64 items.
08:41:03:657    .IconExtOnComplete(): 64 items
08:41:03:657    .SetItemsSource(): `Desktop` 64 items.
08:41:03:657    .GridViewVisibility = Visible
08:41:05:689    .IconExtOnComplete(): 62 items
08:41:05:689    .SetItemsSource(): `Desktop` 62 items.
08:41:25:456    The thread '[Thread Destroyed]' (8484) has exited with code 0 (0x0).
08:41:25:697    The thread '[Thread Destroyed]' (22372) has exited with code 0 (0x0).

Everytime .IconExtOnComplete(): has finished, my desktop folder has been enumerated. As you may see, I may get different number of items while doing so (62, 63, 64). ๐Ÿ˜’

In Fact, it should be 63 items... I'll investigate further ๐Ÿค” ๐Ÿ’ญ

Have a nice, sunny day ๐ŸŒž