Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么不';t气球提示是否指向正确的控件?_C#_.net_Winforms_Textbox_Tooltip - Fatal编程技术网

C# 为什么不';t气球提示是否指向正确的控件?

C# 为什么不';t气球提示是否指向正确的控件?,c#,.net,winforms,textbox,tooltip,C#,.net,Winforms,Textbox,Tooltip,我正在表单上使用工具提示控件,但发现即使光标位于一个控件上,工具提示也会显示在其他地方。我想在我的光标所在的控件中显示它 如上图所示,当我的光标位于Textbox3上时,工具提示将显示在Textbox4上。我希望它能够指向Textbox3显示 我目前正在使用以下代码在3个不同的事件中显示工具提示: private void txtImmediateddest_Enter(object sender, EventArgs e) { ttpDetail.Show("Ex:111000

我正在表单上使用
工具提示
控件,但发现即使光标位于一个控件上,工具提示也会显示在其他地方。我想在我的光标所在的控件中显示它

如上图所示,当我的光标位于
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);
  }
编辑

这很好,但当鼠标最初放在控件上时,如果我第二次正确显示,它将显示正常

请看以下图片


您看到的问题是因为您的
工具提示
控件设置为“True”。设置此属性后,
工具提示不会更改其相对位置,从而导致引出序号的箭头指向错误的控件

下面是一个并排比较,展示了这种现象:

显然,简单的修复方法是通过将
IsBalloon
属性设置为“False”来禁用它。控件将恢复为显示标准的矩形工具提示窗口,该窗口看起来将正确对齐

如果您不能接受,则必须指定工具提示引出序号显示的确切位置。不幸的是,
工具提示
控件中似乎有一个bug,导致它在第一次附加到控件时无法正确显示。这通常可以通过使用空字符串调用一次
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);
}
产生以下结果:


当然,沿着这条路线你的运气也会有所不同。我通常不使用内置的
工具提示
控件来编辑控件(如文本框和组合框)。我发现P/Invoke更可靠,它指定并包含我想要显示的工具提示的信息。我将把查找适当的定义和编写包装器代码作为读者的一个练习,因为这个答案已经太长了。

嘿,我终于得到了这段代码

当老鼠离开

       public class MouseLeave
    {
        public void mouseLeave(TextBox txtTemp, ToolTip ttpTemp)
        {
            ttpTemp.Hide(txtTemp);
        }
    }
当鼠标滑过

    public class MouseOver
    {
        public void mouseOver(TextBox txtTemp, ToolTip ttpTemp)
        {
            switch (txtTemp.Name)
            {
                case "textBox1":
                    {

                        ttpTemp.AutoPopDelay = 2000;
                        ttpTemp.InitialDelay = 1000;
                        ttpTemp.ReshowDelay = 500;
                        ttpTemp.IsBalloon = true;
                        ttpTemp.SetToolTip(txtTemp, "Ex:01(Should be Numeric)");
                        ttpTemp.Show("Ex : 01(Should Be Numeric)", txtTemp, txtTemp.Width, txtTemp.Height / 10, 5000);
                    }
                    break;

                case "txtDetail":
                    {

                        ttpTemp.AutoPopDelay = 2000;
                        ttpTemp.InitialDelay = 1000;
                        ttpTemp.ReshowDelay = 500;
                        ttpTemp.IsBalloon = true;
                        ttpTemp.SetToolTip(txtTemp, "Ex:01(Should be Numeric)");
                        ttpTemp.Show("Ex : 01(Should Be Numeric)", txtTemp, txtTemp.Width, txtTemp.Height / 10, 5000);
                    }
                    break;
            }
        }
    }

您是否尝试在鼠标悬停事件中仅使用设置工具提示方法(不调用显示方法)

ttpTemp.SetToolTip(txtTemp,“Ex:01(应为数字)”


这对我来说很好(我使用的是管理C++,但我认为是一样的)。

< P>经过大量的故障排除,我发现代码BoLet比内置的气球工具提示更优秀。确保通过取消对清单文件中的依赖项的注释来启用视觉样式

在文本框上创建一个气球提示,如下所示:

new BalloonTip("Title", "Message", textBox1, BalloonTip.ICON.INFO, 5000);
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);
    }
}
并实现如下
balloottip

new BalloonTip("Title", "Message", textBox1, BalloonTip.ICON.INFO, 5000);
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);
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
使用System.Runtime.InteropServices;
名称空间库.Windows
{
类气球头
{
private System.Timers.Timer Timer=新的System.Timers.Timer();
私有信号量slim信号量=新信号量slim(1);
私人IntPtr hWnd;
公共气球提示(字符串文本、控件)
{
显示(“”,文本,控件);
}
公共气球提示(字符串标题、字符串文本、控件、图标图标=0、双超时=0、布尔焦点=false)
{
显示(标题、文本、控件、图标、超时、焦点);
}
无效显示(字符串标题、字符串文本、控件、图标图标=0、双超时=0、布尔焦点=false、短x=0、短y=0)
{
如果(x==0&&y==0)
{
x=(短)(control.RectangleToScreen(control.ClientRectangle.Left+control.Width/2);
y=(短)(control.RectangleToScreen(control.ClientRectangle.Top+control.Height/2);
}
TOOLINFO TOOLINFO=新的TOOLINFO();
toolInfo.cbSize=(uint)Marshal.SizeOf(toolInfo);
toolInfo.uFlags=0x20;//TTF\u轨迹
toolInfo.lpszText=文本;
IntPtr pToolInfo=Marshal.alloctaskmem(Marshal.SizeOf(toolInfo));
Marshal.StructureToPtr(toolInfo,pToolInfo,false);
byte[]buffer=Encoding.UTF8.GetBytes(title);
buffer=buffer.Concat(新字节[]{0}).ToArray();
IntPtr pszTitle=Marshal.alloctaskmem(buffer.Length);
Marshal.Copy(buffer,0,pszTitle,buffer.Length);
hWnd=User32.CreateWindowEx(0x8,“工具提示”\u class32“,”,0xC3,0,0,0,0,control.Parent.Handle,(IntPtr)0,(IntPtr)0,(IntPtr)0);
User32.SendMessage(hWnd,1028,(IntPtr)0,pToolInfo);//TTM_ADDTOOL
发送消息(hWnd,1042,(IntPtr)0,(IntPtr)((ushort)x |)((ushort)y 3:假定为一个hIcon;1057表示Unicode
User32.SendMessage(hWnd,1048,(IntPtr)0,(IntPtr)500);//TTM_SETMAXTIPWIDTH
User32.SendMessage(hWnd,0x40c,(IntPtr)0,pToolInfo);//TTM_UPDATETIPTEXT;0x439表示Unicode
User32.SendMessage(hWnd,1041,(IntPtr)1,pToolInfo);//TTM_TRACKACTIVATE
FreeCoTaskMem元帅(pszTitle);
结构(pToolInfo,typeof(toolnfo));
弗里科塔斯克梅姆元帅(托洛林福);
如果(焦点)
control.Focus();
//在用户更改焦点时,取消下面的注释以关闭引出序号,
//开始键入、调整/移动父窗口、最小化父窗口等
//根据显示引出序号提示的控件,调整要订阅的控件事件
/*控件。单击+=控件\事件;
控制。离开+=控制事件;
control.TextChanged+=control\u偶数