Я пытаюсь рисовать пользовательские границы для существующих элементов .Net WinForms. Я попытался это сделать, создав класс, который из элемента управления я хочу изменить цвет границы, а затем попробую несколько вещей во время рисования. Я пробовал следующее:Как рисовать пользовательские границы на элементах .Net WinForms
1. Поймать WM_NCPAINT
. Это работает несколько. Проблема с приведенным ниже кодом заключается в том, что при изменении размера элемента управления граница будет обрезана с правой и нижней стороны. Нехорошо.
protected override void WndProc(ref Message m)
{
if (m.Msg == NativeMethods.WM_NCPAINT) {
WmNcPaint(ref m);
return;
}
base.WndProc(ref m);
}
private void WmNcPaint(ref Message m)
{
if (BorderStyle == BorderStyle.None) {
return;
}
IntPtr hDC = NativeMethods.GetWindowDC(m.HWnd);
if (hDC != IntPtr.Zero) {
using (Graphics g = Graphics.FromHdc(hDC)) {
ControlPaint.DrawBorder(g, new Rectangle(0, 0, this.Width, this.Height), _BorderColor, ButtonBorderStyle.Solid);
}
m.Result = (IntPtr)1;
NativeMethods.ReleaseDC(m.HWnd, hDC);
}
}
2. Переопределение void OnPaint
. Это работает для некоторых элементов управления, но не для всех. Это также требует, чтобы вы установили BorderStyle
в BorderStyle.None
, и вам нужно вручную очистить фон от краски, иначе you get this при изменении размера.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
ControlPaint.DrawBorder(e.Graphics, new Rectangle(0, 0, this.Width, this.Height), _BorderColor, ButtonBorderStyle.Solid);
}
3. Переопределение void OnResize
и void OnPaint
(как в метод 2). Таким образом, он хорошо рисует с изменением размера, но не тогда, когда панель имеет AutoScroll
, и в этом случае при прокрутке будет look like this. Если я попытаюсь использовать WM_NCPAINT
, чтобы нарисовать границу, Refresh()
не действует.
protected override void OnResize(EventArgs eventargs)
{
base.OnResize(eventargs);
Refresh();
}
Предложения более чем из приятных. Я хотел бы знать, что нужно сделать для управления несколькими типами элементов управления (я должен будет сделать это для нескольких элементов управления WinForms по умолчанию).
Я уверен, что вы слышали это раньше, но мое честное предложение состояло в том, чтобы просто использовать WPF вместо WinFroms. Кроме того, у вас есть мои пожелания удачи в этом, и мой +1 для хорошо написанного вопроса. – BradleyDotNET
Спасибо! И да, я слышал это раньше, много раз :) Мне все еще нужно найти время, чтобы изучить WPF, но этот проект слишком глубоко в WinForms, чтобы преобразовать его в WPF. Возможно в будущем. – Codecat
protected override void OnResize (EventArgs eventargs) { base.OnResize (eventargs); Обновить(); } – houssam