Need Graphical Tooltip

G

Guest

I need to make a control that behaves like a tool tip, but I need to be able
to draw on it and I also need to show it on demand, not necessarily during a
mousehover event.

The problem with deriving from Control, is that you get the window frame
when you make the control a top level control. Can I make the frame go away?
I could do something with NativeWindow, but I wanted to check here for
something easier. I'd like to avoid the windows API if possible.
 
G

Guest

We investigated Tooltips a while back and found (sadly) that the .NET Tooltip
classes are not designed with extensibility in mind. We wrote our own in the
end.

You could try something like this to start with...

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication34
{
public class ToolTip : System.Windows.Forms.Form
{
public ToolTip()
{
FormBorderStyle = FormBorderStyle.None;
BackColor = SystemColors.Info;
ForeColor = SystemColors.InfoText;

SetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer |
ControlStyles.AllPaintingInWmPaint, true);
ShowInTaskbar = false;
StartPosition = FormStartPosition.Manual;

paintSize = new Size(120, 15);
Size = paintSize;
Region = new Region(new Rectangle(new Point(0, 0), paintSize));
// can't actually have a form this small, set the paint region
}

private Size paintSize;

public new void Show()
{
ShowWindow(new HandleRef(this, Handle), 4);
SetWindowPos(new HandleRef(this, Handle), new IntPtr(-2), Left,
Top, Width, Height, 0x10);
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(0, 0,
paintSize.Width - 1, paintSize.Height - 1));
using (SolidBrush brush = new SolidBrush(ForeColor))
{
e.Graphics.DrawString("My Tip", Font, brush, 0, 0);
}
}

[DllImportAttribute("user32.dll", ExactSpelling=true,
CharSet=CharSet.Auto)]
static extern bool SetWindowPos(HandleRef hWnd, IntPtr
hWndInsertAfter, int x, int y, int cx, int cy, int flags);

[DllImportAttribute("user32.dll", ExactSpelling=true,
CharSet=CharSet.Auto)]
static extern bool ShowWindow(HandleRef hWnd, int nCmdShow);
}
}

Hope this helps.

Regards,
Matt Garven
 
G

Guest

We investigated Tooltips a while back and found (sadly) that the .NET Tooltip
classes are not designed with extensibility in mind. We wrote our own in the
end.

You could try something like this to start with...

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication34
{
public class ToolTip : System.Windows.Forms.Form
{
public ToolTip()
{
FormBorderStyle = FormBorderStyle.None;
BackColor = SystemColors.Info;
ForeColor = SystemColors.InfoText;

SetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer |
ControlStyles.AllPaintingInWmPaint, true);
ShowInTaskbar = false;
StartPosition = FormStartPosition.Manual;

paintSize = new Size(120, 15);
Size = paintSize;
Region = new Region(new Rectangle(new Point(0, 0), paintSize));
// can't actually have a form this small, set the paint region
}

private Size paintSize;

public new void Show()
{
ShowWindow(new HandleRef(this, Handle), 4);
SetWindowPos(new HandleRef(this, Handle), new IntPtr(-2), Left,
Top, Width, Height, 0x10);
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(0, 0,
paintSize.Width - 1, paintSize.Height - 1));
using (SolidBrush brush = new SolidBrush(ForeColor))
{
e.Graphics.DrawString("My Tip", Font, brush, 0, 0);
}
}

[DllImportAttribute("user32.dll", ExactSpelling=true,
CharSet=CharSet.Auto)]
static extern bool SetWindowPos(HandleRef hWnd, IntPtr
hWndInsertAfter, int x, int y, int cx, int cy, int flags);

[DllImportAttribute("user32.dll", ExactSpelling=true,
CharSet=CharSet.Auto)]
static extern bool ShowWindow(HandleRef hWnd, int nCmdShow);
}
}

Hope this helps.

Regards,
Matt Garven
 
G

Guest

Hmm, deriving from Form is interesting. I didn't know about the
FormBorderStyle property.

Why did you have to override Show() with the API functions? Why did the
default not work for you?

Matt Garven said:
We investigated Tooltips a while back and found (sadly) that the .NET Tooltip
classes are not designed with extensibility in mind. We wrote our own in the
end.

