/// <summary> /// Closes the tooltip /// </summary> private void CloseToolTip() { WINAPI.TOOLINFO ti = new WINAPI.TOOLINFO(); ti.cbSize = Marshal.SizeOf(ti.GetType()); ti.hwnd = GetHandler(moNotifyIcon); WINAPI.SendMessage(moNativeWindow.Handle, WINAPI.TTM_DELTOOL, 0, ref ti); OnBalloonTipClosed(this, EventArgs.Empty); moNativeWindow = new NativeWindow(); }
/// <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); }
/// <summary> /// Shows the ballon tooltip /// </summary> /// <param name="timeout"></param> public void ShowBalloonTip(int timeout) { //Check if a balloon already is shown or no user control was defined if (moNativeWindow.Handle != IntPtr.Zero || moPanel == null) return; //Get a handle for the notify icon IntPtr loNotifyIconHandle = GetHandler(moNotifyIcon); if (loNotifyIconHandle == IntPtr.Zero) return; //Trying to find notify icon rectangle on a desktop if (!GetNotifyIconScreenRect(loNotifyIconHandle)) return; //Create parameters for a new tooltip window System.Windows.Forms.CreateParams moCreateParams = new System.Windows.Forms.CreateParams(); // New window is a tooltip and a balloon moCreateParams.ClassName = WINAPI.TOOLTIPS_CLASS; moCreateParams.Style = WINAPI.WS_POPUP | WINAPI.TTS_NOPREFIX | WINAPI.TTS_ALWAYSTIP | WINAPI.TTS_BALLOON; moCreateParams.Parent = loNotifyIconHandle; // Create the tooltip window moNativeWindow.CreateHandle(moCreateParams); //We save old window proc to be used later and replac it our own IntPtr loNativeProc = WINAPI.SetWindowLong(moNativeWindow.Handle, WINAPI.GWL_WNDPROC, wpcallback); if (loNativeProc == IntPtr.Zero) return; if (WINAPI.SetProp(moNativeWindow.Handle, "NATIVEPROC", loNativeProc) == 0) return; // Make tooltip the top level window if (!WINAPI.SetWindowPos(moNativeWindow.Handle, WINAPI.HWND_TOPMOST, 0, 0, 0, 0, WINAPI.SWP_NOACTIVATE | WINAPI.SWP_NOSIZE)) return; // Tool tip info. Set a TRACK flag to show it in specified position WINAPI.TOOLINFO ti = new WINAPI.TOOLINFO(); ti.cbSize = Marshal.SizeOf(ti); ti.uFlags = WINAPI.TTF_TRACK; ti.hwnd = loNotifyIconHandle; //Approximating window size by use of char size WINAPI.SIZE size = new WINAPI.SIZE(); IntPtr hDC = WINAPI.GetDC(moNativeWindow.Handle); if (hDC == IntPtr.Zero) return; if (WINAPI.GetTextExtentPoint32(hDC, ".", 1, ref size) == 0) return; int lines = 1 + moPanel.Height / size.cy; int cols = moPanel.Width / size.cx; ti.lpszText = "."; for (int i = 0; i < lines; i++) { for (int j = 0; j < cols; j++) ti.lpszText += "."; ti.lpszText += "\r\n"; } //Add tool to the notify icon if (WINAPI.SendMessage(moNativeWindow.Handle, WINAPI.TTM_ADDTOOL, 0, ref ti) == 0) return; WINAPI.SendMessage(moNativeWindow.Handle, WINAPI.TTM_SETTIPBKCOLOR, ColorTranslator.ToWin32(Color.LightYellow), ref ti); WINAPI.SendMessage(moNativeWindow.Handle, WINAPI.TTM_SETTIPTEXTCOLOR, ColorTranslator.ToWin32(Color.Black), ref ti); WINAPI.SendMessage(moNativeWindow.Handle, WINAPI.TTM_SETDELAYTIME, Duration.AutoPop, 1000); WINAPI.SendMessage(moNativeWindow.Handle, WINAPI.TTM_TRACKPOSITION, 0, (moPosition.Y << 16) + moPosition.X); WINAPI.SendMessage(moNativeWindow.Handle, WINAPI.TTM_SETTITLE, (int)BalloonTipIcon, BalloonTipTitle); WINAPI.SendMessage(moNativeWindow.Handle, WINAPI.TTM_TRACKACTIVATE, 1, ref ti); // Raise shown event OnBalloonTipShown(this, EventArgs.Empty); // Timeout for the tooltip moTimer.Interval = timeout; moTimer.Start(); }