Canvas not supported
Canvas not supported
Suchen
Bookmark
Canvas not supported
Shine Effekt
Direkt zum Seiteninhalt

Hauptmenü:

Fenster und Steuerelemente verbergen

 

Autor:

Oscar Kohler

Version:

0.11

Level:

Einfach

Sprache:

C/C++


 
Haftungsausschluss / Disclaimer
Kontakt / Contact
Drucken / Print


Manche Programme lassen es freundlicherweise zu, die Sicht bestimmter Steuerelemente durch die System Administration zu konfigurieren ... andere jedoch leider nicht.

Fenster verbergen: Ein Praxis Beispiel ...


Wir installieren ein Programm das für die Bearbeitung bestimmter Daten nötig ist. Manchen Benutzern, die für die Bearbeitung nicht geschult wurden, reicht die Anzeige der Daten vollkommen aus. Wenn das Programm nicht bereits über ein Benutzer-Rechtesystem verfügt, riskieren wir, dass wichtige Daten unabsichtlich beschädigt werden. Ausserdem wird der Benutzer frustriert, da er vom Funktionsumfang überfordert ist und zudem immer aufpassen muss, nicht versehentlich Daten zu manipulieren.

Für die Sinnhaftigkeit, bestimmte Fenster und Steuerelemente zu verbergen finden sich etliche Beispiele. Immer unter der Voraussetzung, dass sonst wirklich keine andere Möglichkeit zur Konfiguration geboten wird !

Wichtig ist noch, dass diese Funktionen implementiert wurden um die Möglichkeit zu bieten, die Bedienung der Programme für den Benutzer angenehmer und sicherer zu gestalten. Und nicht um Scherzprogramme zu basteln und damit seinen Kumpels auf die Nerven zu gehen !

Das Commandline Fenster verstecken ...


Commandline Fenster versteckenWieder ein Beispiel aus der Praxis: Um unsere kostbare Fotosammlung zur Sicherung von einem Ordner in einen anderen Ordner zu kopieren, haben wir uns eine kleine Batch Datei geschrieben. Unsere Foto Sammlung wird immer umfangreicher, und somit dauert der Kopier Job mittlererweile leider "Stunden". Sobald wir nun unser Script starten, poppt ein schwarzes Commandline Fenster auf und wir können zusehen, wie die Fotos der Reihe nach kopiert werden ...

  • Nur, eigentlich müssen wir da nicht unbedingt zusehen ...

  • Das Fenster nervt, weil es uns nun immer im Weg steht ...

  • Versehentlich haben wir es weggeklickt und der Kopiervorgang wurde abgebrochen ...


Hier wäre es doch praktisch, wenn wir das Fenster solange verstecken könnten, bis entweder der Kopiervorgang abgeschlossen ist, oder ein gravierender Fehler auftrat.

Die Technik ...


Die Frage ist nun, wie können wir unser eigenes Konsolenfenster je nach Bedarf sichtbar oder unsichtbar machen ?
Wir wissen bereits, wenn wir ein Fenster "aufgreifen" möchten, benötigen wir immer ein Handle (hWND).
Wer die Techniken hinter den Windows Fenstern nicht mehr so genau im Blick hat, kann hier nochmals nachlesen:

Blitz Tutorial: Fenster

Gut, wir brauchen also ein Fensterhandle auf unser eigenes Konsolenfenster. Das wäre gar nicht mal so einfach, wenn uns Microsoft nicht mit einer netten Api-Funktion beschenkt hätte:

HWND WINAPI GetConsoleWindow(void);

MSDN: GetConsoleWindow()


Nachdem wir das Handle auf das Konsole Fenster in den Händen halten, können wir nun das Fenster je nach Bedarf ausknippsen und auch wieder anknippsen.

Windows bietet eine stattliche Anzahl von Funktionen zum Umgang mit Fenstern.

MSDN: Windows Funktionen


Eine davon bietet sich genau für unsere Zwecke an und hört auf den sprechenden Namen ShowWindow().

BOOL WINAPI ShowWindow(
  __in  HWND hWnd,
  __in  int nCmdShow
);

