-
March 8th, 2009, 11:08 AM
#1
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;
}
}
}
-
March 8th, 2009, 12:50 PM
#2
Re: Multiple unassigned tooltips question
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.
-
March 9th, 2009, 10:33 AM
#3
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.
-
March 9th, 2009, 11:53 AM
#4
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);
}
}
-
March 9th, 2009, 12:58 PM
#5
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.
-
March 9th, 2009, 01:18 PM
#6
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.
-
March 9th, 2009, 01:38 PM
#7
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;
}
}
}
-
March 9th, 2009, 01:43 PM
#8
Re: Multiple unassigned tooltips question
Why are you recreating the ToolTip class?
-
March 9th, 2009, 02:23 PM
#9
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.
-
March 9th, 2009, 02:37 PM
#10
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++.
-
March 9th, 2009, 03:11 PM
#11
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");
-
March 9th, 2009, 03:36 PM
#12
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.
-
March 10th, 2009, 10:21 AM
#13
Re: Multiple unassigned tooltips question
Originally Posted by BigEd781
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.
-
March 10th, 2009, 12:10 PM
#14
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.
-
March 10th, 2009, 03:20 PM
#15
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.
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|