2010-02-03 6 views
5

사용자가 내 유효성 검사 단추 (내 C#, WinForm, .net 3.5 응용 프로그램)를 클릭하면 특정 컨트롤 주위에 테두리가 그려지기를 원합니다. >컨트롤 주위에 테두리 그리기 Button_Click

ControlPaint.DrawBorder(Graphics.FromHwnd(this.Handle), 
    tbxLastName.ClientRectangle, Color.Firebrick, ButtonBorderStyle.Solid); 

불행하게도, 나는 그래픽은 내가 아무것도하지 않는 무엇을 같은 개체에 대한 넣어 무슨 생각이 없다 - 나는 이런 식으로 뭔가를 할 필요가 생각 tbxLastName라는 텍스트 상자는 말.

나는 그림판 이벤트에서이 코드를 가지고있는 MSDN - HERE의 모든 예제를 보았습니다. 그래서처럼 ->

private void panel1_Paint(object sender, PaintEventArgs e) 
{  
    ControlPaint.DrawBorder(e.Graphics, this.panel1.ClientRectangle, 
     Color.DarkBlue, ButtonBorderStyle.Solid); 
} 

그러나 나는 특정 조건이 Button_Click


제안의 그래서 많은 사람들이 사용하는 것이 좋습니다 a로 쫓겨되어 대회를하는 동안 나타나는 경계를 갖고 싶어 container 객체를 사용하여 텍스트 상자를 잡고 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에서 호출합니다.

+0

그래픽은 Win32 DC와 동일합니다. http://msdn.microsoft.com/en-us/library/dd162467(VS.85).aspx –

답변

2

이 스레드의 도움으로 VB.Net과 비슷한 작업을 수행했습니다.각 컨트롤 주위에 Panel 컨테이너가 있고 PanelOnPaint 처리기에서 Panel의 모든 자식 컨트롤을 반복하고 tag="required"이있는 경우 경계선을 그립니다. 편집 또는 새로 만들기에서 테두리 만 표시하므로 fVisible 매개 변수를 만들어이 기능을 켜거나 끕니다. 이 기능을 해제하려면 Panel.Refresh()으로 전화하여 OnPaint 이벤트를 발생시킵니다. 이 방법은 디자인 타임에 필요한 컨트롤에 태그를 설정하고 컨테이너 패널에 대한 핸들러를 추가하는 것입니다. 모든 컨트롤은 동적으로 작동합니다.

여기 내 Panel의 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 
+0

흥미로운 방법 덕분에, 텍스트를 입력하면 강조 표시가 필요하므로 아래에 게시 한 것과 귀하의 방식을 결합 할 것입니다. 불행히도 우리는 매우 독특한 모델을 가지고 있습니다. 편집 또는 새로 만들기를 클릭하지 않고 데이터를 입력 한 후 이상한, 알고 있습니다! –

+0

하하는 분명히 희박합니다! 도와 주니 기쁩니다. –

1

텍스트 상자는 OnPaint 메서드를 호출하지 않습니다 (Note 섹션의 this page 참조). 한 가지 방법은 텍스트 상자를 약간 큰 패널에 배치하는 것입니다. 그런 다음 단추를 클릭 할 때마다 배경색을 변경하십시오. MSDN forums 이상의 스레드는 몇 가지 해결책이 있습니다.

편집 단순히 패널을 만들고, 패널 솔루션을 명확히하고 그것에 당신의 텍스트 상자를 추가하려면 : 예를 들어,

private void myButton_Click(object sender, EventArgs e) 
    { 
     if (tbxLastName.Text == "") 
     { 
      myPanel.BackColor = Color.Red; 
     } 
     else 
     { 
      myPanel.BackColor = Color.Transparent; 
     } 
    } 
+0

OnPaint 메서드가있는 컨트롤 인 경우 어떨까요? 또한, 이유에 대한 아이디어, 내가 그것을 Groupbox에 놓았을 때 Rect가 그린 때 컨트롤이 누락되었습니다 (OP 하단의 편집 참조)? 감사합니다 –

+0

OnPaint 메서드를 사용하려는 이유가 없으면 업데이트 된 답변에서 메서드를 시도 할 수 있습니다. – keyboardP

+0

아, 지금 당신이하고있는 것을 봅니다. 나는 이것에 대해 생각해야 할 것이다. 30 ~ 40 개의 컨트롤이있어 주위에 상자를 가져올 수 있습니다. 이 규모로 어떻게 구현할 지 궁금합니다. –

3

은 양식 조치 필드의 목록을 사용하여 추가 또는 제거, 사용자 정의 도면 수 :

// 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); 
} 

이 방법

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) 
} 

그런 다음 버튼 클릭 이벤트를 처리 하나 이상의 경계를 추가 할 수 있습니다.

+1

+1 .Inflate 메서드를 지적하기 위해, 나는 결코 그 점을 발견하지 못했습니다. 이전에 매우 편리 했었습니다. –

1
protected override void OnTextChanged(EventArgs e) 
    { 
     base.OnTextChanged(e); 
     if (string.IsNullOrEmpty(Text)) 
     { 
      this.BorderStyle = BorderStyle.FixedSingle; 
     } 
     else 
     { 
      this.BorderStyle = BorderStyle.Fixed3D; 
     } 
    } 
1

사각형이 텍스트 상자를 "누락"시키는 이유는 ClientRectangle에 위치가 아닌 컨트롤의 크기 만 포함되어 있기 때문입니다. 대신 다음을 시도하십시오 :

관련 문제