/// <summary> /// Gets the NotifyIcon rectangle /// </summary> /// <param name="handle">Handle of the NotifyIcon</param> /// <returns></returns> private bool GetNotifyIconScreenRect(IntPtr handle) { WINAPI.RECT loNotifyIconRecr = new WINAPI.RECT(); if (handle == IntPtr.Zero) { return false; } // Find tray window IntPtr hWndTray = WINAPI.FindWindowEx(IntPtr.Zero, IntPtr.Zero, "Shell_TrayWnd", 0); if (hWndTray == IntPtr.Zero) return false; // Find SysTray toolbar WINAPI.EnumChildWindowsCallback callback = new WINAPI.EnumChildWindowsCallback(EnumChildWindowsFunc); WINAPI.EnumChildWindows(hWndTray, callback, 0); if (!mFound) return false; mFound = false; hWndTray = mHWndNotify; // Get a NotifyIcon rectangle and a tip position if (WINAPI.GetWindowRect(handle, ref loNotifyIconRecr) == 0) return false; if (WINAPI.MapWindowPoints(hWndTray, IntPtr.Zero, ref loNotifyIconRecr, 2) == 0) return false; // Here we should analyze where SysTray happens to be - up, left, right or bottom moPosition.X = loNotifyIconRecr.left; moPosition.Y = loNotifyIconRecr.top; return true; }
/// <summary> /// Tooltip window proc /// </summary> /// <param name="hWnd"></param> /// <param name="iMsg"></param> /// <param name="wParam"></param> /// <param name="lParam"></param> /// <returns></returns> protected int WindowProc(IntPtr hWnd, UInt32 iMsg, IntPtr wParam, IntPtr lParam) { int height = 0; int width = 0; IntPtr nativeProc = WINAPI.GetProp(hWnd, "NATIVEPROC"); if (iMsg == WINAPI.WM_PAINT) { // Drow the original tooltip int liWinProcResult = WINAPI.CallWindowProc(nativeProc, hWnd, iMsg, wParam, lParam); WINAPI.TOOLINFO ti = new WINAPI.TOOLINFO(); ti.cbSize = Marshal.SizeOf(ti.GetType()); ti.hwnd = GetHandler(moNotifyIcon); if (ti.hwnd != IntPtr.Zero) { // Create graphics object for the tooltip Graphics loGraphics = Graphics.FromHwnd(hWnd); WINAPI.RECT rect = new WINAPI.RECT(); WINAPI.RECT rect1 = new WINAPI.RECT(); WINAPI.GetWindowRect(hWnd, ref rect); // In rect1 - tooltip rectangle // Calculate text display rectangle to rect rect1 = rect; WINAPI.SendMessage(hWnd, WINAPI.TTM_ADJUSTRECT, 0, out rect); // Width and heigth of the text area width = rect.right - rect.left; height = rect.bottom - rect.top; //Calculate iner rectangle of the text area rect.left = rect.left - rect1.left; rect.top = rect.top - rect1.top; rect.right = rect.left + width; rect.bottom = rect.top + height; //Clear text area: 16 pixs - header, 30 pixs from bottom loGraphics.FillRectangle(new SolidBrush(Color.LightYellow), new Rectangle(rect.left, rect.top + 16, width, height-30)); //Add close button and click handler // 16 pixs for the button control moCloseButton.Location = new System.Drawing.Point(rect.right - 16, rect.top); moCloseButton.AutoSize = false; moCloseButton.Click += CloseButtonClick; WINAPI.SetParent(moCloseButton.Handle, hWnd); //Adding panel to the tooltip below the header moPanel.Location = new Point(rect.left, rect.top + 16); WINAPI.SetParent(moPanel.Handle, hWnd); loGraphics = null; } return liWinProcResult; } return WINAPI.CallWindowProc(nativeProc, hWnd, iMsg, wParam, lParam); }