MSDN: ShowWindow()


hWnd ist unser geliebtes Fenster Handle, nCmdShow eine Konstante mit der wir die "Sichtbarkeit" des Fensters angeben können.
Für unseren Einsatz interessiert uns speziell:

  • SW_HIDE: Verbirgt das Fenster,

  • SW_SHOW: Zeigt das Fenster wieder an.


Nun können wir bereits ein kleines Testprogramm schreiben, das unser Konsolen Fenster zuerst unsichtbar und nach einer Sekunde wieder sichtbar machen kann.
Wichtig ist hierbei noch, das dieses Programm für Konsole und nicht für das Win32 Subsystem kompiliert wird.

01 #define _WIN32_WINNT 0x0501
02
03
#include
04
#include
05
#include
06
07 int _tmain(int argc, _TCHAR* argv[]) {
08     
09     
// Eigenes Konsolenfenster ermitteln
10
11     HWND hWnd = GetConsoleWindow();
12
13     
// Fenster für eine Sekunde verbergen
14
15     if (hWnd != NULL) {
16         ShowWindow(hWnd, SW_HIDE);
17         Sleep(1000);
18         ShowWindow(hWnd, SW_SHOW);
19     }
20
21     return 0;
22 }

Aufgerufen wird es nun über eine kleine Batch Datei:

@echo off
echo Dieses Konsolenfenster fuer eine Sekunden verstecken !
pause
hide_my_console_4_1_second.exe
echo Konsolenfenster ist nun wieder sichtbar.
pause


Wem das Ausknippsen des Fensters nun zu blutrünstig war, der kann die Konsole auch ganz human minimieren:

  • SW_MINIMIZE: Fenster minimieren,

  • SW_RESTORE: Fenster in normaler Grösse anzeigen.


Das Windows Fenster verstecken ...


Windows Fenster versteckenDas Commandline Fenster war nun ein recht unkompliziertes Beispiel. Vorallem weil Windows ohne Mucken und Murren den Handle unseres Konsolenfensters rausrückte.
Wie sieht es nun aber aus, wenn wir das Versteckspiel mit einem anderen Windowsfenster durchführen möchten ?
Wie würden wir manuell ein Fenster minimieren ?
Indem wir optisch das Fenster anhand des Titels raussuchen und mit der Maus minimieren. Prinzipiell genauso wird es auch automatisiert gemacht.

Für unser Beispiel wählen wir unvoreingenommen wieder unser Lieblingsprogramm: den Windows Taschenrechner

Spy++Zuerst müssen wir also das Fenster des Taschenrechners finden:

Tutorial: Fenster Spionage

Mit Spy++ suchen wir den Windows "Rechner" und lassen uns die Fensterdaten anzeigen. Wichtig für uns, sind die beiden bekannten Attribute:

Titel (Beschriftung)
Fenster Klasse

In unserem Fall nennt sich der Titel: Rechner und die Klasse: SciCalc.
So, nun hätten wir also unsere beiden Attribute, nur die passende Windows Funktion fehlt noch ...
Wie könnte die denn heissen ? Suche Fenster ? Finde Fenster ?

Bingo ! Genau, das wars: FindWindow()

HWND WINAPI FindWindow(
  __in_opt  LPCTSTR lpClassName,
  __in_opt  LPCTSTR lpWindowName
);

MSDN: FindWindow()


Nun haben wir das Rüstzeug zusammen um wieder ein kleines Testprogramm zu schreiben, das den Rechner für eine Sekunde "verschwinden" lässt.

01 #define _WIN32_WINNT 0x0501
02
03
#include
04
#include
05
#include
06
07 int _tmain(int argc, _TCHAR* argv[]) {
08     
09     
// Windows Rechner suchen
10
11     HWND hWnd = FindWindow ( _T("SciCalc"),
12                              _T("Rechner") );
13
14     
// Rechner für eine Sekunde verbergen
15
16     if (hWnd != NULL) {
17         ShowWindow(hWnd, SW_HIDE);
18         Sleep(1000);
19         ShowWindow(hWnd, SW_SHOW);
20     }
21
22     return 0;
23 }

