public static ApplicationWindow GetNthApplicationWindowOnNotificationArea(IntPtr notificationAreaHwnd, int i) { TBBUTTON tbButton = new TBBUTTON(); string text = String.Empty; IntPtr ipWindowHandle = IntPtr.Zero; NotificationAreaWindow notificationAreaWindow; bool b = User32.GetTBButton(notificationAreaHwnd, i, ref tbButton, ref text, ref ipWindowHandle, out notificationAreaWindow); if (!b) return null; //if (!User32.KeepWindowHandleInAltTabList(notificationAreaWindow.MainWindowHandle)) //return null; /*if (hash.Contains(notificationAreaWindow.MainWindowHandle)) return null; hash.Add(notificationAreaWindow.MainWindowHandle);*/ uint processId = 0; User32.GetWindowThreadProcessId(notificationAreaWindow.MainWindowHandle, out processId); if (processId == 0) return null; if (processId == App.ProcessId) return null; var fileName = User32.GetWindowModuleFileNameFromHandle(notificationAreaWindow.MainWindowHandle); if (fileName.ToLower().EndsWith("explorer.exe")) return null; var window = new ApplicationWindow((int)processId, fileName, notificationAreaWindow); return window; }
public static unsafe bool GetTBButton(IntPtr hToolbar, int i, ref TBBUTTON tbButton, ref string text, ref IntPtr ipWindowHandle, out NotificationAreaWindow notificationAreaWindow) { notificationAreaWindow = new NotificationAreaWindow(); // One page const int BUFFER_SIZE = 0x1000; byte[] localBuffer = new byte[BUFFER_SIZE]; uint 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; } 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; } 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; } // window handle fixed (byte* pLocalBuffer = localBuffer) { IntPtr ipLocalBuffer = new IntPtr(pLocalBuffer); Int32 dwBytesRead = 0; IntPtr ipBytesRead = new IntPtr(&dwBytesRead); var ipRemoteData = tbButton.dwData; bool b4 = Kernel32.ReadProcessMemory( hProcess, ipRemoteData, ipLocalBuffer, new UIntPtr(4), ipBytesRead); if (!b4) { Debug.Assert(false); return false; } if (dwBytesRead != 4) { Debug.Assert(false); return false; } Int32 iWindowHandle = BitConverter.ToInt32(localBuffer, 0); if (iWindowHandle == -1) { Debug.Assert(false); }//return false; } ipWindowHandle = new IntPtr(iWindowHandle); } var rect = default(RECT); uint dwTrayProcessID = 0; GetWindowThreadProcessId(hToolbar, out dwTrayProcessID); if (dwTrayProcessID <= 0) { return false; } IntPtr hTrayProc = Kernel32.OpenProcess(PROCESS_ALL_ACCESS, 0, dwTrayProcessID); if (hTrayProc == IntPtr.Zero) { return false; } IntPtr lpData = Kernel32.VirtualAllocEx(hTrayProc, IntPtr.Zero, Marshal.SizeOf(tbButton.GetType()), MEM_COMMIT, PAGE_READWRITE); if (lpData == IntPtr.Zero) { Kernel32.CloseHandle(hTrayProc); return false; } // Show tray icon if hidden //if ((tbButton.fsState & (byte)TBSTATE_HIDDEN) == (byte)TBSTATE_HIDDEN) SendMessage(hToolbar, TB_HIDEBUTTON, tbButton.idCommand, 1); // Get rectangle of tray icon Int32 dwBytesRead2 = -1; var rectNotifyIcon = new RECT(0, 0, 0, 0); byte[] byteBuffer3 = new byte[Marshal.SizeOf(rectNotifyIcon.GetType())]; SendMessage(hToolbar, TB.GETITEMRECT, tbButton.idCommand, lpData); Kernel32.ReadProcessMemory(hTrayProc, lpData, byteBuffer3, Marshal.SizeOf(rectNotifyIcon.GetType()), out dwBytesRead2); if (dwBytesRead2 < Marshal.SizeOf(rectNotifyIcon.GetType())) { return false; } IntPtr ptrOut2 = Marshal.AllocHGlobal(Marshal.SizeOf(rectNotifyIcon.GetType())); Marshal.Copy(byteBuffer3, 0, ptrOut2, byteBuffer3.Length); rectNotifyIcon = (RECT)Marshal.PtrToStructure(ptrOut2, typeof(RECT)); //MapWindowPoints(hToolbar, IntPtr.Zero, ref rectNotifyIcon, 2); // Display coordinates var c = GetRect(hToolbar); System.Diagnostics.Debug.Print("{4} ICONS COORDINATES ARE: Top: {0}, Left: {1}, Bottom: {2}, Right: {3}", rectNotifyIcon.Top - c.Top, rectNotifyIcon.Left - c.Left, (rectNotifyIcon.Bottom - c.Bottom) + rectNotifyIcon.Height, rectNotifyIcon.Right - c.Right, text); Kernel32.VirtualFreeEx(hTrayProc, lpData, UIntPtr.Zero, MEM_RELEASE); Kernel32.CloseHandle(hTrayProc); rect = new RECT( rectNotifyIcon.Left - c.Left, rectNotifyIcon.Top - c.Top, rectNotifyIcon.Right - c.Right, (rectNotifyIcon.Bottom - c.Bottom) + rectNotifyIcon.Height); Kernel32.VirtualFreeEx( hProcess, ipRemoteBuffer, UIntPtr.Zero, MemAllocationType.RELEASE); Kernel32.CloseHandle(hProcess); notificationAreaWindow = new NotificationAreaWindow() { TBBUTTON = tbButton, MainWindowHandle = ipWindowHandle, ToolBarIconHandle = hToolbar, Text = text, RECT = rect }; return true; }