Dor*_*eka 7 .net c# textbox tooltip winforms
我ToolTip在我的表单上使用了一个控件,但是发现即使我的光标在一个控件上,工具提示也显示在其他地方.我想在我的光标所在的控件内显示这个.

如上图所示,当我的光标结束时Textbox3,工具提示正在显示Textbox4.我希望它显示指向Textbox3.
我目前正在使用以下代码在3个不同的事件中显示工具提示:
private void txtImmediateddest_Enter(object sender, EventArgs e)
{
ttpDetail.Show("Ex:111000025", txtImmediateddest);
}
private void txtImmediateddest_MouseHover(object sender, EventArgs e)
{
ttpDetail.Show("Ex:111000025", txtImmediateddest);
}
private void txtImmediateddest_MouseUp(object sender, MouseEventArgs e)
{
ttpDetail.Show("Ex:111000025", txtImmediateddest, e.Location);
//toolTipimmeddest.Show("Required & Must be 9 Digits", txtImmediateddest);
}
Run Code Online (Sandbox Code Playgroud)
编辑
private void textBox1_MouseHover(object sender, EventArgs e)
{
ttpDetail.AutoPopDelay = 2000;
ttpDetail.InitialDelay = 1000;
ttpDetail.ReshowDelay = 500;
ttpDetail.IsBalloon = true;
//ttpDetail.SetToolTip(textBox1, "Ex:01(Should be Numeric)");
ttpDetail.Show("Ex : 01(Should Be Numeric)", textBox1,textBox1.Width, textBox1.Height/10,5000);
}
Run Code Online (Sandbox Code Playgroud)
这工作正常,但当鼠标初始到控件时它显示正常,如果我有第二次它正确显示
请看下面的图片


Cod*_*ray 23
您看到的问题是因为您的ToolTip控件的IsBalloon属性设置为"True".设置此属性后,ToolTip不会更改其相对位置,导致气球的箭头指向错误的控件.
这是一个并排比较,展示了这种现象:

显然,简单的解决方法是通过将IsBalloon属性设置为"False" 来禁用该属性.控件将恢复显示标准的矩形工具提示窗口,该窗口将正确对齐.
如果您无法接受,则必须指定工具提示气球显示的确切位置.不幸的是,看起来ToolTip控件中存在一个错误,导致它在第一次连接到控件时不能正确显示.通常可以通过Show使用空字符串调用方法一次来修复此问题.例如,使用以下代码:
private void txtImmediateddest_Enter(object sender, EventArgs e)
{
ttpDetail.Show(string.Empty, textBox3, 0);
ttpDetail.Show("Ex:111000025", textBox3, textBox3.Width / 2, textBox3.Height, 5000);
}
Run Code Online (Sandbox Code Playgroud)
产生这个结果:

