2013-05-07 4 views
0

스크롤 막대가있는 사용자 정의 컨트롤 (패널에서 상속 한 포함 된 사용자 정의 컨트롤로 스크롤바가 나타남)이 너무 깁니다. 마우스를 사용하여 스크롤 할 때 모두 잘되지만 마우스 휠을 사용하여 스크롤하려고하면 작동하지 않습니다.스크롤에 초점

여기 내 솔루션은 Scroll에 대한 이벤트 처리기에서 내 자식 제어에 초점을 설정하는 것입니다. 이 작동합니다. 이제 질문. 이로 인해 childControl.Focus()에 불필요한 전화가 많이 걸립니까? 이 일을하는 더 깔끔한 방법이 있습니까?

편집 : 나는 내 질문에 이렇게 질문을 다른 표현으로 약간 불분명 생각 :

포커스를 설정하는 나쁜 방법

private void ChildControl_OnScroll(object sender, ScrollEventArgs scrollEventArgs) 
{ 
    this.childControl.Focus(); 
} 

입니까? 나는. 스크롤 할 때마다 포커스가 여러 번 반복됩니까? 또는 오히려 이로 인해 성능 문제가 발생할 수 있습니다.

+1

질문에 대한 자세한 내용은 나와 있지 않습니다. 당신은 당신이 사용하고있는 통제와 배치 방법을 언급하지 않았습니다. –

+0

질문이 업데이트되었습니다. – Mystogan

+0

아마도이 문제를 데모하는 작은 코드를 포함시킬 수 있습니까? –

답변

1

SomeUserControl 내부의 panel1 스크롤바 영역을 클릭했을 때 초점을 맞추는 또 다른 방법이 있습니다. NativeWindow를 사용하므로 UserControl에서 패널을 변경할 필요가 없습니다. 마우스가 스크롤 영역에 아래 을 갈 때이 방법 초점()는 한 번만 호출됩니다 :

public partial class SomeUserControl : UserControl 
{ 
    private TrapMouseDownOnScrollArea trapScroll = null; 

    public SomeUserControl() 
    { 
     InitializeComponent(); 
     this.VisibleChanged += new EventHandler(SomeUserControl_VisibleChanged); 
    } 

    void SomeUserControl_VisibleChanged(object sender, EventArgs e) 
    { 
     if (this.Visible && trapScroll == null) 
     { 
      trapScroll = new TrapMouseDownOnScrollArea(this.panel1); 
     } 
    } 

    private class TrapMouseDownOnScrollArea : NativeWindow 
    { 
     private Control control = null; 
     private const int WM_NCLBUTTONDOWN = 0xA1; 

     public TrapMouseDownOnScrollArea(Control ctl) 
     { 
      if (ctl != null && ctl.IsHandleCreated) 
      { 
       this.control = ctl; 
       this.AssignHandle(ctl.Handle); 
      } 
     } 

     protected override void WndProc(ref Message m) 
     { 
      switch (m.Msg) 
      { 
       case WM_NCLBUTTONDOWN: 
        if (this.control != null) 
        { 
         Rectangle screenBounds = control.RectangleToScreen(new Rectangle(0, 0, control.Width, control.Height)); 
         if (screenBounds.Contains(Cursor.Position)) 
         { 
          control.Focus(); 
         } 
        } 

        break; 
      } 
      base.WndProc(ref m); 
     } 

    } 

} 

이 시나리오에 대한 잔인한 수도 있지만 트랩 낮은 수준 메시지에 대한 한 가지 방법을 보여줍니다. 이전에 말했듯이 Panel에서 파생되어 동일한 효과를 얻을 수 있습니다. IMessageFilter를 사용하여 응용 프로그램 수준에서 메시지를 트랩 할 수도 있습니다.

+0

니스! 고마워! – Mystogan

1

MouseWheel 이벤트는 "거품 나는"이벤트입니다. Windows는 마우스 커서의 위치에 관계없이 포커스가있는 컨트롤로 보냅니다. 가장 일반적인 문제는 포커스를받을 수없는 컨트롤이 있다는 것입니다. 패널 예를 들어.

패널에 컨트롤을 배치하면 변경됩니다. 이제 해당 컨트롤이 포커스를 가져올 수 있으며 MouseWheel 메시지를 가져옵니다. 메시지를 사용하지 않으므로 메시지가 부모에게 전달됩니다. 어떤 을 사용하면을 사용할 수 있으며 예상대로 패널이 스크롤됩니다.

this answer에서 집중 가능한 패널 컨트롤을 사용할 수 있습니다. childControl가 MouseEnter을()가있는 경우 this question

+0

설명 주셔서 감사합니다! 그러나, 실제로 포커스를 설정할 수 있습니다, 내 질문에 오히려 어떤 단점 또는 디자인 포커스 때 스크롤 할 때 포커스를 설정하는 것입니다. – Mystogan

+0

연결이 표시되지 않습니다. 프로그램에 초점을 맞추는 것은 나쁜 생각입니다. 항상 사용자에게 맡겨야합니다. –

0

에서 일반적인는 "이 브라우저 나 오피스 프로그램처럼 작동하게"솔루션 이벤트는 대신에를 사용

private void childControl_MouseEnter(object sender, EventArgs e) 
    { 
     childControl.Focus(); 
    } 

그런 다음 마우스 휠 이벤트가 childControl 직접해야한다 .

+0

나는 MouseEnter를 사용하지 않을 것이다 ... 사용자가 스크롤바를 실제로 클릭했을 때만 이것을 설정한다. (그리고'Click' 이벤트를 사용해 보았지만 도움은 안된다.) – Mystogan

+0

** 스크롤 막대 영역 ** 마우스를 아래쪽으로 트랩하려면 기본 클래스에서 상속 받고 WndProc()에서 WM_NCLBUTTONDOWN 메시지를 찾을 수 있습니다. –