2014-10-02 13 views
5

Zauważam, że WinForm ma wiele metod, które przetwarzają komendy lub klucze (Process*()) i (pre) filtrują wiadomości systemowe, ale ich cele nie są dla mnie jasne.Jaki jest cel wszystkich metod Process * i wszystkich filtrów wiadomości?

Oficjalna dokumentacja jest nieco niejasna i nie znalazłem żadnej jasnej i kompletnej odpowiedzi.

mówię o następujących metod:

  • PreFilterMessage(ref Message m)
  • ProcessCmdKey(ref Message msg, Keys keyData)
  • WndProc(ref Message m)
  • ProcessDialogKey(Keys keyData)
  • PreProcessMessage(ref Message msg)
  • ProcessKeyMessage(ref Message m)
  • ProcessKeyPreview(ref Message m)

Niektóre są dla kluczy odcięta (jak ProcessCmdKey lub ProcessDialogKey), a niektóre wiadomości odcięta (nawzajem). Ale dlaczego tyle metod? Jakie są ich cele i zastosowania?

Przypuszczam, że kolejność wykonywania dla każdej metody jest inna.

Oto, co wiem (a myślę, wiem):

  • PreFilterMessage: najpierw przechwycić wiadomości. Możesz zatrzymać dystrybucję wiadomości dla wszystkich poniższych metod tutaj!
  • ProcessCmdKey: przechwytuje WSZYSTKIE klucze, a nawet kombinacje, klucze specjalne i polecenia. Dobrze wykrywa kluczowe skróty w całym formularzu (np. Ctrl + D). Możesz zatrzymać dystrybucję kluczy tutaj.
  • WndProc: sekundować przechwytywanie wiadomości po filtrowaniu? Używam go tylko do wykrycia, czy użytkownik kliknął w prawym górnym rogu "X", ale przypuszczam, że jest to możliwe na innej metodzie!
  • ProcessDialogKey: przechwytuje JEDEN klucz tylko, prawdopodobnie po ProcessCmdKey i przed wszystkimi zdarzeniami klawiszy kontrolek.
  • PreProcessMessage: przed WndProc i po PreFilterMessage? Nie wiem dokładnie, dlaczego jest używany.
  • ProcessKeyMessage: wiadomość kluczowa przechwytująca. Wydaje się, że jest rzadko używany.
  • ProcessKeyPreview: klucz przechwytywania przed zdarzeniem podglądu? Rzadko używane.

W głębi, myślę, że jest to prawidłowa kolejność wykonywania:

  1. filtr wstępny
  2. Filtr
  3. Preprocesuj
  4. Process
  5. Wydarzenia

Dlaczego tak wiele kroków?

Wszelkie informacje lub konkretne przypadki użycia zostaną docenione!

+0

W skrócie, z wielu z tych samych powodów masz 'KeyDown',' KeyUp' i 'KeyPress' ... abyś mógł otrzymać wiadomość w momencie najbardziej zgodnym z twoim celem (celami). Na różnych etapach otrzymujesz różne informacje. – DonBoitnott

Odpowiedz

9

Natywna aplikacja Windows GUI ma zazwyczaj jedną pętlę wiadomości, podstawową funkcją wywołania winapi jest GetMessage(). Ale ma wiele okien, które otrzymują wiadomości, podstawą wywołania winapi jest DispatchMessage(). W twojej aplikacji .NET masz jedno wywołanie Application.Run(), ale wiele metod WndProc(), po jednym dla każdej kontrolki. Większość z nich jest ukryta w kodzie .NET Framework, widoczna tylko wtedy, gdy ją przesłonisz.

Zazwyczaj istnieje potrzeba przechwycenia pętli wiadomości, przechwycenia komunikatu przed jego wysłaniem do kontrolki i przybycia do funkcji WndProc(). Najbardziej oczywistym powodem jest skrót klawiszowy, na którym chcesz działać, bez względu na to, na którym sterowaniu jest skupiony. Byłoby to oczywiście bolesne, gdybyś musiał użyć KeyDown na co kontrolka, aby wykryć skrót. I mniej oczywiste powody, formanty ActiveX są godne uwagi na konieczność negocjacji z ich hostem na przykład.