当然,你的运气也可能因这条路线而异.我通常不使用内置ToolTip控件进行编辑控件(例如文本框和组合框).我发现P/Invoke更可靠SendMessage,指定EM_SHOWBALLOONTIP和包含我想要显示的工具提示信息的EDITBALLOONTIP结构.我将留下查找适当的定义并将包装器代码编写为读者的练习,因为这个答案已经太久了.
经过大量的故障排除后,我发现下面的代码比内置气球工具提示优于网络.通过取消注释清单文件中的依赖项,确保启用了Visual Styles.
在TextBox上创建一个BalloonTip,如下所示:
new BalloonTip("Title", "Message", textBox1, BalloonTip.ICON.INFO, 5000);
Run Code Online (Sandbox Code Playgroud)
并实现BalloonTip如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Lib.Windows
{
class BalloonTip
{
private System.Timers.Timer timer = new System.Timers.Timer();
private SemaphoreSlim semaphore = new SemaphoreSlim(1);
private IntPtr hWnd;
public BalloonTip(string text, Control control)
{
Show("", text, control);
}
public BalloonTip(string title, string text, Control control, ICON icon = 0, double timeOut = 0, bool focus = false)
{
Show(title, text, control, icon, timeOut, focus);
}
void Show(string title, string text, Control control, ICON icon = 0, double timeOut = 0, bool focus = false, short x = 0, short y = 0)
{
if (x == 0 && y == 0)
{
x = (short)(control.RectangleToScreen(control.ClientRectangle).Left + control.Width / 2);
y = (short)(control.RectangleToScreen(control.ClientRectangle).Top + control.Height / 2);
}
TOOLINFO toolInfo = new TOOLINFO();
toolInfo.cbSize = (uint)Marshal.SizeOf(toolInfo);
toolInfo.uFlags = 0x20; // TTF_TRACK
toolInfo.lpszText = text;
IntPtr pToolInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(toolInfo));
Marshal.StructureToPtr(toolInfo, pToolInfo, false);
byte[] buffer = Encoding.UTF8.GetBytes(title);
buffer = buffer.Concat(new byte[] { 0 }).ToArray();
IntPtr pszTitle = Marshal.AllocCoTaskMem(buffer.Length);
Marshal.Copy(buffer, 0, pszTitle, buffer.Length);
hWnd = User32.CreateWindowEx(0x8, "tooltips_class32", "", 0xC3, 0, 0, 0, 0, control.Parent.Handle, (IntPtr)0, (IntPtr)0, (IntPtr)0);
User32.SendMessage(hWnd, 1028, (IntPtr)0, pToolInfo); // TTM_ADDTOOL
User32.SendMessage(hWnd, 1042, (IntPtr)0, (IntPtr)((ushort)x | ((ushort)y << 16))); // TTM_TRACKPOSITION
//User32.SendMessage(hWnd, 1043, (IntPtr)0, (IntPtr)0); // TTM_SETTIPBKCOLOR
//User32.SendMessage(hWnd, 1044, (IntPtr)0xffff, (IntPtr)0); // TTM_SETTIPTEXTCOLOR
User32.SendMessage(hWnd, 1056, (IntPtr)icon, pszTitle); // TTM_SETTITLE 0:None, 1:Info, 2:Warning, 3:Error, >3:assumed to be an hIcon. ; 1057 for Unicode
User32.SendMessage(hWnd, 1048, (IntPtr)0, (IntPtr)500); // TTM_SETMAXTIPWIDTH
User32.SendMessage(hWnd, 0x40c, (IntPtr)0, pToolInfo); // TTM_UPDATETIPTEXT; 0x439 for Unicode
User32.SendMessage(hWnd, 1041, (IntPtr)1, pToolInfo); // TTM_TRACKACTIVATE
Marshal.FreeCoTaskMem(pszTitle);
Marshal.DestroyStructure(pToolInfo, typeof(TOOLINFO));
Marshal.FreeCoTaskMem(pToolInfo);
if (focus)
control.Focus();
// uncomment bellow to make balloon close when user changes focus,
// starts typing, resizes/moves parent window, minimizes parent window, etc
// adjust which control events to subscribe to depending on the control over which the balloon tip is shown
/*control.Click += control_Event;
control.Leave += control_Event;
control.TextChanged += control_Event;
control.LocationChanged += control_Event;
control.SizeChanged += control_Event;
control.VisibleChanged += control_Event;
Control parent = control.Parent;
while(parent != null)
{
parent.VisibleChanged += control_Event;
parent = parent.Parent;
}
control.TopLevelControl.LocationChanged += control_Event;
((Form)control.TopLevelControl).Deactivate += control_Event;*/
timer.AutoReset = false;
timer.Elapsed += timer_Elapsed;
if (timeOut > 0)
{
timer.Interval = timeOut;
timer.Start();
}
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Close();
}
void control_Event(object sender, EventArgs e)
{
Close();
}
void Close()
{
if (!semaphore.Wait(0)) // ensures one time only execution
return;
timer.Elapsed -= timer_Elapsed;
timer.Close();
User32.SendMessage(hWnd, 0x0010, (IntPtr)0, (IntPtr)0); // WM_CLOSE
//User32.SendMessage(hWnd, 0x0002, (IntPtr)0, (IntPtr)0); // WM_DESTROY
//User32.SendMessage(hWnd, 0x0082, (IntPtr)0, (IntPtr)0); // WM_NCDESTROY
}
[StructLayout(LayoutKind.Sequential)]
struct TOOLINFO
{
public uint cbSize;
public uint uFlags;
public IntPtr hwnd;
public IntPtr uId;
public RECT rect;
public IntPtr hinst;
[MarshalAs(UnmanagedType.LPStr)]
public string lpszText;
public IntPtr lParam;
}
[StructLayout(LayoutKind.Sequential)]
struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
public enum ICON
{
NONE,
INFO,
WARNING,
ERROR
}
}
static class User32
{
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
[DllImportAttribute("user32.dll")]
public static extern IntPtr CreateWindowEx(uint dwExStyle, string lpClassName, string lpWindowName, uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr LPVOIDlpParam);
}
}
Run Code Online (Sandbox Code Playgroud)
这是它的样子:
