WPF NotifyIcon and Window Handles
Greetings,
I am attempting to create a WPF NotifyIcon class, as the WinForms NotifyIcon class doesn't meet my requirements and technical preferences (I would like to use a styled WPF ContextMenu and an Icon from my WPF Resources).
I'm using Shell_NotifyIcon() in the Shell32.dll method for the underlying implementation of this NotifyIcon class. One of the parameters to Shell_NotifyIcon() has a window handle to the icon you want to display.Can anyone shed some light on how I can get a window handle for an icon I have in my "wpf" resources?
Now the only other area where I've used an icon in WPF is for the Window.Icon property. This happens to be a ImageSource object, so it seemed like a good idea to create a an Icon property which is of type ImageSource.
After reading through themsdn help, I deducted that I'd need to wrap the ImageSource in a visual, and place that inside a HwndSource object. So, I added code similar to the following:
Code Snippet
ImageSource imageSource = BitmapFrame.Create(Application.GetResourceStream(new Uri("Resources/Icons/Text.ico", UriKind.RelativeOrAbsolute)).Stream);
Image image = new Image();
image.Source = imageSource;
HwndSource source = new HwndSource(new HwndSourceParamters());
source.RootVisual = image;
m_notifyIconData.hIcon = source.Handle;
// Go off and display the icon with Shell_NotifyIcon()
Am I heading down the right track? With the method I'm currently using, I'm not getting anything displayed. I'm confident I'm using Shell_NotifyIcon() as I can get an "WinForms" Icon displayed by using the Handle property of the Icon class.
Thanks in advance,
-Brad
(I thought I would post an update to my quest to have a WPF NotifyIcon).
Brad Leach wrote: |
| Can anyone shed some light on how I can get a window handle for an icon I have in my "wpf" resources? | |
After taking some time to research and understand WPF resources, I've found a way use a WPF resource in a System.Drawing.Icon class.
Code Snippet
GetIcon(
new
System.Uri("Resources/Icons/Text.ico"
, System.UriKind.Relative));private static System.Drawing.Icon GetIcon(Uri uri)
{
using (Stream resourceStream = Application.GetResourceStream(uri).Stream)
{
return new System.Drawing.Icon(resourceStream);
}
}
From the icon, you can use the Handle property to get a handle that I can use in Shell_NotifyIcon(). Now you will need to reference System.Drawing in your WPF application. While I'd prefer not to reference a Windows Forms based dll (or at least a dll that was only designed for Windows Forms), at this stage I can't figure out how to use pure WPF constructs for this class.
The next step is adding the context menu. I haven't had interop success so far with that either, but I need to do some more experimentation.
Cheers,
-Brad
So now I'm on to the ContextMenu part of the WPF NotifyIcon. I've wrapped the System.Windows.Controls.ContextMenu in a HwndSource object, and I seem to be getting a Handle back.
I was planning on using TrackPopupMenu() and GetMenuItemID() for tracking and getting the selected menu items. However, TrackPopupMenu() always seems to be returning "0" (and no popup menu is being displayed). Based on the content in this document, most notably this passage: "The rest of your WPF content in the application shares that singular HWND. An exception is menus, combo box drop downs, and other pop-ups. These elements create their own top-level window, which is why a WPF menu can potentially go past the edge of the window HWND that contains it."; I assumed this would work ok. However, after reading through a link here "I'd be nice to have a way to use the Context menu in a manner similar to Win32s TrackPopupMenu. All it would need would be a way to determine what MenuItem was active when the menu closes."; I am not so sure this method is going to work.
So my question is, "Is it possible to show a WPF ContextMenu from a native notification area icon?". If so, How? 