Wer sich über das Konstrukt _T(...) wundert, dies ist nur ein Makro, das bei Unicode Kompilierung auch Unicode Chars verwendet.
Aufgerufen wird das Testprogramm entweder manuell oder wieder über eine kleine Batch Datei:

@echo off
echo Den Windows Rechner fuer eine Sekunden verstecken !
pause
hide_calc_4_1_second.exe
echo Rechner ist nun wieder sichtbar.
pause


Nun stellt sich noch eine Frage. Die FindWindow() Funktion gibt uns eine Adresse zum Fenster des Rechners. Was wäre jedoch, wenn nun mehrere Rechner auf dem Desktop sitzen ?
Dann erhalten wie die Adresse, die als erstes gefunden wurde. Wollen wir auch noch die der anderen Rechner, müssen wir ein anderes Verfahren anwenden. Alle Fenster des Dektops enumerieren und jeweils prüfen, ob unser gewünschtes dabei ist.

BOOL WINAPI EnumWindows(
  __in  WNDENUMPROC lpEnumFunc,
  __in  LPARAM lParam
);

MSDN: EnumWindows()


Einzelne Windows Steuerelemente verstecken ...


Nun kommen wir langsam zum interessanten Teil. In der Praxiseinführung haben wir darüber gesprochen wie praktisch es doch wäre, ganz gezielt einzelne Steuerelemente eines Programm ein - und ausblenden zu können. Die halbe Miete haben wir bereits, nun geht es nur noch darum, auf die einzelnen Steuerelemente zugreifen zu können.

Mittels FindWindow() erhielten wir bereits das Handel des gwünschten Programmfensters und wir haben auch schon gehört, dass Steuerelemente prinzipiell auch "nur" Fenster sind.

Wir gehen nun folgendermassen vor:

  • Programm Fenster suchen,

  • Steuerelement suchen,

  • Sichtbarkeit des Steuerelements ändern.


Wie kommen wir nun an das Steuerelement ?
FindWindow() funktioniert nicht, da wir damit nur TopLevel Fenster auslesen können. Doch glücklicherweise findet sich zu FindWindow() auch noch eine erweiterte Version: FindWindowEx()

HWND WINAPI FindWindowEx(
  __in_opt  HWND hwndParent,
  __in_opt  HWND hwndChildAfter,
  __in_opt  LPCTSTR lpszClass,
  __in_opt  LPCTSTR lpszWindow
);

MSDN: FindWindowEx()


Und wieder kommt unser Lieblings Rechner zum Einsatz. Dieses Mal ist unser Ziel, den Button mit der Zahl "6" für genau eine Sekunde zu verbergen.

Spy++Das Fenster Handle hwndParent haben wir bereits, nämlich das Fenster des Rechners, das Child Handle hwndChildAfter benötigen wir in unserem Fall aufgrund der einfachen Hirarchie nicht.
Nun müssen wir also lediglich mit Spy++ die beiden beliebten Fensterattribute auslesen:

Titel (Beschriftung)
Windows Klasse

Die haben wir recht schnell zur Hand. Unsere Taste ist mit "6" beschriftet, und hat daher den Titel "6". Die Klasse ist die integrierte Steuerelemente Klasse "Button".
Wer nun aufgepasst hat, braucht eigentlich keinen Spy++ um die Steuerelemente rauszusuchen. Eine gute handvoll Steuerelemente Klassen im Kopf, und den Titel des Elemens abzulesen genügt in den meisten Fällen.

Damit haben wir nun alle Funktionen um unser Testprogram so zu erweitern, dass die Taste "6" auf dem Windows Rechner für eine Sekunde deaktiviert wird.

01 #define _WIN32_WINNT 0x0501
02
03
#include
04
#include
05
#include
06
07 int _tmain(int argc, _TCHAR* argv[]) {
08     
09     
// Taste 6 für eine Sekunde verbergen
10
11     HWND hWnd = FindWindow ( _T("SciCalc"),
12                              _T("Rechner") );
13     if (hWnd != NULL) {
14         HWND hButton = FindWindowEx ( hWnd,
15                                       NULL,
16                                       _T("Button"),
17                                       _T("6") );
18         if (hButton != NULL) {
19            ShowWindow(hButton, SW_HIDE);
20            Sleep(1000);
21            ShowWindow(hButton, SW_SHOW);
22         }
23     }
24
25     return 0;
26 }

