|
|
Hello,
I'm extending a ListBox with tooltips for items that don't fit, but I can't find out how to position the tooltip exactly over the item. I already got the item coordinates, but how do I tell the tooltip where to appear. It is possible via a Windows message, but how do I get the Win32 handle of the window?
[EDIT: There's a private Handle property... it could help]
Any other ideas?
-- LuisR
Luis Alonso Ramos
Intelectix - Chihuahua, Mexico
Not much here: My CP Blog!
The amount of sleep the average person needs is five more minutes. -- Vikram A Punathambekar, Aug. 11, 2005
-- modifed at 16:00 Thursday 25th August, 2005
|
|
|
|
|
I guess this is all you need. Give me a candy if this works for you.
private void ListControlMouseMove(object sender, MouseEventArgs e)
{
Point ptOnlist = Point.Empty;
ListViewItem item = null;
int subItemIndex = -1;
int subItemTextWidth = -1;
ListViewItem.ListViewSubItem curSubItem = null;
if (e.Button == MouseButtons.None)
{
item = this.GetItemAt(e.X, e.Y);
if (item != null)
{
subItemIndex = this.GetSubItemIndexFromPoint(item, new Point(e.X, e.Y));
if (subItemIndex != -1)
{
curSubItem = item.SubItems[subItemIndex];
if (curSubItem != null)
{
if (curSubItem.Text.Length > 0)
{
subItemTextWidth = this.ListViewGetStringWidth(curSubItem.Text);
if (subItemTextWidth != -1)
{
subItemTextWidth += 12;
if (subItemTextWidth > this.Columns[subItemIndex].Width)
{
this.SetToolTipText(curSubItem.Text);
}
else
{
this.HideToolTip();
}
}
}
}
}
else
{
this.HideDynamicControls();
}
}
}
}
protected int GetSubItemIndexFromPoint(ListViewItem item, Point ptInList)
{
int sumOfWidths = 0;
int columnIndex = 0;
foreach (ColumnHeader column in this.Columns)
{
if (sumOfWidths < ptInList.X && ptInList.X < sumOfWidths + column.Width)
{
return columnIndex;
}
sumOfWidths += column.Width;
columnIndex++;
}
return -1;
}
private const int LVM_GETSTRINGWIDTHW = 4183
protected int ListViewGetStringWidth(string subItemText)
{
IntPtr hString = Marshal.StringToHGlobalAuto(subItemText);
int width = UnsafeNativeMethods.SendMessage(this.Handle, LVM_GETSTRINGWIDTHW, 0, hString);
Marshal.FreeHGlobal(hString);
return width;
}
protected void SetToolTipText(string toolTipText)
{
if (toolTipText != null)
{
this.toolTip.Active = true;
this.toolTip.SetToolTip(this, toolTipText);
}
}
Cheers.
|
|
|
|
|
Sorry. It won't work. As matter of fact I'm using a ListBox , not a ListView , so all the above code doesn't really aply. But I appreciate your effort! Thanks!
I found out using .NET Reflector that the ToolTip class uses "normal" tooltips (using TTM_ACTIVATE to make it active.) There's a special type of tool tips, called "tracking" that have the TTF_TRACK flag, and you activate them with TTM_TRACKACTIVATE, and set their position with TTM_TRACKPOSITION (all of them Win32 window messages). Tracking tooltips don't move with the mouse; they just stay where they appear.
So I guess I'll have to rewrite the entire ToolTip class into something like TrackingToolTip. It doesn't really seem that hard to do, it's a simple class. I'll be sure to post an article here when I'm done.
Thanks!
-- LuisR
Luis Alonso Ramos
Intelectix - Chihuahua, Mexico
Not much here: My CP Blog!
The amount of sleep the average person needs is five more minutes. -- Vikram A Punathambekar, Aug. 11, 2005
|
|
|
|
|
I hope the following works for you. As faar as ListBox is concerned you can do the following
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int cx;
public int cy;
}
[DllImport("gdi32.dll")]
public static extern int GetTextExtentPoint32(IntPtr hdc, String str, int len, ref POINT pt);
[DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hWnd,IntPtr hdc);
private void listBox1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
int index = this.listBox1.IndexFromPoint(e.X,e.Y);
if ( index > 0 )
{
IntPtr dc = GetDC(this.listBox1.Handle);
POINT pt;
pt.cx = 0;
pt.cy = 0;
GetTextExtentPoint32(dc, this.listBox1.Items[index].ToString() ,this.listBox1.Items[index].ToString().Length,ref pt);
ReleaseDC(this.listBox1.Handle, dc);
if(this.listBox1.Width < pt.cx)
{
this.SetToolTipText(this.listBox1.Items[index].ToString());
}
}
}
and as far as ToolTip is concerned
///
/// Set the position of the control with respect to the anchor control
///
/// <param name="anchorControl" />
private void SetPosition(Control anchorControl)
{
//
//Resolve the Balloon Coordinates
//to the client area
//
UnsafeNativeMethods.GetClientRect(anchorControl.Handle, ref this.toolInfo.rect);
UnsafeNativeMethods.ClientToScreen(anchorControl.Handle, ref this.toolInfo.rect);
//
//set the position of the toolTip to be
//displayed
//
int pt = MAKELONG(toolInfo.rect.left, toolInfo.rect.top + toolInfo.rect.bottom);
IntPtr ptr = new IntPtr(pt);
UnsafeNativeMethods.SendMessage(
this.Handle, TTM_TRACKPOSITION,
0, ptr);
}
[DllImport("User32", SetLastError = true)]
public static extern int GetClientRect(IntPtr hWnd, ref Rect lpRect);
[DllImport("User32", SetLastError = true)]
public static extern int ClientToScreen(IntPtr hWnd, ref Rect lpRect);
private const int WM_USER = 0x0400;
private const int TTM_TRACKACTIVATE = WM_USER + 17;
private int MAKELONG(int loWord, int hiWord)
{
return (hiWord << 16) | (loWord & 0xffff);
}
|
|
|
|
|
That looks more like what I need... I'll try that code and get back to you. Did you test it?
-- LuisR
Luis Alonso Ramos
Intelectix - Chihuahua, Mexico
Not much here: My CP Blog!
The amount of sleep the average person needs is five more minutes. -- Vikram A Punathambekar, Aug. 11, 2005
|
|
|
|
|
Yes I did. If you want I can send you the zipped project.
Live Life King Size
Alomgir Miah
|
|
|
|
|
Well, sure! I was thinking of trying it monday morning when I get to the office, but if you can send it to me before that, I'll appreciate it! Thank you very much, really!
I won't post my e-mail here for spam reasons, but you'll find my e-mail on the notification message you get telling you I responded to your post.
-- LuisR
Luis Alonso Ramos
Intelectix - Chihuahua, Mexico
Not much here: My CP Blog!
The amount of sleep the average person needs is five more minutes. -- Vikram A Punathambekar, Aug. 11, 2005
-- modified at 4:09 Saturday 27th August, 2005
|
|
|
|
|
Hi I need to make the way a child form pop up when I run my project.It contains information about my program and its the first form that should be seen>Anybody can tell mr how can I manage it?
|
|
|
|
|
On the OnLoad event of the parent form do the following.
private void OnFormLoad(object sender, System.EventArgs e)
{
ChildForm f = new ChildForm();
f.MdiParent = this;
f.Show();
}
|
|
|
|
|
Does it work?
In your way, you have to set this.isMdiParent = true;
Then its appearance will change. I do not think it is a good method.
ps: can you give me some idea to make a logo. many thanks!
|
|
|
|
|
Hello again
I'm currently developing a simple IRC client and right now I have to decide whether to use Regex or normal String methods to parse the incoming data. The incoming data looks like this and has to be parsed serveral times a second in frequently used IRC channels:
:Nicky!u001@s1.bouncer.ca PRIVMSG #asdf :Hello everybody :)
This is my code - it works and is easy to maintain, but how fast is it compared to using String methods like IndexOf(), Substring() etc?
string pattern1 = @"^:(?<nick>.+)!(?<user>.+)@(?<hostname>[^\s]+)\s(?<command>\w+)\s(?<channel>.+)\s:(?<text>.+)$";
MatchCollection mc = Regex.Matches(cmd, pattern1);
if(mc.Count > 0)
{
for(int i=0; i<mc.Count; i++)
{
GroupCollection gc = mc[i].Groups;
if(gc.Count >= 6)
{
nick = gc[1].Value;
user = gc[2].Value;
host = gc[3].Value;
cmd = gc[4].Value;
channel = gc[5].Value;
text = gc[6].Value;
}
}
}
modified 12-Sep-18 21:01pm.
|
|
|
|
|
String size: how big is the string? If it's only a few chars, IndexOf is faster. If it's a few KB, Regex can be several times faster.
Don't forget to create compiled Regexes.
I see dead pixels
Yes, even I am blogging now!
|
|
|
|
|
length is about 50-500 characters and has to be evaluated about 1-20 times a second
modified 12-Sep-18 21:01pm.
|
|
|
|
|
On a decent machine, I'd bet you'll not see much difference (if your Regex does not backtrack a lot) after the first invocation (the Regex engine will need to compile your Regex on the first invocation), but also depends on the position on the string your matches will be and if you're able to build a 0 backtrack regex.
For small matches on small strings (as it seems your case), I'd suggest you to use non-greedy operator (e.g., instead of using .* use .*?).
If you have parser construction and compiler construction knowledge, the best performing solution will alway be producing a DFA parser with a parser tool like COCO/R or using a parser generated by ANTLR, specially if your grammar is LL(1).
I see dead pixels
Yes, even I am blogging now!
|
|
|
|
|
Ok thanks, I think I will try both methods and watch what's faster, but I think I'll stick with the regex.
modified 12-Sep-18 21:01pm.
|
|
|
|
|
I like your code. That's text book use of regex.
/\ |_ E X E GG
|
|
|
|
|
It really is? I haven't used regex in complex programs so far.
Thanks!
modified 12-Sep-18 21:01pm.
|
|
|
|
|
Hello All:
I am trying to find a way to send email notifications through my windows service. Can someone please help me with this? Thanks a lot.
|
|
|
|
|
What is the best way to secure the Configuration Settings (app.config and web.config). It seems that one way to do it is to encrypt the contents of the Configuration Settings, especially the database access string, using a two-way encryption algorithm. This encryption can either be performed from our own code (using the Cryptography library) or through the Configuration Settings App Block. However in both cases we have to deal with an encryption key. Anybody that can get access to this key will be able to decrypt the encrypted strings. The question is where to store that key. Storing the key in the code does not seem to be a good idea, especially since it is easy to read the code contents through the disassembler. Does anybody know how to protect that encryption key or any other way to protect the configuration settings.
|
|
|
|
|
Hi,
I have a main form in my application and this form has a button. When the button is clicked, a new form is loaded - form A. Form A has another button, when clicked it loads form B. When form B is loaded I need the name (header) of the main form to change to included the name of form B. Since main form's properies are private, is there way of changing main form's text when clicking event occures in form A. I guess I can define a public property in the main form class to set it's text, is there any other way?
thank you
Felix
|
|
|
|
|
felimonchik wrote:
is there any other way?
Sure, I'd just pass the MainForm instance around to each form constructor.
FormA formA = new FormA(this);
...
public FormA(MainForm mainInstance)
{
mainInstance.Text = "you've loaded form A now!";
}
Tech, life, family, faith: Give me a visit.
I'm currently blogging about: Who is Jewish, the Trivia Game!
Judah Himango
|
|
|
|
|
Is this an MDI application or a group of SDI apps? Have you looked into the Model-View-Controller pattern?
|
|
|
|
|
It's an MDI application.
Thanx
|
|
|
|
|
I think Text property of a windows form is public. So u can directly assign to it.
Jayant D. Kulkarni
Brainbench Certified Software Engineer in C#, ASP.NET, .NET Framework and ADO.NET
|
|
|
|
|