in src/AccessibilityInsights.SharedUx/Highlighting/TextTip.cs [364:494]
public IntPtr WndProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam)
{
switch (uMsg)
{
case Win32Constants.WM_NCHITTEST:
return (IntPtr)Win32Constants.HTTRANSPARENT;
// Using ERASEBKGND instead of PAINT gives us more responsive update
case Win32Constants.WM_ERASEBKGND:
{
if (this.Text == null || string.IsNullOrEmpty(this.Text))
return (IntPtr)1;
IntPtr hDC = wParam;
IntPtr hFont = NativeMethods.SelectObject(hDC, this.hFont);
RECT rcClient;
NativeMethods.GetClientRect(hWnd, out rcClient);
IntPtr hBrush = NativeMethods.CreateSolidBrush(this.BackgroundColor);
#pragma warning disable CA1806 // Do not ignore method results
NativeMethods.FillRect(hDC, ref rcClient, hBrush);
hBrush = NativeMethods.SelectObject(hDC, hBrush);
NativeMethods.SetBkColor(hDC, this.BackgroundColor);
NativeMethods.SetTextColor(hDC, this.TextColor);
#pragma warning restore CA1806 // Do not ignore method results
int CurYPos = 1 + TEXTBORDER;
int idxCur = 0;
while (idxCur < this.Text.Length)
{
// Find the end of the line...
int idxEnd = idxCur;
var ch = this.Text[idxEnd];
while (ch != '\r' && ch != '\n' && ch != '\t')
{
idxEnd++;
if (idxEnd < this.Text.Length)
{
ch = this.Text[idxEnd];
}
else
{
break;
}
}
int Len = (int)(idxEnd - idxCur);
// Now pass the line to DrawText to get the height/length...
RECT rc = new RECT() { left = 1 + TEXTBORDER, top = CurYPos, right = rcClient.right, bottom = rcClient.bottom };
// TODO - set tab stops correctly (default is 8 - probably too small...
int Height = NativeMethods.DrawText(hDC, this.Text.Substring(idxCur, Len), Len, ref rc,
Win32Constants.DT_NOCLIP | Win32Constants.DT_LEFT | Win32Constants.DT_SINGLELINE | Win32Constants.DT_NOPREFIX);
if (ch == '\t')
{
// work out second part of the tab-stop'd line...
idxEnd++;
idxCur = idxEnd;
while (ch != '\r' && ch != '\n')
{
idxEnd++;
if (idxEnd < this.Text.Length)
{
ch = this.Text[idxEnd];
}
else
{
break;
}
}
rc.left += m_TabStop + TEXTTABMIN;
Len = (int)(idxEnd - idxCur);
int Height2 = NativeMethods.DrawText(hDC, this.Text.Substring(idxCur, Len), Len, ref rc,
Win32Constants.DT_NOCLIP | Win32Constants.DT_LEFT | Win32Constants.DT_SINGLELINE | Win32Constants.DT_NOPREFIX | Win32Constants.DT_END_ELLIPSIS);
if (Height < Height2)
Height = Height2;
}
CurYPos += Height;
// Skip over the \r (or \n) - and allow for a trailing \n (or \r) if on exists.
if (ch == '\r')
{
idxEnd++;
ch = this.Text[idxEnd];
if (ch == '\n')
{
idxEnd++;
}
}
else if (ch == '\n')
{
idxEnd++;
ch = this.Text[idxEnd];
if (ch == '\r')
{
idxEnd++;
}
}
// Use this as the new starting pos...
idxCur = idxEnd;
}
hBrush = NativeMethods.SelectObject(hDC, hBrush);
NativeMethods.DeleteObject(hBrush);
IntPtr hPen = NativeMethods.GetStockObject(StockObjects.BLACK_PEN);
hPen = NativeMethods.SelectObject(hDC, hPen);
// Draw rectangle...
NativeMethods.MoveToEx(hDC, 0, 0, IntPtr.Zero);
NativeMethods.LineTo(hDC, 0, rcClient.bottom - 1);
NativeMethods.LineTo(hDC, rcClient.right - 1, rcClient.bottom - 1);
NativeMethods.LineTo(hDC, rcClient.right - 1, 0);
NativeMethods.LineTo(hDC, 0, 0);
hPen = NativeMethods.SelectObject(hDC, hPen);
NativeMethods.SelectObject(hDC, hFont);
return (IntPtr)1;
}
}
return NativeMethods.DefWindowProc(hWnd, uMsg, wParam, lParam);
}