Когда пользователь нажимает мой Проверять Кнопку (в моем C#, WinForm, приложении .net 3.5), я хотел бы потянуть границу вокруг определенного управления, если это пусто. Скажите текстовое поле, которое называют tbxLastName, я думал, что должен был сделать что-то вроде этого->
ControlPaint.DrawBorder(Graphics.FromHwnd(this.Handle),
tbxLastName.ClientRectangle, Color.Firebrick, ButtonBorderStyle.Solid);
К сожалению, я понятия не имею, что поместить для Графического Объекта как, что я имею, НИЧЕГО не делает.
Все примеры, с которыми я столкнулся, MSDN - ЗДЕСЬ, имеют этот код в Событии Краски. Как так->
private void panel1_Paint(object sender, PaintEventArgs e)
{
ControlPaint.DrawBorder(e.Graphics, this.panel1.ClientRectangle,
Color.DarkBlue, ButtonBorderStyle.Solid);
}
Я, однако, только хочу иметь границу, появляются, в то время как определенные условия, встречаются, который начат Button_Click
Столь многие предложения предлагают использовать контейнерный объект для содержания текстового поля и вызова, это - Paint_Event. Я сделал это, и поле появляется, но НЕ вокруг управления. Это появляется в Верхнем левом углу Контейнерного Управления. Вот то, что я делаю->
private void grpImmunizationCntrl_Paint(object sender, PaintEventArgs e)
{
if (lkuNOImmunizationReason.Text.Equals(string.Empty)
{
ControlPaint.DrawBorder(
e.Graphics, lkuNOImmunizationReason.ClientRectangle,
Color.Firebrick, ButtonBorderStyle.Solid);
}
}
Править
Это - то, что я придумал объединяющиеся предложения здесь с тем, что работало на меня.
public static void HighlightRequiredFields(Control container, Graphics graphics, Boolean isVisible)
{
Rectangle rect = default(Rectangle);
foreach (Control control in container.Controls)
{
if (control.Tag is string && control.Tag.ToString() == "required")
{
rect = control.Bounds;
rect.Inflate(3, 3);
if (isVisible && control.Text.Equals(string.Empty))
{
ControlPaint.DrawBorder(graphics, rect, Color.FromArgb(173,216,230), ButtonBorderStyle.Solid);
}
else
{
ControlPaint.DrawBorder(graphics, rect, container.BackColor, ButtonBorderStyle.None);
}
}
if (control.HasChildren)
{
foreach (Control ctrl in control.Controls)
{
HighlightRequiredFields(ctrl, graphics, isVisible);
}
}
}
}
Я называю это от Paint_Event
из любого Контейнера я должен.
Я только что сделал кое-что подобное с VB.Net, с помощью этого потока. У меня есть контейнер Panel
вокруг каждого набора моих элементов управления, а в OnPaint
обработчике Panel
я перебираю все дочерние элементы управления в Panel
и рисую границы вокруг них, если они имеют тег tag="required"
. Я отображаю границы только на Edit или New, поэтому я создал параметр fVisible
, чтобы включить и выключить их. Когда я хочу это выключить, я вызываю Panel.Refresh()
, поэтому он запускает событие OnPaint
. Таким образом, все, что мне нужно сделать, это установить теги на требуемых элементах управления во время проектирования, и добавить обработчик для панелей контейнеров, и все это будет работать динамически.
Вот общая функция, которую я вызываю из всех обработчиков событий моей панели OnPaint
. (Извините, я знаю, что вы используете C#, а это VB, но это довольно элементарно.)
Friend Sub HighlightRequiredFields(ByVal pnlContainer As Panel, ByVal gr As Graphics, ByVal fVisible As Boolean)
Dim rect As Rectangle
For Each oControl As Control In pnlContainer.Controls
If TypeOf oControl.Tag Is String AndAlso oControl.Tag.ToString = "required" Then
rect = oControl.Bounds
rect.Inflate(1, 1)
If fVisible Then
ControlPaint.DrawBorder(gr, rect, Color.Red, ButtonBorderStyle.Solid)
Else
ControlPaint.DrawBorder(gr, rect, pnlContainer.BackColor, ButtonBorderStyle.None)
End If
End If
If TypeOf oControl Is Panel Then HighlightRequiredFields(DirectCast(oControl, Panel), gr, fVisible)
Next
End Sub
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
if (string.IsNullOrEmpty(Text))
{
this.BorderStyle = BorderStyle.FixedSingle;
}
else
{
this.BorderStyle = BorderStyle.Fixed3D;
}
}
вы можете использовать поле списка действий в форме и добавлять или удалять собственные рисунки:
// field
List<Action<Graphics>> drawings = new List<Action<Graphics>>();
// on click event:
drawings.Add(delegate(Graphics g) {
var rect = tbxLastName.Bounds;
rect.Inflate(1, 1); // make rectange a bit larger than textbox
ControlPaint.DrawBorder(g, rect,
Color.DarkBlue, ButtonBorderStyle.Solid);
});
// make sure you added only once or clear before
panel1.Refresh(); // refresh panel to force painting
// Paint method:
foreach (var draw in drawings) {
draw(e.Graphics);
}
Таким образом вы можете добавить более одной границы
Причина, по которой ваш прямоугольник "пропущен" в текстовом поле, заключается в том, что ClientRectangle содержит только размер элемента управления, а не его местоположение. Попробуйте вместо этого:
private void grpImmunizationCntrl_Paint(object sender, PaintEventArgs e)
{
if (lkuNOImmunizationReason.Text.Equals(string.Empty)
{
ControlPaint.DrawBorder(
e.Graphics, new Rectangle(lkuNOImmunizationReason.Left, lkuNOImmunizationReason.Top, lkuNOImmunizationReason.ClientRectangle.Width, lkuNOImmunizationReason.ClientRectangle.Height),
Color.Firebrick, ButtonBorderStyle.Solid);
}
}
Текстовые поля не вызывают метод OnPaint (см. , примечание
раздел на этой странице
). Обойти это можно, поместив текстовое поле на панель, которая немного больше.Затем меняйте цвет фона при каждом нажатии кнопки. В ветке на форумах MSDN есть несколько решений.
Редактировать Чтобы прояснить решение панели, просто создайте панель и добавьте к ней свое текстовое поле: например.
private void MyForm_Load(object sender, EventArgs e)
{
myPanel.Controls.Add(tbxLastName); //Make sure the panel size is slightly bigger than the text box (so that it looks like a border)
}
Затем обработайте событие нажатия кнопки:
private void myButton_Click(object sender, EventArgs e)
{
if (tbxLastName.Text == "")
{
myPanel.BackColor = Color.Red;
}
else
{
myPanel.BackColor = Color.Transparent;
}
}