Starten können wir das Testprogramm wie in den oberen Fällen, entweder manuell oder über eine Batch Datei.

@echo off
echo Taste 6 fuer eine Sekunden verstecken !
pause
hide_calc_6_4_1_second.exe
echo Taste 6 ist nun wieder sichtbar.
pause


Einzelne Windows Steuerelemente versteckenDas Resultat sieht schon mal sehr beeindruckend aus ! Wie von Geisterhand ist die Taste "6" verschwunden und taucht nach einer Sekunde wieder auf. Gruslig ... vorallem weil es nun eher danach aussieht, dass das Programm irgendwie kaputt ist. Man kommt weniger auf die Idee, dass die Taste "6" gewollt ausgeblendet wurde, sondern eher, dass mit dem Programm etwas nicht stimmt, nicht ?

Tasten und Menupunkte werden in der Praxis normalerweise disabled, wenn der Benutzer diese Tasten zu dieser Zeit nicht benutzen soll ...

Diese kleine Hürde werden wir nun auch noch schaffen !

Die Lösung ist auch recht naheliegend.
Wir müssen nur die Showwindow() Funktion durch eine Funktion ersetzen, die den Button nicht ausblendet sondern nur disabled.

Freundlicherweise beglückte uns Microsoft auch mit solch einer Funktion die sie sinnigerweise: EnableWindow() tauften.
Die Funktion findet sich allerdings in der "Keyboard Input Reference", da sie den Input zum Control unterbindet, was von uns ja auch erwünscht ist.

BOOL WINAPI EnableWindow(
  __in  HWND hWnd,
  __in  BOOL bEnable
);

MSDN: EnableWindow()


Einzelne Windows Steuerelemente verbergenNun müssen wir in unserem Testprogramm nur noch die Funktion ShowWindow() ...

ShowWindow(hButton, SW_HIDE);
Sleep(1000);
ShowWindow(hButton, SW_SHOW);

... gegen die Funktion EnableWindow() ersetzen.

EnableWindow(hButton, false);
Sleep(1000);
EnableWindow(hButton, true);

Einzelne Windows Steuerelemente verbergenAnwendbar sind diese Funktionen bei den verschiedensten Steuerelemente Typen. Die Taste "6" war vom Typ "Button". Das Anzeigefeld links vom Typ "Edit".

Durch geschicktes anwenden der Funktion FindWindowEx() kann man sich durch die Fenster durchhangeln und erreicht so praktisch jedes Steuerelement.


Zum Abschluss dieses Tutorials möchte ich noch auf folgende mögliche Probleme und Risiken aufmerksam machen:


  • Wie schon bei der Fenster Spionage, tritt auch hier wieder das Problem der Internationalisierung auf. Die Titel-Texte heissen natürlich je nach Gebietsregion komplett anders. Das muss immer berücksichtigt werden.

  • Bei Fenster Funktionen ist immer Vorsicht geboten und dürfen daher nur sehr bedacht angewendet werden. Einserseits ist immer darauf zu achten, dass man sich selbst nicht ausperrt und das Fenster nicht mehr bedienbar wird, andererseits können nicht alle Programme mit manipulierten Fenstern umgehen ! Hier kann es zu Funktionsstörungen kommen, die unter Umständen nicht sofort erkennbar sind.

  • Möglicherweise wird durch die Fenstermanipulation sogar irgendein Punkt in der EULA (Vertragsvereinbarung) des Programmes verletzt. Dies ist auch immer zu prüfen !


Ganz generell ist es jedem selbst überlassen, ob und wie Api Funktionen angewendet werden und jeder trägt selbst die Verantwortung dafür !


 
Kein Kommentar
 
Letzte Änderung: 03.02.2015
button Canvas not supported button
Zurück zum Seiteninhalt | Zurück zum Hauptmenü