Jak wyświetlić okno aby okno obecnie posiadające focus nie straciło go?
Zadanie (Windows Forms):
Z pierwszego okna otwórz drugie okno, które ma się pojawić nad pierwszym oknem, ale tak, żeby focus pozostał w pierwszym oknie.
Ostatnio
spotkałem się właśnie z takim problemem. Chciałem zaprogramować coś
a'la ToolTip, który będzie mi się pokazywał nad moim polem tekstowym i
w którym będę mógł umieszczać swoje informacje. Okazało się, że sprawa
nie jest tak oczywista jak mogłoby się wydawać. Oczywiście zacząłem od
ustawienia drugiej formatki jako
TopMost, żeby zawsze pojawiała
się na wierzchu. Największy problem polegał na zabraniu (albo najlepiej
nie daniu) otwieranemu oknu focusa.
Pierwsze znalezisko - ale niestety nie rozwiązuje problemu do końca.Dowiedziałem się, że implementując formatkę (dziedzicząc po Form) można nadpisać właściwość
ShowWithoutActivation.
protected override bool ShowWithoutActivation
{
get { return true; }
}Jeżeli to zrobmy i zwrócimy
true to okno będzie otwierało się
bez focusa. Fajnie, już myślałem, że sprawa załatwiona. Niestety okazuje się, że opcja ta nie działa jeżeli okno ma ustawioną właściwość
TopMost na
true :(. W komentarzu na
MSDN znalazłem, że aby podobny efekt uzyskać z oknem
TopMost to należy skorzystać bezpośrednio z API Windowsa.
Druga wersja - tym razem rozwiązująca zadanie.Po kolejnych kulku minutach na Googlach znalazłem to czego szukałem.
[DllImport("User32.dll")]
public extern static int ShowWindow(System.IntPtr hWnd, short cmdShow);Wywołanie
tej metody z uchwytem do pokazywanego okna i z parametrem cmdShow = 4
(SW_SHOWNOACTIVATE) załatwia sprawę. Okienko ładnie się pokazuje i nie
dostaje focusa. Great! :)
W załączniku umieściłem przykładową
aplikację, która pokazuje omówione tu techniki. Symuluje ona edycję
tekstu w polu tekstowym oraz wyświetlanie okien pomocniczych. Wciskając
kombinacje klawiszy CTRL + [Z, X, C] otwierać będą się kolejno: okno z
TopMost = true przy użyciu standardowej metody
Show, okno z ustawionym
TopMost = true, ale za pomocą metody
ShowWindow oraz okno z
TopMost = false z nadpisaną właściwością
ShowWithoutActivation zwracającą
true.
Jeżeli jesteście ciekawi to zerknijcie sobie.