2010-03-02 7 views
11

Tworzę niestandardowy formant oparty na UserControl, dla którego chciałbym ustawić fokus.Ustawianie ostrości na .NET UserControl ...?

Niestandardowy element sterujący zawiera kontrolkę ComboBox, a ja rysuję obok niego kilka ciągów.

ComboBox może otrzymać fokus, ale chciałbym móc ustawić fokus na UserControl. Mój program obsługi OnPaint jest skonfigurowany tak, aby rysować kontrolkę nieco inaczej, jeśli ma fokus, ale wywołuję CanFocus() z formularza nadrzędnego, gdy tworzę kontrolkę niestandardową i zwraca wartość false.

Czy istnieje właściwość lub element do ustawienia?

Odpowiedz

21

UserControl będzie walczyć z wami i paznokciami, aby uniknąć koncentracji. Ma kod, który automatycznie przekazuje fokus do kontrolki podrzędnej (jeśli jest), jeśli ma fokus. Będziesz musiał co najmniej przesłonić funkcję WndProc() i przechwycić komunikat WM_SETFOCUS. Mogą być potrzebne inne operacje, takie jak ControlStyles.Selectable oraz właściwości TabStop i TabIndex.

Twoim następnym problemem jest to, że UserControl nie reaguje w znaczący sposób na, powiedzmy, komunikaty na klawiaturze, gdy ma fokus. Będziesz musiał wykrywać kliknięcia na tle UC, aby obsługiwać komunikaty myszy, a także przesłonić obraz, aby było jasne dla użytkownika, że ​​UC ma fokus (użyj ControlPaint.DrawFocusRectangle). Jeśli brzmi to nieatrakcyjnie, to dlatego, że UC miało być kontrolerem kontenera.

+1

To wydawało się wykonywać tę pracę. Nadal będę się z nim bawił, żeby uporządkować zawiłości, o których wspomniałeś. Dzięki! – Sambo

+1

+1 Cieszę się, że mam kolejną wspaniałą odpowiedź od NoBugza. Ciekawy: czy w tym przypadku uważasz, że OP mógłby zrobić lepiej przy użyciu formularza zamiast kontrolki użytkownika? – BillW

+2

@Bill: klasa Form jest również kontrolką kontenera, chociaż nie będzie walczyć w podobny sposób. Moja rada musiałaby polegać na unikaniu niestandardowych praktyk interfejsu użytkownika. Dezorientuje również użytkownika. –

1

Od http://msdn.microsoft.com/en-us/library/system.windows.forms.control.canfocus.aspx

Uwagi

w celu kontroli otrzymywać wejściowego ostrości, kontrola musi mieć uchwyt przypisany do niego, a Visible i Włączone właściwości musi zarówno być ustawiona na wartość true dla wszystkich formantu nadrzędnego, a kontrola musi być formą lub kontem Zewnętrzny rodzic rola musi być formularzem .

Upewnij się, że spełniasz te wstępne zwroty.

+1

Dziękuję za odpowiedź ... Potwierdziłem, że moja kontrola ma wartość Handle. Kontrola jest widoczna i włączona, a panel, w którym ją wyświetlam, jest widoczny i włączony ... i wszystko pojawia się na formularzu ...! To wydaje się spełniać warunki wstępne ... Przełamałem OnGotFocus() i ustawiłem punkt przerwania, ale nigdy nie został trafiony. Ponadto ustawiłem program obsługi w moim obiekcie formularzy dla zdarzenia GotFocus kontrolnego i po raz kolejny kod nigdy nie został trafiony. Jakieś inne pomysły ...? – Sambo

+0

Te wymagania wstępne dotyczą Kontroli, ale UserControl sabotuje to jako @HansPassant wymienione powyżej. –

1

zbyt długi komentarz, zawiera link i kod ... ale to jest komentarz ...

Wiele osób skarżyło się o UserControl nie wypalanie „GotFocus() wydarzenie. Na przykład: UserControl and GotFocus() fyi: LostFocus() zostanie uruchomiony zgodnie z oczekiwaniami, z mojego doświadczenia. W przeszłości w projekcie z wieloma formularzami eksperymentowałem z implementowaniem programów obsługi zdarzeń "Enter" i "Leave" na kontrolerze UserControl na każdym formularzu i stwierdziłem, że "Enter jest wywoływany tylko raz przy ładowaniu formularza, jeden raz.