You could try something like this to start with...

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication34
{
public class ToolTip : System.Windows.Forms.Form
{
public ToolTip()
{
FormBorderStyle = FormBorderStyle.None;
BackColor = SystemColors.Info;
ForeColor = SystemColors.InfoText;

SetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer |
ControlStyles.AllPaintingInWmPaint, true);
ShowInTaskbar = false;
StartPosition = FormStartPosition.Manual;

paintSize = new Size(120, 15);
Size = paintSize;
Region = new Region(new Rectangle(new Point(0, 0), paintSize));
// can't actually have a form this small, set the paint region
}

private Size paintSize;

public new void Show()
{
ShowWindow(new HandleRef(this, Handle), 4);
SetWindowPos(new HandleRef(this, Handle), new IntPtr(-2), Left,
Top, Width, Height, 0x10);
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(0, 0,
paintSize.Width - 1, paintSize.Height - 1));
using (SolidBrush brush = new SolidBrush(ForeColor))
{
e.Graphics.DrawString("My Tip", Font, brush, 0, 0);
}
}

[DllImportAttribute("user32.dll", ExactSpelling=true,
CharSet=CharSet.Auto)]
static extern bool SetWindowPos(HandleRef hWnd, IntPtr
hWndInsertAfter, int x, int y, int cx, int cy, int flags);

[DllImportAttribute("user32.dll", ExactSpelling=true,
CharSet=CharSet.Auto)]
static extern bool ShowWindow(HandleRef hWnd, int nCmdShow);
}
}

Hope this helps.

Regards,
Matt Garven

RichM said:
I need to make a control that behaves like a tool tip, but I need to be able
to draw on it and I also need to show it on demand, not necessarily during a
mousehover event.

The problem with deriving from Control, is that you get the window frame
when you make the control a top level control. Can I make the frame go away?
I could do something with NativeWindow, but I wanted to check here for
something easier. I'd like to avoid the windows API if possible.
 
G

Guest

Well sadly you can't override Show(), I just redeclared it for clarity. You
need to use the API functions so that showing the tooltip form doesn't steal
focus from the form the user is currently using.

You need to use a Form instead of Control because your tooltips may show
over the edge of the form that the tooltip is appearing on - it would look
strange to have the tooltip truncated at the edge of the form.

Hope this helps.

Regards,
Matt

RichM said:
Hmm, deriving from Form is interesting. I didn't know about the
FormBorderStyle property.

Why did you have to override Show() with the API functions? Why did the
default not work for you?

Matt Garven said:
We investigated Tooltips a while back and found (sadly) that the .NET Tooltip
classes are not designed with extensibility in mind. We wrote our own in the
end.

You could try something like this to start with...

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication34
{
public class ToolTip : System.Windows.Forms.Form
{
public ToolTip()
{
FormBorderStyle = FormBorderStyle.None;
BackColor = SystemColors.Info;
ForeColor = SystemColors.InfoText;

SetStyle(ControlStyles.UserPaint | ControlStyles.DoubleBuffer |
ControlStyles.AllPaintingInWmPaint, true);
ShowInTaskbar = false;
StartPosition = FormStartPosition.Manual;

paintSize = new Size(120, 15);
Size = paintSize;
Region = new Region(new Rectangle(new Point(0, 0), paintSize));
// can't actually have a form this small, set the paint region
}

private Size paintSize;

public new void Show()
{
ShowWindow(new HandleRef(this, Handle), 4);
SetWindowPos(new HandleRef(this, Handle), new IntPtr(-2), Left,
Top, Width, Height, 0x10);
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(0, 0,
paintSize.Width - 1, paintSize.Height - 1));
using (SolidBrush brush = new SolidBrush(ForeColor))
{
e.Graphics.DrawString("My Tip", Font, brush, 0, 0);
}
}

[DllImportAttribute("user32.dll", ExactSpelling=true,
CharSet=CharSet.Auto)]
static extern bool SetWindowPos(HandleRef hWnd, IntPtr
hWndInsertAfter, int x, int y, int cx, int cy, int flags);

[DllImportAttribute("user32.dll", ExactSpelling=true,
CharSet=CharSet.Auto)]
static extern bool ShowWindow(HandleRef hWnd, int nCmdShow);
}
}

Hope this helps.

Regards,
Matt Garven

RichM said:
I need to make a control that behaves like a tool tip, but I need to be able
to draw on it and I also need to show it on demand, not necessarily during a
mousehover event.

The problem with deriving from Control, is that you get the window frame
when you make the control a top level control. Can I make the frame go away?
I could do something with NativeWindow, but I wanted to check here for
something easier. I'd like to avoid the windows API if possible.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top