C# 获取应用程序';图标矩形是什么?
我想知道我的C# 获取应用程序';图标矩形是什么?,c#,.net,vb.net,windows,winforms,C#,.net,Vb.net,Windows,Winforms,我想知道我的NotifyIcon在系统托盘中的位置(在单击它之前) 在中,Hans Passant发表评论说不,这是不可能的,但我认为操作系统内部可以完成的几乎所有事情都可以由开发人员复制,如果我不正确,那么为什么SO可以让通知图标位置显示弹出窗口 在上面的同一个问题中,有一个C#示例演示了如何定位systemtray矩形,我想知道这是否是一个开始 这项任务能否实现 如果是的话,怎么办 如果没有,为什么操作系统可以?我们以何种方式被限制无法复制相同的内容?您需要以下声明: public
NotifyIcon
在系统托盘中的位置(在单击它之前)
在中,Hans Passant发表评论说不,这是不可能的,但我认为操作系统内部可以完成的几乎所有事情都可以由开发人员复制,如果我不正确,那么为什么SO可以让通知图标
位置显示弹出窗口
在上面的同一个问题中,有一个C#示例演示了如何定位systemtray矩形,我想知道这是否是一个开始
这项任务能否实现
如果是的话,怎么办
如果没有,为什么操作系统可以?我们以何种方式被限制无法复制相同的内容?您需要以下声明:
public const Int32 WM_MYMESSAGE = 0x8000; //WM_APP
public const Int32 NOTIFYICON_VERSION_4 = 0x4;
//messages
public const Int32 WM_CONTEXTMENU = 0x7B;
public const Int32 NIN_BALLOONHIDE = 0x403;
public const Int32 NIN_BALLOONSHOW = 0x402;
public const Int32 NIN_BALLOONTIMEOUT = 0x404;
public const Int32 NIN_BALLOONUSERCLICK = 0x405;
public const Int32 NIN_KEYSELECT = 0x403;
public const Int32 NIN_SELECT = 0x400;
public const Int32 NIN_POPUPOPEN = 0x406;
public const Int32 NIN_POPUPCLOSE = 0x407;
public const Int32 NIIF_USER = 0x4;
public const Int32 NIIF_NONE = 0x0;
public const Int32 NIIF_INFO = 0x1;
public const Int32 NIIF_WARNING = 0x2;
public const Int32 NIIF_ERROR = 0x3;
public const Int32 NIIF_LARGE_ICON = 0x20;
public enum NotifyFlags {
NIF_MESSAGE = 0x01,
NIF_ICON = 0x02,
NIF_TIP = 0x04,
NIF_INFO = 0x10,
NIF_STATE = 0x08,
NIF_GUID = 0x20,
NIF_SHOWTIP = 0x80
}
public enum NotifyCommand { NIM_ADD = 0x0, NIM_DELETE = 0x2, NIM_MODIFY = 0x1, NIM_SETVERSION = 0x4}
[StructLayout(LayoutKind.Sequential)]
public struct NOTIFYICONDATA
{
public Int32 cbSize;
public IntPtr hWnd;
public Int32 uID;
public NotifyFlags uFlags;
public Int32 uCallbackMessage;
public IntPtr hIcon;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public String szTip;
public Int32 dwState;
public Int32 dwStateMask;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public String szInfo;
public Int32 uVersion;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public String szInfoTitle;
public Int32 dwInfoFlags;
public Guid guidItem; //> IE 6
public IntPtr hBalloonIcon;
}
[DllImport("shell32.dll")]
public static extern System.Int32 Shell_NotifyIcon(NotifyCommand cmd, ref NOTIFYICONDATA data);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public Int32 left;
public Int32 top;
public Int32 right;
public Int32 bottom;
}
[StructLayout(LayoutKind.Sequential)]
public struct NOTIFYICONIDENTIFIER
{
public Int32 cbSize;
public IntPtr hWnd;
public Int32 uID;
public Guid guidItem;
}
//Works with Shell32.dll (version 6.1 or later)
[DllImport("shell32.dll", SetLastError = true)]
public static extern int Shell_NotifyIconGetRect([In]ref NOTIFYICONIDENTIFIER identifier, [Out]out RECT iconLocation);
添加图标:
//you only need this guid to identify your icon
private Guid guid;
//call only once to set the icon and create the guid.
private void AddIcon()
{
guid = Guid.NewGuid();
NOTIFYICONDATA data = new NOTIFYICONDATA();
data.cbSize = Marshal.SizeOf(data);
data.hWnd = this.Handle;
data.guidItem = guid;
data.uCallbackMessage = WM_MYMESSAGE; //This is the message sent to our app
data.hIcon = Properties.Resources.myIcon;
data.szTip = "Your text";
data.uFlags = NotifyFlags.NIF_ICON | NotifyFlags.NIF_GUID | NotifyFlags.NIF_MESSAGE | NotifyFlags.NIF_TIP |
NotifyFlags.NIF_SHOWTIP;
Shell_NotifyIcon(NotifyCommand.NIM_ADD, ref data);
data.uVersion = NOTIFYICON_VERSION_4;
Shell_NotifyIcon(NotifyCommand.NIM_SETVERSION, ref data);
}
获取图标在屏幕坐标中的位置:
private void GetRectIcon()
{
RECT rect = new RECT();
NOTIFYICONIDENTIFIER notifyIcon = new NOTIFYICONIDENTIFIER();
notifyIcon.cbSize = Marshal.SizeOf(notifyIcon);
//only guid is needed
notifyIcon.guidItem = guid;
int hresult = Shell_NotifyIconGetRect(ref notifyIcon, out rect);
//rect now has the position and size of icon
}
要删除通知图标,请执行以下操作:
private void DeleteIcon()
{
NOTIFYICONDATA data = new NOTIFYICONDATA();
data.cbSize = Marshal.SizeOf(data);
data.uFlags = NotifyFlags.NIF_GUID;
data.guidItem = guid;
Shell_NotifyIcon(NotifyCommand.NIM_DELETE, ref data);
}
添加阳台
private void AddBalloon()
{
NOTIFYICONDATA data;
data = new NOTIFYICONDATA();
data.cbSize = Marshal.SizeOf(data);
data.guidItem = guid;
//Set custom icon for balloon or NIIF_NONE for no icon. You can use all the other
//NIIF_... for system icons
data.dwInfoFlags = NIIF_USER;
data.hBalloonIcon = Properties.Resources.myNewIcon;
//text in balloon
data.szInfo = "My text in balloon";
//balloon title
data.szInfoTitle = "Balloon title";
//set the flags to be modified
data.uFlags = NotifyFlags.NIF_INFO | NotifyFlags.NIF_SHOWTIP | NotifyFlags.NIF_GUID;
Shell_NotifyIcon(NotifyCommand.NIM_MODIFY, ref data);
}
捕捉消息
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MYMESSAGE)
{
//(Int32)m.LParam & 0x0000FFFF get the low 2 bytes of LParam, we dont need the high ones.
//(Int32)m.WParam & 0x0000FFFF is the X coordinate and
//((Int32)m.WParam & 0xFFFF0000) >> 16 the Y
switch ((Int32)m.LParam & 0x0000FFFF)
{
case NIN_BALLOONHIDE:
break;
case NIN_BALLOONSHOW:
break;
case NIN_BALLOONTIMEOUT:
break;
case NIN_BALLOONUSERCLICK:
//user clicked on balloon
break;
case NIN_SELECT:
//user left click on icon
break;
case WM_CONTEXTMENU:
//user right click on icon
break;
//get what mouse messages you want
//case WM_LBUTTONDOWN:
//....
default:
break;
}
}
base.WndProc(ref m);
}
非托管代码的威力在γηράσκωδ'αεπολλάΔιδ的帮助下,我能够找到一个解决方案,让您使用标准的
通知图标
控件来确定图标的位置。它需要使用反射,因为它必须访问私有字段,因此依赖于NotifyIcon类的当前实现。我用.NETFramework2.0和4.0对它进行了测试
using System;
using System.Reflection;
using System.Windows.Forms;
using System.Runtime.InteropServices;
sealed class NotifyIconHelper
{
public static Rectangle GetIconRect(NotifyIcon icon)
{
RECT rect = new RECT();
NOTIFYICONIDENTIFIER notifyIcon = new NOTIFYICONIDENTIFIER();
notifyIcon.cbSize = Marshal.SizeOf(notifyIcon);
//use hWnd and id of NotifyIcon instead of guid is needed
notifyIcon.hWnd = GetHandle(icon);
notifyIcon.uID = GetId(icon);
int hresult = Shell_NotifyIconGetRect(ref notifyIcon, out rect);
//rect now has the position and size of icon
return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public Int32 left;
public Int32 top;
public Int32 right;
public Int32 bottom;
}
[StructLayout(LayoutKind.Sequential)]
private struct NOTIFYICONIDENTIFIER
{
public Int32 cbSize;
public IntPtr hWnd;
public Int32 uID;
public Guid guidItem;
}
[DllImport("shell32.dll", SetLastError = true)]
private static extern int Shell_NotifyIconGetRect([In]ref NOTIFYICONIDENTIFIER identifier, [Out]out RECT iconLocation);
private static FieldInfo windowField = typeof(NotifyIcon).GetField("window", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance);
private static IntPtr GetHandle(NotifyIcon icon)
{
if (windowField == null) throw new InvalidOperationException("[Useful error message]");
NativeWindow window = windowField.GetValue(icon) as NativeWindow;
if (window == null) throw new InvalidOperationException("[Useful error message]"); // should not happen?
return window.Handle;
}
private static FieldInfo idField = typeof(NotifyIcon).GetField("id", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance);
private static int GetId(NotifyIcon icon)
{
if (idField == null) throw new InvalidOperationException("[Useful error message]");
return (int)idField.GetValue(icon);
}
}
当然,操作系统可以做应用程序做不到的事情。你只能做操作系统允许你做的事情。这就是操作系统的工作原理。不管怎样,看起来那些老问题可能已经过时了。看:似乎是好消息,谢谢!,但我看到了同样的大问题,该函数中使用的结构需要一个notifyicon句柄和图标位置,我无法想象如何确定当前位置,更重要的是,如果notifyicon没有公开句柄,如何获取notifyicon的句柄,我想可能会涉及FindWindowEx和EnumChildWindows函数来确定所有图标中的哪个是我的图标,但是我需要搜索什么来关联此信息呢?。再次感谢!该函数的位置是一个out参数:这就是结果,您不需要传入它。看见不确定如何获取通知程序ID;您可以使用反射来访问,也可以扔掉NotifyIcon并通过pinvoke执行所有图标操作。首先,谢谢,但我问的是:“如何获取我的应用程序的NotifyIcon的位置/rect”,而不是“如何添加自定义图标并获取位置”,因为使用您建议的解决方案,我无法在应用程序中添加/使用NotifyIcon,因此我无法订阅NotifyIcon鼠标事件以了解何时需要显示contextmenu或ballontip事件。如果我错了,请重新解释我,让我知道如何使用它。无论如何,谢谢你@ElektroStudios这是同样的事情。用这种方法,你可以手工操作,而不是用“简单”的方法来使用设计器。。。我无法订阅NotifyIcon鼠标事件此示例只是获取矩形的一部分。当然,你可以得到鼠标事件和你想要的一切。我将编辑anwser@ElektroStudios终于编辑好了!我认为NIN_POPUPCLOSE的值不正确-在windows标题中,它被定义为:
\define NIN_POPUPCLOSE(WM_USER+7)