[英]Get ToolTip Text from Icon in System Tray
我正在嘗試從系統托盤中讀取不屬於我自己的應用程序的ToolTip文本。 基本上我認為最簡單的方法是獲取一些狀態信息。
使用C#提取ToolTip文本最簡單的方法是什么?
讓我們從找到systray窗口句柄開始:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr hWndChildAfter, string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
static IntPtr GetSystemTrayHandle()
{
IntPtr hWndTray = FindWindow("Shell_TrayWnd", null);
if (hWndTray != IntPtr.Zero)
{
hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "TrayNotifyWnd", null);
if (hWndTray != IntPtr.Zero)
{
hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "SysPager", null);
if (hWndTray != IntPtr.Zero)
{
hWndTray = FindWindowEx(hWndTray, IntPtr.Zero, "ToolbarWindow32", null);
return hWndTray;
}
}
}
return IntPtr.Zero;
}
Systray窗口是一個工具欄類,您需要獲取單個圖標的信息:
private static unsafe bool GetTBButton(IntPtr hToolbar, int i, ref TBBUTTON tbButton, ref string text, ref IntPtr ipWindowHandle)
{
// One page
const int BUFFER_SIZE = 0x1000;
byte[] localBuffer = new byte[BUFFER_SIZE];
UInt32 processId = 0;
UInt32 threadId = User32.GetWindowThreadProcessId(hToolbar, out processId);
IntPtr hProcess = Kernel32.OpenProcess(ProcessRights.ALL_ACCESS, false, processId);
if (hProcess == IntPtr.Zero) { Debug.Assert(false); return false; }
IntPtr ipRemoteBuffer = Kernel32.VirtualAllocEx(
hProcess,
IntPtr.Zero,
new UIntPtr(BUFFER_SIZE),
MemAllocationType.COMMIT,
MemoryProtection.PAGE_READWRITE);
if (ipRemoteBuffer == IntPtr.Zero) { Debug.Assert(false); return false; }
// TBButton
fixed (TBBUTTON* pTBButton = &tbButton)
{
IntPtr ipTBButton = new IntPtr(pTBButton);
int b = (int)User32.SendMessage(hToolbar, TB.GETBUTTON, (IntPtr)i, ipRemoteBuffer);
if (b == 0) { Debug.Assert(false); return false; }
// this is fixed
Int32 dwBytesRead = 0;
IntPtr ipBytesRead = new IntPtr(&dwBytesRead);
bool b2 = Kernel32.ReadProcessMemory(
hProcess,
ipRemoteBuffer,
ipTBButton,
new UIntPtr((uint)sizeof(TBBUTTON)),
ipBytesRead);
if (!b2) { Debug.Assert(false); return false; }
}
// button text
fixed (byte* pLocalBuffer = localBuffer)
{
IntPtr ipLocalBuffer = new IntPtr(pLocalBuffer);
int chars = (int)User32.SendMessage(hToolbar, TB.GETBUTTONTEXTW, (IntPtr)tbButton.idCommand, ipRemoteBuffer);
if (chars == -1) { Debug.Assert(false); return false; }
// this is fixed
Int32 dwBytesRead = 0;
IntPtr ipBytesRead = new IntPtr(&dwBytesRead);
bool b4 = Kernel32.ReadProcessMemory(
hProcess,
ipRemoteBuffer,
ipLocalBuffer,
new UIntPtr(BUFFER_SIZE),
ipBytesRead);
if (!b4) { Debug.Assert(false); return false; }
text = Marshal.PtrToStringUni(ipLocalBuffer, chars);
if (text == " ") text = String.Empty;
}
Kernel32.VirtualFreeEx(
hProcess,
ipRemoteBuffer,
UIntPtr.Zero,
MemAllocationType.RELEASE);
Kernel32.CloseHandle(hProcess);
return true;
}
現在,您所要做的就是遍歷按鈕並獲取數據:
IntPtr _ToolbarWindowHandle = GetSystemTrayHandle();
UInt32 count = User32.SendMessage(_ToolbarWindowHandle, TB.BUTTONCOUNT, 0, 0);
for (int i = 0; i < count; i++)
{
TBBUTTON tbButton = new TBBUTTON();
string text = String.Empty;
IntPtr ipWindowHandle = IntPtr.Zero;
bool b = GetTBButton(_ToolbarWindowHandle, i, ref tbButton, ref text, ref ipWindowHandle);
}
如果有人遇到這個線程並且有相同的需求,我發布了一個線程,詢問如何正確實現代碼示例並獲得了很多幫助,以及一個有效的解決方案:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.