Skip to content

Commit 705c3ad

Browse files
committed
Improve ToolTip visuals
Fix function matching Regex bug
1 parent 39f878c commit 705c3ad

File tree

4 files changed

+102
-22
lines changed

4 files changed

+102
-22
lines changed

Source/ExcelDna.IntelliSense/IntelliSenseDisplay.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ void FunctionListSelectedItemChange(string selectedItemText, Rect selectedItemBo
320320
{
321321
_descriptionToolTip.ShowToolTip(
322322
text: new FormattedText { GetFunctionDescriptionOrNull(functionInfo) },
323-
left: (int)selectedItemBounds.Right + 25,
323+
left: (int)selectedItemBounds.Right + 21,
324324
top: (int)selectedItemBounds.Top);
325325
return;
326326
}
@@ -332,7 +332,7 @@ void FunctionListSelectedItemChange(string selectedItemText, Rect selectedItemBo
332332

333333
void FunctionListMove(Rect selectedItemBounds)
334334
{
335-
_descriptionToolTip.MoveToolTip((int)selectedItemBounds.Right + 25, (int)selectedItemBounds.Top);
335+
_descriptionToolTip.MoveToolTip((int)selectedItemBounds.Right + 21, (int)selectedItemBounds.Top);
336336
}
337337

338338
// TODO: Performance / efficiency - cache these somehow

Source/ExcelDna.IntelliSense/ToolTipForm.cs

Lines changed: 86 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Diagnostics;
44
using System.Drawing;
5+
using System.Drawing.Drawing2D;
56
using System.Linq;
67
using System.Text;
78
using System.Windows.Forms;
@@ -20,12 +21,27 @@ class ToolTipForm : Form
2021
Win32Window _owner;
2122
int _left;
2223
int _top;
24+
Brush _textBrush;
25+
Pen _borderPen;
26+
Dictionary<FontStyle, Font> _fonts;
2327

2428
public ToolTipForm(IntPtr hwndOwner)
2529
{
2630
Debug.Assert(hwndOwner != IntPtr.Zero);
2731
InitializeComponent();
2832
_owner = new Win32Window(hwndOwner);
33+
// CONSIDER: Maybe make a more general solution that lazy-loads as needed
34+
_fonts = new Dictionary<FontStyle, Font>
35+
{
36+
{ FontStyle.Regular, new Font("Segoe UI", 9, FontStyle.Regular) },
37+
{ FontStyle.Bold, new Font("Segoe UI", 9, FontStyle.Bold) },
38+
{ FontStyle.Italic, new Font("Segoe UI", 9, FontStyle.Italic) },
39+
{ FontStyle.Underline, new Font("Segoe UI", 9, FontStyle.Underline) },
40+
{ FontStyle.Bold | FontStyle.Italic, new Font("Segoe UI", 9, FontStyle.Bold | FontStyle.Italic) },
41+
42+
};
43+
_textBrush = new SolidBrush(Color.FromArgb(68, 68, 68));
44+
_borderPen = new Pen(Color.FromArgb(205, 205, 205));
2945
//Win32Helper.SetParent(this.Handle, hwndOwner);
3046

3147
// _owner = new NativeWindow();
@@ -63,18 +79,20 @@ public void ShowToolTip()
6379
public void ShowToolTip(FormattedText text, int left, int top)
6480
{
6581
_text = text;
82+
_left = left;
83+
_top = top;
6684
if (!Visible)
6785
{
6886
Debug.Print($"Showing ToolTipForm: {_text.ToString()}");
87+
Left = _left;
88+
Top = _top;
6989
ShowToolTip();
7090
}
7191
else
7292
{
7393
Debug.Print($"Invalidating ToolTipForm: {_text.ToString()}");
7494
Invalidate();
7595
}
76-
_left = left;
77-
_top = top;
7896
}
7997

8098
public void MoveToolTip(int left, int top)
@@ -88,7 +106,8 @@ public IntPtr OwnerHandle
88106
{
89107
get
90108
{
91-
if (_owner == null) return IntPtr.Zero;
109+
if (_owner == null)
110+
return IntPtr.Zero;
92111
return _owner.Handle;
93112
}
94113
set
@@ -99,7 +118,7 @@ public IntPtr OwnerHandle
99118
//Win32Helper.SetParent(this.Handle, value);
100119
if (Visible)
101120
{
102-
// Rather just change Owner....
121+
// CONSIDER: Rather just change Owner....
103122
Hide();
104123
ShowToolTip();
105124
}
@@ -152,11 +171,12 @@ protected override void OnHandleDestroyed(EventArgs e)
152171

153172
protected override void OnPaint(PaintEventArgs e)
154173
{
155-
Debug.Print($"Painting ToolTipForm: {_text.ToString()}");
156-
const int leftPadding = 3;
174+
Debug.Assert(_left != 0 || _top != 0);
175+
Logger.Display.Verbose($"ToolTipForm OnPaint: {_text.ToString()} @ ({_left},{_top})");
176+
const int leftPadding = 6;
157177
const int linePadding = 2;
158178
const int widthPadding = 10;
159-
const int heightPadding = 7;
179+
const int heightPadding = 3;
160180

161181
base.OnPaint(e);
162182
List<int> lineWidths = new List<int>();
@@ -178,16 +198,13 @@ protected override void OnPaint(PaintEventArgs e)
178198
int lineHeight = 0;
179199
foreach (var run in line)
180200
{
181-
using (var font = new Font("Segoe UI", 9, run.Style)) // TODO: Look this up or something ...?
182-
{
183-
// TODO: Empty strings are a problem....
184-
var text = run.Text == "" ? " " : run.Text;
185-
186-
// TODO: Find the color SystemBrushes.ControlDarkDark
187-
DrawString(e.Graphics, SystemBrushes.WindowFrame, ref layoutRect, out textSize, format, text, font);
188-
totalWidth += textSize.Width;
189-
lineHeight = Math.Max(lineHeight, textSize.Height);
190-
}
201+
var font = _fonts[run.Style];
202+
// TODO: Empty strings are a problem....
203+
var text = run.Text == "" ? " " : run.Text;
204+
205+
DrawString(e.Graphics, _textBrush, ref layoutRect, out textSize, format, text, font);
206+
totalWidth += textSize.Width;
207+
lineHeight = Math.Max(lineHeight, textSize.Height);
191208
}
192209
lineWidths.Add(totalWidth);
193210
totalWidth = 0;
@@ -196,7 +213,27 @@ protected override void OnPaint(PaintEventArgs e)
196213
}
197214
}
198215

199-
SetBounds(_left, _top, lineWidths.Max() + widthPadding, totalHeight + heightPadding);
216+
var width = lineWidths.Max() + widthPadding;
217+
var height = totalHeight + heightPadding;
218+
//if (Left != _left ||
219+
// Top != _top ||
220+
// Width != width ||
221+
// Height != height)
222+
//{
223+
//var pRegion = Win32Helper.CreateRoundRectRgn(0, 0, width - 1, height - 1, 2, 2);
224+
//try
225+
//{
226+
// Region = Region.FromHrgn(pRegion);
227+
//}
228+
//finally
229+
//{
230+
// Win32Helper.DeleteObject(pRegion);
231+
//}
232+
SetBounds(_left, _top, width, height);
233+
//}
234+
235+
DrawRoundedRectangle(e.Graphics, new RectangleF(0,0, Width - 1, Height - 1), 2, 2);
236+
200237
// Size = new Size(lineWidths.Max() + widthPadding, totalHeight + heightPadding);
201238
}
202239

@@ -224,6 +261,36 @@ void DrawString(Graphics g, Brush brush, ref Rectangle rect, out Size used,
224261
}
225262
}
226263

264+
265+
public void DrawRoundedRectangle(Graphics g, RectangleF r, float radiusX, float radiusY)
266+
{
267+
var oldMode = g.SmoothingMode;
268+
g.SmoothingMode = SmoothingMode.AntiAlias;
269+
270+
// Draw the truncated rectangle in white.
271+
using (GraphicsPath path = new GraphicsPath())
272+
{
273+
path.StartFigure();
274+
275+
// if (radiusX <= 0.0F || radiusY <= 0.0F)
276+
{
277+
path.AddRectangle(r);
278+
}
279+
//else
280+
{
281+
//arcs work with diameters (radius * 2)
282+
PointF d = new PointF(Math.Min(radiusX * 2, r.Width), Math.Min(radiusY * 2, r.Height));
283+
path.AddArc(r.X, r.Y, d.X, d.Y, 180, 90);
284+
path.AddArc(r.Right - d.X, r.Y, d.X, d.Y, 270, 90);
285+
path.AddArc(r.Right - d.X, r.Bottom - d.Y, d.X, d.Y, 0, 90);
286+
path.AddArc(r.X, r.Bottom - d.Y, d.X, d.Y, 90, 90);
287+
}
288+
path.CloseFigure();
289+
g.DrawPath(_borderPen, path);
290+
}
291+
g.SmoothingMode = oldMode;
292+
}
293+
227294
void InitializeComponent()
228295
{
229296
this.components = new System.ComponentModel.Container();
@@ -264,7 +331,7 @@ void InitializeComponent()
264331
this.Controls.Add(this.labelDna);
265332
this.DoubleBuffered = true;
266333
this.ForeColor = System.Drawing.Color.DimGray;
267-
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
334+
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
268335
this.Name = "ToolTipForm";
269336
this.ShowInTaskbar = false;
270337
this.ResumeLayout(false);

Source/ExcelDna.IntelliSense/UIMonitor/FormulaParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ static class FormulaParser
88
// TODO: This needs a proper implementation, considering subformulae
99
internal static bool TryGetFormulaInfo(string formulaPrefix, out string functionName, out int currentArgIndex)
1010
{
11-
var match = Regex.Match(formulaPrefix, @"^=(?<functionName>(\w|.)*)\(");
11+
var match = Regex.Match(formulaPrefix, @"^=(?<functionName>[\w|.]*)\(");
1212
if (match.Success)
1313
{
1414
functionName = match.Groups["functionName"].Value;

Source/ExcelDna.IntelliSense/Win32Helper.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ enum WM : uint
2828
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
2929
static extern int GetWindowTextLength(IntPtr hWnd);
3030

31+
[DllImport("gdi32.dll")]
32+
internal static extern IntPtr CreateRoundRectRgn(
33+
int nLeftRect, // x-coordinate of upper-left corner
34+
int nTopRect, // y-coordinate of upper-left corner
35+
int nRightRect, // x-coordinate of lower-right corner
36+
int nBottomRect, // y-coordinate of lower-right corner
37+
int nWidthEllipse, // height of ellipse
38+
int nHeightEllipse); // width of ellipse
39+
40+
[DllImport("gdi32.dll")]
41+
[return: MarshalAs(UnmanagedType.Bool)]
42+
internal static extern bool DeleteObject([In] IntPtr hObject);
43+
3144
[DllImport("user32.dll", SetLastError = true)]
3245
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
3346

0 commit comments

Comments
 (0)