WinForm daje wiele punktów rozszerzeń do przechwytywania wiadomości. Zbyt wiele, naprawdę, ale nieuchronnie efekt uboczny, że nie chcą przewidzieć, w jakich przypadkach mogą być użyteczne. W celu:

  • IMessageFilter.PreFilterMessage() pozwala zajrzeć do wiadomości zaraz po jej pobraniu przez GetMessage(). Należy pamiętać, że można wyświetlać tylko wiadomości wysłane do kolejki komunikatów, podstawowe wywołanie to PostMessage(), nie można zobaczyć wysłanych wiadomości. Co ogranicza jego użyteczność do wprowadzania danych przez użytkownika, wiadomości z klawiatury i myszy. Rzadko by tak manipulować, ale można go użyć, aby mysz działała inaczej i aby wykryć interakcję użytkownika z programem. Programiści, którzy chcą automatycznie wylogować użytkownika po okresie bezczynności, używają go na przykład.
  • Zdarzenia OnPreviewKeyDown() i PreviewKeyDown. Specyficzne dla kontroli, na której koncentruje się. Sposób na kontrolę przechwytywania naciśnięcia klawisza, zanim zostanie przetestowany pod kątem skrótu. W ten sposób można na przykład wykryć klawisze kursora, zanim zostaną użyte do przesunięcia fokusa. Alternatywa dla nadpisania IsInputKey().
  • PreProcessMessage(). Bardzo podobne do PreFilterMessage, ale specyficzne dla kontroli, która ma fokus. Ważne dla formantów ActiveX, ja osobiście nigdy nie miałem z tego żadnego pożytku.
  • ProcessCmdKey(). Jest to metoda workhorse do implementacji własnych skrótów klawiaturowych.
  • IsInputKey(), pozwala kontrolować głosowanie, czy klucz normalnie używany do nawigacji powinien zostać wysłany do kontrolki. Zastępujesz tę metodę, gdy na przykład używasz klawiszy kursora.
  • ProcessDialogKey(). Podobnie jak ProcessCmdKey(), ale filtrowane dla klawiszy, które powinny być traktowane jak klucze wejściowe.Domyślna implementacja sprawia, że ​​wiadomość z komunikatem klawiatury jest kierowana do formantu nadrzędnego, co daje wybór, w którym należy zastąpić metodę ProcessCmdKey(). Nie potrafię wymyślić dobrego powodu, dla którego chciałbyś go zastąpić i nigdy nie zrobił tego, poza zatrzymaniem bulgotania.
  • IsInputChar(), bardzo podobny do IsInputKey, ale dla zdarzeń KeyPress. Nigdy go nie użyłem, ale sposób na wczesne filtrowanie danych wejściowych.
  • ProcessDialogChar(), można użyć do nadania skrótów klawiaturowych klawiszy pisania na klawiaturze. To niespotykane.
  • WndProc(), metoda Workhorse do przetwarzania wiadomości. Przesłonisz to, aby kontrola mogła reagować na wiadomości, które nie są w inny sposób objęte istniejącymi zdarzeniami. Lub dostosować zachowanie istniejących natywnych formantów.
  • ProcessKeyEventArgs(), ogólna metoda generowania zdarzeń klawiatury (OnKeyDown, OnKeyUp, OnKeyPress), wywoływana przez Control.WndProc(). Nie mogę wymyślić powodu, aby to zmienić, szczególnie przy implementacji dziwacznej właściwości Form.KeyPreview, właściwości zgodnej z VB6, prawdopodobnie z powodu jej ujawnienia.

Rzeczywiście kręty labirynt.

Próbując zachować rozsądek, należy zawsze zastępować ProcessCmdKey() w celu implementacji klawiszy skrótu. Zastąp IsInputKey(), aby pozwolić twojemu sterowi zobaczyć klawisze nawigacyjne. I tylko nadpisaj WndProc(), aby dostosować istniejące formanty.

+0

Wow! Jak zwykle świetna odpowiedź z wieloma szczegółami i przydatnymi informacjami! Twój wniosek jest trafny i pomocny. Jedyny czas, w którym użyłem PreFilterMessage, polegał na wysłaniu myszy przewijanej na nieostre formanty formularza (jeden z kodów umieszczonych na tej stronie). –