Najwyraźniej kontrole w UserControl "biorą ostrość" (w pewnym sensie nie mogę tego wytłumaczyć, ale prawdopodobnie jeden z guru SO z WinForms będzie). Być może jest to związane z faktem, że UserControl schodzi z ContainerControl?

eksperymentowałem z pisaniem jeden „GotFocus() Handler:

private void Control_GotFocus(object sender, EventArgs e) 
    { 
     Console.WriteLine("Control GotFocus : " + ((sender as Control).Name)); 
    } 

a następnie w usercontrol” zdarzenie Load przewodowego się wszystkie kontrolki na UserControl do tej obsługi zdarzeń: co zaobserwowałem, że Kontrola w UserControl przy najniższym TabIndex uruchamiałaby zdarzenie "GotFocus" tuż po uruchomieniu aplikacji i przełączeniu między Formami.

Jedyną rzeczą, o której wspomniałem w tej sytuacji, jest upewnienie się, że właściwość "IsTabStop w UserControl jest ustawiona na" True: to było z Shawn Wildermuth w MS w kontekście pytania związanego z SilverLight, więc nie mam pojęcia, czy to może dotyczyć twojej sprawy.

Inna propozycja, która polegała na napisaniu obsługi zdarzeń MouseDown lub MouseClick dla UserControl, oraz w wywołaniu: this.SetFocus(); doprowadziła mnie donikąd.

Mam nadzieję, że otrzymasz odpowiedź!

1

W niektórych przypadkach jest również pożądane, aby nie pozwolić fokusowi przejść do elementów potomnych kontrolki UserControl.
W takim przypadku należy również ustawić wartość ControlStyles.ContainerControl na wartość false.

Public Sub New() 
    InitializeComponent() 

    Me.SetStyle(ControlStyles.ContainerControl, False) 
    Me.SetStyle(ControlStyles.Selectable, True) 

End Sub 
0

Powiedzmy, że masz obraz na kontroli użytkownika i chcesz, aby podświetlić go naśladując „GetFocus” event (słownie skupić się na kontroli użytkownika trwa ten obraz). Skoncentrowanie się na kontroli użytkownika będzie obsługiwane przez rysowanie linii przerywanej linii do PictureBox. Odbywa się to za pośrednictwem zdarzeń kontrolnych użytkownika OnEnter i OnLeave. Oto procedura podświetlenia ...

Public Sub highlightImage() 
    Dim l As Single() = {2, 2, 2, 2} 
    Dim p As New Pen(Color.Gray, 1) 
    p.DashPattern = l 
    Dim g As Graphics = picColor.CreateGraphics() 
    g.DrawRectangle(p, 0, 0, picColor.Width - 1, picColor.Height - 1) 
End Sub 

Te dwa przesłonięcia wykonają zadanie.

Protected Overrides Sub OnEnter(e As EventArgs) 
    MyBase.OnEnter(e) 
    Me.highlightImage() 
End Sub 
Protected Overrides Sub OnLeave(e As EventArgs) 
    MyBase.OnLeave(e) 
    MyBase.Refresh() 
End Sub 
0

Jeśli UserControl skupia się, wewnętrznie przekazuje fokus do kontroli podrzędnej.

Musisz więc pominąć wykonanie kodu, który ustawia fokus na kontrolę podrzędną. W tym celu należy zastąpić WndProc() pominięcie wykonywania dowolnej wiadomości WM_SETFOCUS.

public class FocusableUserControl : UserControl 
{ 
    protected override void WndProc(ref Message m) 
    { 
     switch (m.Msg) 
     { 
      case (int)Win32Constants.WM_SETFOCUS: 
      //Returning from here will skip setting focus to child controls. 
      //It will not skip setting focus to this control. 

       Console.WriteLine("FocusableUserControl is focused: " + Focused); 
       return; 
     } 

     base.WndProc(ref m); 
    } 
} 

Gdzie WM_SETFOCUS to "0x0007".