Multiple unassigned tooltips question
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 17

Thread: Multiple unassigned tooltips question

  1. #1
    Join Date
    Mar 2009
    Posts
    8

    Multiple unassigned tooltips question

    My idea was to create a simple function to add/relocate/remove up to 30 unassigned tooltips. My experience in C# is about a month and the only idea how to make it was taken from autohotkey code and translated to C#. The code below is able to create and remove tooltips, but width of each tooltip equal ONE character. How to fix this bug?
    Code:
    using System;
    using System.Runtime.InteropServices;
    
    namespace ToolTipTest
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                ToolTip.CoordMode(false); //we can define screen coordinates or active window relative coordinates, false is screen coordinates
                ToolTip.Show("111", 0, 0, 1); //adding tooltip number 1 with "111" at x=0,y=0 of a screen
                System.Threading.Thread.Sleep(1000);
                ToolTip.Show("222", 20, 20, 2); //adding tooltip number 2 with "222" at x=20,y=20 of a screen
                System.Threading.Thread.Sleep(1000);
                ToolTip.Remove(1); //removing tooltip 1
                System.Threading.Thread.Sleep(1000);
                ToolTip.Show("", null, null, 2); //removing tooltip 2 (another method)
                System.Threading.Thread.Sleep(3000);
    
            }
        }
    
        public struct ToolTip
        {
            #region API
            [DllImport("User32.dll", SetLastError = true)]
            private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref TOOLINFO lParam);
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
    
            [DllImport("User32.dll", SetLastError = true)]
            private static extern int GetClientRect(IntPtr hWnd, ref RECT lpRect);
    
            [DllImport("User32.dll", SetLastError = true)]
            private static extern bool SetWindowPos(
                IntPtr hWnd,
                IntPtr hWndInsertAfter,
                int X,
                int Y,
                int cx,
                int cy,
                int uFlags);
    
            [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
            private static extern int GetSystemMetrics(int sysMetric);
    
            [DllImport("user32.dll", EntryPoint = "IsWindow")]
            private static extern bool IsWindow(IntPtr hWnd);
    
            [DllImport("user32.dll", EntryPoint = "GetWindowRect")]
            private static extern bool GetWindowRect(IntPtr handle, out RECT rect);
    
            [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
            private static extern IntPtr GetDesktopWindow();
    
            [DllImport("user32.dll", EntryPoint = "GetCursorPos")]
            private static extern int GetCursorPos(out POINTAPI point);
    
            [DllImport("user32.dll", EntryPoint = "GetForegroundWindow")]
            private static extern IntPtr GetForegroundWindow();
    
            [DllImport("user32.dll", EntryPoint = "CreateWindowEx")]
            private static extern IntPtr CreateWindowEx(
                int dwExStyle,
                string lpClassName,
                string lpWindowName,
                uint dwStyle,
                int x,
                int y,
                int nWidth,
                int nHeight,
                IntPtr hWndParent,
                IntPtr hMenu,
                IntPtr hInstance,
                IntPtr lpParam);
    
            private const ushort WM_USER = 0x0400;
            private const byte WS_EX_TOPMOST = 0x0008;
            private const int CW_USEDEFAULT = unchecked((int)0x80000000);
            private const byte TTS_ALWAYSTIP = 0x01;
            private const byte TTS_NOPREFIX = 0x02;
            private const byte TTF_TRACK = 0x0020;
            private const ushort TTM_ADDTOOLA = (WM_USER + 4);
            private const ushort TTM_UPDATETIPTEXT = (WM_USER + 12);
            private const ushort TTM_TRACKACTIVATE = (WM_USER + 17);
            private const ushort TTM_TRACKPOSITION = (WM_USER + 18);
            private const ushort TTM_SETMAXTIPWIDTH = (WM_USER + 24);
    
            private const int SM_CXVIRTUALSCREEN = 78;
            private const int SM_XVIRTUALSCREEN = 76;
            private const int SM_YVIRTUALSCREEN = 77;
            private const int SM_CYVIRTUALSCREEN = 79;
            private const int SM_CXSCREEN = 0;
    
            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int left;
                public int top;
                public int right;
                public int bottom;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct POINTAPI
            {
                public int x;
                public int y;
            }
    
            #endregion
    
            private static bool winClose(IntPtr hWnd)
            {
                if (hWnd != IntPtr.Zero)
                {
                    //WM_CLOSE = 0x10
                    SendMessage(hWnd, 0x10, 0, 0);
                    return true;
                }
                return false;
            }
    
            private static void GetVirtualDesktopRect(out RECT aRect)
            {
                aRect.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
                if (aRect.right != 0) // A non-zero value indicates the OS supports multiple monitors or at least SM_CXVIRTUALSCREEN.
                {
                    aRect.left = GetSystemMetrics(SM_XVIRTUALSCREEN);  // Might be negative or greater than zero.
                    aRect.right += aRect.left;
                    aRect.top = GetSystemMetrics(SM_YVIRTUALSCREEN);   // Might be negative or greater than zero.
                    aRect.bottom = aRect.top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
                }
                else // Win95/NT do not support SM_CXVIRTUALSCREEN and such, so zero was returned.
                    GetWindowRect(GetDesktopWindow(), out aRect);
            }
            
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
            struct TOOLINFO
            {
                public int cbSize;
                public int uFlags;
                public IntPtr hwnd;
                public IntPtr uId;
                public RECT rect;
                public IntPtr hinst;
                [MarshalAs(UnmanagedType.LPTStr)]
                public String lpszText;
                public IntPtr lParam;
            }
    
            private static bool ToolTipCoordMode = true; //default coord mode - relative
            public static void CoordMode(bool if_screen_then_false)
            {
                ToolTipCoordMode = if_screen_then_false;
            }
    
            private static int MAKELONG(int wLow, int wHigh)
            {
                int low = (int)LOWORD(wLow);
                short high = LOWORD(wHigh);
                int product = 0x00010000 * (int)high;
                int makeLong = (int)(low | product);
                return makeLong;
            }
            private static short LOWORD(int dw)
            {
                short loWord = 0;
                ushort andResult = (ushort)(dw & 0x00007FFF);
                ushort mask = 0x8000;
                if ((dw & 0x8000) != 0)
                {
                    loWord = (short)(mask | andResult);
                }
                else
                {
                    loWord = (short)andResult;
                }
                return loWord;
            }
    
            private static IntPtr[] g_hWndToolTip = new IntPtr[30]; //pointers to 30 tooltips
    
            public static bool Remove(int aID) // remove tooltip with aID
            {
                return Show("", null, null, aID);
            }
    
            public static bool Show(string aText, System.Nullable<int> aX, System.Nullable<int> aY, System.Nullable<int> aID) // create or modify tooltip
            {
                int window_index = 0;
                if (aID.HasValue) { window_index = (int)(aID) - 1; }
                if (window_index < 0 | window_index >= 30) return false;
                IntPtr tip_hwnd = g_hWndToolTip[window_index];
    
                if (aText == "")
                {
                    if (tip_hwnd != IntPtr.Zero & IsWindow(tip_hwnd))
                    {
                        winClose(tip_hwnd);
                    }
                    g_hWndToolTip[window_index] = IntPtr.Zero;
                    return true;
                }
    
                RECT dtw = new RECT();
                GetVirtualDesktopRect(out dtw);
    
                bool one_or_both_coords_unspecified = (!aX.HasValue | !aY.HasValue);
                POINTAPI pt = new POINTAPI();
                POINTAPI pt_cursor = new POINTAPI();
    
                if (one_or_both_coords_unspecified)
                {
                    GetCursorPos(out pt_cursor);
                    pt.x = pt_cursor.x + 16;  // Set default spot to be near the mouse cursor.
                    pt.y = pt_cursor.y + 16;  // Use 16 to prevent the tooltip from overlapping large cursors.
                }
                RECT rect = new RECT();
    
                if ((aX.HasValue | aY.HasValue) & ToolTipCoordMode)
                {
                    if (!GetWindowRect(GetForegroundWindow(), out rect))
                        return true;
                }
                // This will convert from relative to screen coordinates if rect contains non-zero values:
                if (aX.HasValue)
                    pt.x = (int)aX + (int)rect.left;
                if (aY.HasValue)
                    pt.y = (int)aY + (int)rect.top;
    
                TOOLINFO ti = new TOOLINFO();
    
                //ti.cbSize = Marshal.SizeOf(ti) - Marshal.SizeOf(typeof(void*)); //as in original autohotkey code
                ti.cbSize = Marshal.SizeOf(ti); //another version which is also working
                ti.uFlags = TTF_TRACK;
                ti.lpszText = aText;
                
                if (tip_hwnd == IntPtr.Zero | !IsWindow(tip_hwnd))
                {
                    
                    tip_hwnd = g_hWndToolTip[window_index] = CreateWindowEx(WS_EX_TOPMOST, "tooltips_class32", "", TTS_NOPREFIX | TTS_ALWAYSTIP
                                , CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
                    SendMessage(tip_hwnd, TTM_ADDTOOLA, 0, ref ti);
                    // v1.0.21: GetSystemMetrics(SM_CXSCREEN) is used for the maximum width because even on a
                    // multi-monitor system, most users would not want a tip window to stretch across multiple monitors:
                    SendMessage(tip_hwnd, TTM_SETMAXTIPWIDTH, 0, GetSystemMetrics(SM_CXSCREEN));
                    // Must do these next two when the window is first created, otherwise GetWindowRect() below will retrieve
                    // a tooltip window size that is quite a bit taller than it winds up being:
    
                    SendMessage(tip_hwnd, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y));
                    SendMessage(tip_hwnd, TTM_TRACKACTIVATE, 1, ref ti);
                }
    
                SendMessage(tip_hwnd, TTM_UPDATETIPTEXT, 0, ref ti);
    
                RECT ttw = new RECT();
                GetWindowRect(tip_hwnd, out ttw); // Must be called this late to ensure the tooltip has been created by above.
                int tt_width = ttw.right - ttw.left;
                int tt_height = ttw.bottom - ttw.top;
    
                // v1.0.21: Revised for multi-monitor support.  I read somewhere that dtw.left can be negative (perhaps
                // if the secondary monitor is to the left of the primary).  So it seems best to assume it is possible:
                if (pt.x + tt_width >= dtw.right)
                    pt.x = dtw.right - tt_width - 1;
                if (pt.y + tt_height >= dtw.bottom)
                    pt.y = dtw.bottom - tt_height - 1;
    
                if (one_or_both_coords_unspecified)
                {
                    // Since Tooltip is being shown at the cursor's coordinates, try to ensure that the above
                    // adjustment doesn't result in the cursor being inside the tooltip's window boundaries,
                    // since that tends to cause problems such as blocking the tray area (which can make a
                    // tootip script impossible to terminate).  Normally, that can only happen in this case
                    // (one_or_both_coords_unspecified == true) when the cursor is near the buttom-right
                    // corner of the screen (unless the mouse is moving more quickly than the script's
                    // ToolTip update-frequency can cope with, but that seems inconsequential since it
                    // will adjust when the cursor slows down):
                    ttw.left = pt.x;
                    ttw.top = pt.y;
                    ttw.right = ttw.left + tt_width;
                    ttw.bottom = ttw.top + tt_height;
                    if ((pt_cursor.x >= ttw.left) & (pt_cursor.x <= ttw.right) & (pt_cursor.y >= ttw.top) & (pt_cursor.y <= ttw.bottom))
                    {
                        // Push the tool tip to the upper-left side, since normally the only way the cursor can
                        // be inside its boundaries (when one_or_both_coords_unspecified == true) is when the
                        // cursor is near the bottom right corner of the screen.
                        pt.x = pt_cursor.x - tt_width - 3;    // Use a small offset since it can't overlap the cursor
                        pt.y = pt_cursor.y - tt_height - 3;   // when pushed to the the upper-left side of it.
                    }
                }
                SendMessage(tip_hwnd, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y));
                // And do a TTM_TRACKACTIVATE even if the tooltip window already existed upon entry to this function,
                // so that in case it was hidden or dismissed while its HWND still exists, it will be shown again:
                SendMessage(tip_hwnd, TTM_TRACKACTIVATE, 1, ref ti);
                return true;
            }
        }
    }

  2. #2
    Join Date
    May 2007
    Posts
    1,546

    Re: Multiple unassigned tooltips question

    Would the ToolTip (http://msdn.microsoft.com/en-us/libr...ltip.show.aspx) class not be a better choice?
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  3. #3
    Join Date
    Mar 2009
    Posts
    8

    Re: Multiple unassigned tooltips question

    I am trying any choices, API coding is not requirement. But I want to make a module which is working all the time independently on what we are trying to code (console application or library or windows forms application).

    I have a problem with tooltip class also. To show tooltip I need a handle to IWin32Window. I am using some process and trying to wrap the handle of the process in a class that implements IWin32Window to use it with ToolTip.

    Code:
    private class WindowWrapper : System.Windows.Forms.IWin32Window
    {
        public WindowWrapper(IntPtr handle)
        {
           _hwnd = handle;
        }
    
        public IntPtr Handle
        {
            get { return _hwnd; }
        }
    
        private IntPtr _hwnd;
    }
    
    public Show (string aText, int X, int Y, int iD)
    {
    //...code...till creation of a tooltip, then:
                   System.Windows.Forms.ToolTip tooltip = new System.Windows.Forms.ToolTip();
                   Process proc = Process.GetCurrentProcess();
                   IntPtr hwnd = proc.MainWindowHandle;
                   WindowWrapper window = new WindowWrapper(hwnd); //IWin32Window wrapper
                   tooltip.Show(aText, window);
                   MessageBox.Show(window, "Test");
    
    //another block of the code
    // ...
    //
    }
    In this variant MessageBox accepts "window" without a problem, tooltip doesnot. I have nullreference exception. Can you suggest me a method how to create unassigned to any control tooltips or assigned to desktop/process etc.

  4. #4
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Multiple unassigned tooltips question

    Almost every control implementsIWin32Window. Tooltips are very easy to use in .NET, you don't need to make it more complicated than it is.

    Code:
    class Form1
    {
        public Form1
        {
            ToolTip toolTip1 = new ToolTip();
            toolTip1.Show("I am a tooltip", this);
        }
    }

  5. #5
    Join Date
    Mar 2009
    Posts
    8

    Re: Multiple unassigned tooltips question

    Error 3 Argument '2': cannot convert from 'ToolTipTest.ToolTip' to 'System.Windows.Forms.IWin32Window'

    Probably my custom ToolTip class is not a control. I need a ToolTip code for example in dll. I can use two commands ToolTip.Show and ToolTip.Remove to show and remove tooltips where I want and when I want. Is it possible to make with C#?
    Last edited by Slav2; March 9th, 2009 at 01:05 PM.

  6. #6
    Join Date
    May 2007
    Posts
    1,546

    Re: Multiple unassigned tooltips question

    Paste the actual code you're compiling. I bet 'this' doesn't refer to an object which inherits from System.Windows.Forms.Form.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  7. #7
    Join Date
    Mar 2009
    Posts
    8

    Re: Multiple unassigned tooltips question

    Posted, but it is just a draft on the moment of posting. I have commented another lines with errors to look later.

    1. Task is to make tooltip in front of any active window or just on desktop depending on coordmode (screen, relative).
    2. Any X, Y, coordinate (also relative to active window or screen)



    Code:
    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    
    namespace ToolTipTest
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                ToolTip tt = new ToolTip();
                //tt.CoordMode(false);
                tt.Show("111", 0, 0, 1);
                System.Threading.Thread.Sleep(1000);
                tt.Show("222", 20, 20, 2);
                System.Threading.Thread.Sleep(1000);
                //tt.Remove(1);
                System.Threading.Thread.Sleep(1000);
                tt.Show("", null, null, 2);
                System.Threading.Thread.Sleep(3000);
    
            }
        }
    
        public class ToolTip
        {
            #region API
            //[DllImport("User32.dll", SetLastError = true)]
            //private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref TOOLINFO lParam);
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
    
            [DllImport("User32.dll", SetLastError = true)]
            private static extern int GetClientRect(IntPtr hWnd, ref RECT lpRect);
    
            [DllImport("User32.dll", SetLastError = true)]
            private static extern bool SetWindowPos(
                IntPtr hWnd,
                IntPtr hWndInsertAfter,
                int X,
                int Y,
                int cx,
                int cy,
                int uFlags);
    
            [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
            private static extern int GetSystemMetrics(int sysMetric);
    
            [DllImport("user32.dll", EntryPoint = "IsWindow")]
            private static extern bool IsWindow(IntPtr hWnd);
    
            [DllImport("user32.dll", EntryPoint = "GetWindowRect")]
            private static extern bool GetWindowRect(IntPtr handle, out RECT rect);
    
            [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
            private static extern IntPtr GetDesktopWindow();
    
            [DllImport("user32.dll", EntryPoint = "GetCursorPos")]
            private static extern int GetCursorPos(out POINTAPI point);
    
            [DllImport("user32.dll", EntryPoint = "GetForegroundWindow")]
            private static extern IntPtr GetForegroundWindow();
    
            [DllImport("user32.dll", EntryPoint = "CreateWindowEx")]
            private static extern IntPtr CreateWindowEx(
                int dwExStyle,
                string lpClassName,
                string lpWindowName,
                uint dwStyle,
                int x,
                int y,
                int nWidth,
                int nHeight,
                IntPtr hWndParent,
                IntPtr hMenu,
                IntPtr hInstance,
                IntPtr lpParam);
    
            private const ushort WM_USER = 0x0400;
            private const byte WS_EX_TOPMOST = 0x0008;
            private const int CW_USEDEFAULT = unchecked((int)0x80000000);
            private const byte TTS_ALWAYSTIP = 0x01;
            private const byte TTS_NOPREFIX = 0x02;
            private const byte TTF_TRACK = 0x0020;
            private const ushort TTM_ADDTOOLA = (WM_USER + 4);
            private const ushort TTM_UPDATETIPTEXT = (WM_USER + 12);
            private const ushort TTM_TRACKACTIVATE = (WM_USER + 17);
            private const ushort TTM_TRACKPOSITION = (WM_USER + 18);
            private const ushort TTM_SETMAXTIPWIDTH = (WM_USER + 24);
    
            private const int SM_CXVIRTUALSCREEN = 78;
            private const int SM_XVIRTUALSCREEN = 76;
            private const int SM_YVIRTUALSCREEN = 77;
            private const int SM_CYVIRTUALSCREEN = 79;
            private const int SM_CXSCREEN = 0;
    
            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int left;
                public int top;
                public int right;
                public int bottom;
            }
    
            [StructLayout(LayoutKind.Sequential)]
            private struct POINTAPI
            {
                public int x;
                public int y;
            }
            #endregion
    
            private static bool winClose(IntPtr hWnd)
            {
                if (hWnd != IntPtr.Zero)
                {
                    //WM_CLOSE = 0x10
                    SendMessage(hWnd, 0x10, 0, 0);
                    return true;
                }
                return false;
            }
    
            private static void GetVirtualDesktopRect(out RECT aRect)
            {
                aRect.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
                if (aRect.right != 0) // A non-zero value indicates the OS supports multiple monitors or at least SM_CXVIRTUALSCREEN.
                {
                    aRect.left = GetSystemMetrics(SM_XVIRTUALSCREEN);  // Might be negative or greater than zero.
                    aRect.right += aRect.left;
                    aRect.top = GetSystemMetrics(SM_YVIRTUALSCREEN);   // Might be negative or greater than zero.
                    aRect.bottom = aRect.top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
                }
                else // Win95/NT do not support SM_CXVIRTUALSCREEN and such, so zero was returned.
                    GetWindowRect(GetDesktopWindow(), out aRect);
            }
    
            private static bool ToolTipCoordMode = true; //true is default coord mode - relative
            public static void CoordMode(bool if_screen_then_false)
            {
                ToolTipCoordMode = if_screen_then_false;
            }
    
            private static IntPtr[] g_hWndToolTip = new IntPtr[30]; //pointers to 30 tooltips
    
            //public static bool Remove(int aID) // remove tooltip with aID
            //{
            //    return Show("", null, null, aID);
            //}
    
            private class WindowWrapper : System.Windows.Forms.IWin32Window
            {
                public WindowWrapper(IntPtr handle)
                {
                    _hwnd = handle;
                }
    
                public IntPtr Handle
                {
                    get { return _hwnd; }
                }
    
                private IntPtr _hwnd;
            }
    
            public bool Show(string aText, System.Nullable<int> aX, System.Nullable<int> aY, System.Nullable<int> aID) // create or modify tooltip
            {
                int window_index = 0;
                if (aID.HasValue) { window_index = (int)(aID) - 1; }
                if (window_index < 0 | window_index >= 30) return false;
                IntPtr tip_hwnd = g_hWndToolTip[window_index];
    
                if (aText == "")
                {
                    if (tip_hwnd != IntPtr.Zero & IsWindow(tip_hwnd))
                    {
                        winClose(tip_hwnd);
                    }
                    g_hWndToolTip[window_index] = IntPtr.Zero;
                    return true;
                }
    
                RECT dtw = new RECT();
                GetVirtualDesktopRect(out dtw);
    
                bool one_or_both_coords_unspecified = (!aX.HasValue | !aY.HasValue);
                POINTAPI pt = new POINTAPI();
                POINTAPI pt_cursor = new POINTAPI();
    
                if (one_or_both_coords_unspecified)
                {
                    GetCursorPos(out pt_cursor);
                    pt.x = pt_cursor.x + 16;  // Set default spot to be near the mouse cursor.
                    pt.y = pt_cursor.y + 16;  // Use 16 to prevent the tooltip from overlapping large cursors.
                }
                RECT rect = new RECT();
    
                if ((aX.HasValue | aY.HasValue) & ToolTipCoordMode)
                {
                    if (!GetWindowRect(GetForegroundWindow(), out rect))
                        return true;
                }
                // This will convert from relative to screen coordinates if rect contains non-zero values:
                if (aX.HasValue)
                    pt.x = (int)aX + (int)rect.left;
                if (aY.HasValue)
                    pt.y = (int)aY + (int)rect.top;
    
                if (tip_hwnd == IntPtr.Zero | !IsWindow(tip_hwnd))
                {
    
               //     tip_hwnd = g_hWndToolTip[window_index] = CreateWindowEx(WS_EX_TOPMOST, "tooltips_class32", "ToolTip", TTS_NOPREFIX | TTS_ALWAYSTIP
               //                 , CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
               //     SendMessage(tip_hwnd, TTM_ADDTOOLA, 0, ref ti);
               //     // v1.0.21: GetSystemMetrics(SM_CXSCREEN) is used for the maximum width because even on a
               //     // multi-monitor system, most users would not want a tip window to stretch across multiple monitors:
               //     SendMessage(tip_hwnd, TTM_SETMAXTIPWIDTH, 0, GetSystemMetrics(SM_CXSCREEN));
               //     // Must do these next two when the window is first created, otherwise GetWindowRect() below will retrieve
               //     // a tooltip window size that is quite a bit taller than it winds up being:
                //
               //     SendMessage(tip_hwnd, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y));
                //    SendMessage(tip_hwnd, TTM_TRACKACTIVATE, 1, ref ti);
                   System.Windows.Forms.ToolTip tooltip = new System.Windows.Forms.ToolTip();
                   // tooltip.ShowAlways = true;
                   // tooltip.OwnerDraw = false;
                   //Process proc = Process.GetCurrentProcess();
                   //IntPtr hwnd = proc.MainWindowHandle;
                   //WindowWrapper window = new WindowWrapper(hwnd); //IWin32Window wrapper
                   tooltip.Show(aText, this);  //<=================================================
                   //MessageBox.Show(window, "Test");
    
    
                   // IntPtr ptr = new IntPtr(tooltip.GetHashCode());
                   // tip_hwnd = g_hWndToolTip[window_index] = ptr;
                }
    
                //SendMessage(tip_hwnd, TTM_UPDATETIPTEXT, 0, ref ti);
    
                RECT ttw = new RECT();
                GetWindowRect(tip_hwnd, out ttw); // Must be called this late to ensure the tooltip has been created by above.
                int tt_width = ttw.right - ttw.left;
                int tt_height = ttw.bottom - ttw.top;
    
                // v1.0.21: Revised for multi-monitor support.  I read somewhere that dtw.left can be negative (perhaps
                // if the secondary monitor is to the left of the primary).  So it seems best to assume it is possible:
                if (pt.x + tt_width >= dtw.right)
                    pt.x = dtw.right - tt_width - 1;
                if (pt.y + tt_height >= dtw.bottom)
                    pt.y = dtw.bottom - tt_height - 1;
    
                if (one_or_both_coords_unspecified)
                {
                    // Since Tooltip is being shown at the cursor's coordinates, try to ensure that the above
                    // adjustment doesn't result in the cursor being inside the tooltip's window boundaries,
                    // since that tends to cause problems such as blocking the tray area (which can make a
                    // tootip script impossible to terminate).  Normally, that can only happen in this case
                    // (one_or_both_coords_unspecified == true) when the cursor is near the buttom-right
                    // corner of the screen (unless the mouse is moving more quickly than the script's
                    // ToolTip update-frequency can cope with, but that seems inconsequential since it
                    // will adjust when the cursor slows down):
                    ttw.left = pt.x;
                    ttw.top = pt.y;
                    ttw.right = ttw.left + tt_width;
                    ttw.bottom = ttw.top + tt_height;
                    if ((pt_cursor.x >= ttw.left) & (pt_cursor.x <= ttw.right) & (pt_cursor.y >= ttw.top) & (pt_cursor.y <= ttw.bottom))
                    {
                        // Push the tool tip to the upper-left side, since normally the only way the cursor can
                        // be inside its boundaries (when one_or_both_coords_unspecified == true) is when the
                        // cursor is near the bottom right corner of the screen.
                        pt.x = pt_cursor.x - tt_width - 3;    // Use a small offset since it can't overlap the cursor
                        pt.y = pt_cursor.y - tt_height - 3;   // when pushed to the the upper-left side of it.
                    }
                }
                //SendMessage(tip_hwnd, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y));
                // And do a TTM_TRACKACTIVATE even if the tooltip window already existed upon entry to this function,
                // so that in case it was hidden or dismissed while its HWND still exists, it will be shown again:
                //SendMessage(tip_hwnd, TTM_TRACKACTIVATE, 1, ref ti);
                return true;
            }
        }
    }

  8. #8
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Multiple unassigned tooltips question

    Why are you recreating the ToolTip class?

  9. #9
    Join Date
    Mar 2009
    Posts
    8

    Re: Multiple unassigned tooltips question

    I like how tooltips are organizing in autohotkey. They serve as a small lines of information you can show on the header of active window or somewhere on the screen, or near coursor of the mouse. The code in 1st post is making the task but with some not understandable bug. In C++ we pass a pointer to a string in toolinfo struct, in C# it is a string. May be this is a problem? But from my research people use string in C# code.

  10. #10
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Multiple unassigned tooltips question

    If this is a C#W app, use the ToolTip class unless you absolutely cannot. I don't see any reason yet that would prevent you from doing so. C# is not C++.

  11. #11
    Join Date
    Jun 2008
    Posts
    154

    Re: Multiple unassigned tooltips question

    here is an example of my tooltip making tips for tuns of stuff. C# Forms

    Code:
                int autoDelay = 2000;
                int initialDelay = 1000;
                int repeatDelay = 800;
                ToolTip helperTip = new ToolTip();
                helperTip.AutoPopDelay = autoDelay;
                helperTip.InitialDelay = initialDelay;
                helperTip.ReshowDelay = repeatDelay;
                helperTip.ShowAlways = true;
                helperTip.SetToolTip(lbl_ATTmodvalue1, "Attack Modifier");
                helperTip.SetToolTip(lbl_ATTmodvalue2, "Attack Modifier");
                helperTip.SetToolTip(lbl_ARCmodvalue1, "Arcane Bonus");
                helperTip.SetToolTip(lbl_ARCmodvalue2, "Arcane Bonus");
                helperTip.SetToolTip(lbl_AGLmodvalue1, "Agility Bonus");
                helperTip.SetToolTip(lbl_AGLmodvalue2, "Agility Bonus");
                helperTip.SetToolTip(lbl_ARequip1, "Armor Equipped");
                helperTip.SetToolTip(lbl_ARequip2, "Armor Equipped");
                helperTip.SetToolTip(lbl_basicArmor1, "Basic Armor (Clothing)");
                helperTip.SetToolTip(lbl_basicArmor2, "Basic Armor (Clothing)");
                helperTip.SetToolTip(lbl_basicAttack1, "Base Attack Rating");
                helperTip.SetToolTip(lbl_basicAttack2, "Base Attack Rating");

  12. #12
    Join Date
    May 2007
    Posts
    1,546

    Re: Multiple unassigned tooltips question

    Well, i'm not up for debugging P/Invokes when a built in option is there. If you decide to use the built in tooltip class and have issues, i'll take another look. Otherwise you're on your own

    The people at autohotkey might be able to provide you with help, or possibly someone else here.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  13. #13
    Join Date
    Mar 2009
    Posts
    8

    Re: Multiple unassigned tooltips question

    Quote Originally Posted by BigEd781 View Post
    If this is a C#W app, use the ToolTip class unless you absolutely cannot. I don't see any reason yet that would prevent you from doing so. C# is not C++.
    I have used ToolTip class but have no idea what to use as a IWin32Window parameter. If I want to use ToolTip class I have to create a form, draw a bitton, assign tooltip to this button and hide the form? This is not "clean" coding really
    I have asked the same question on autohotkey forums, lest see if somebody will reply.

  14. #14
    Join Date
    Jun 2008
    Posts
    2,477

    Re: Multiple unassigned tooltips question

    Creating your own ToolTip class is not "clean coding" either unless it is necessary. What exactly are you trying to do anyway? I have never had problems using the ToolTip class before.

  15. #15
    Join Date
    May 2007
    Posts
    1,546

    Re: Multiple unassigned tooltips question

    If I want to use ToolTip class I have to create a form, draw a bitton, assign tooltip to this button and hide the form?
    What do you think the CreateWindowEx function call is doing?
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center