Hotkeys abfrage prob
-
Hi zusammen,
Ich hab ein Programm erstellt welches Auf drücken einer Taste Programme öffnet
void CBlaablaDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { char IsChar; IsChar = char(nChar); if(IsChar == 'A') { WinExec("calc.exe",SW_SHOW); } if(IsChar == 'B') { WinExec("sol.exe",SW_SHOW);} CDialog::OnKeyDown(nChar, nRepCnt, nFlags); }
Das funktioniert an sich auch Prima, allerdings NUR wenn ich keine Steuerelemente im Dialogfeld habe. Sobald ich auch nur ein Steuerelement habe, funktiont das alles nicht.
Dies kann ich mir nur erklären, dass das Dialogfeld als ein eigenes Objekt angesehen wird und wenn ich Steuerelemente( die ich zurn weiteren Programmierung brauche ) zufüge er diese als neue Objekte ansieht und vielleicht dann beim tastendruck in einem falschen Objekt drin ist?! Oder verwende ich den code generell in der falscen Funktion ?Jetzt brauch ich die Bedienelemente weil ich gerne möchte das der user in einem Eingabefeld selbst die Taste für ein zu startendes programm festlegt.
vieloen Dank für eure Hilfe !
-
Unter Windows hat zu einer Zeit genau ein Fenster den Eingabefocus. Dieses Fenster erhält die Tastaturbotschaften ( WM_KEYDOWN, WM_KEYUP ... )
Wenn Du einen Dialog ohne Controls hast so ist dies beim Aufruf das Element mit Eingabefokus.
Sobald du dem Dialog jedoch ein Control hinzufügst, gibt der Dialog den Fokus an das erste Control ab ( welches, liegt an der Tab-Reihenfolge ). Dadurch erhält das Control und nicht mehr der Dialog die Tastaturbotschaften.Für die Lösung gäbe es mehrere Ansätze:
1. Subclassen der Controls und die Tastaturbotschaften hier abfangen.
2. MFC: Überladen der CWnd::PreTranslateMessage - Funktion (gibts auch eine Technical Note TN021 glaube ich)
3. Wenns auch dann sein soll, wenn deine Anwendung nicht aktiv ist könnte man einen Tastatur-Hook einsetzen ( SetWindowsHookEx )
Ich würde das mit Variante 2 machen.
-
Danke, ich muss da mal schaun weil ich noch neu mit vc++ bin ;/
Hab mir da gerade noch etwas anderes überlöegt, geht das auch ?
Wenn ich 2 Steuerelemente einfüge ein Eingabefeld und einen Button, der Button das letzte Element welches "bedient" wird. Ich die Funktion onkeydown in der Funktion des Buttons aufrufe ? Oder hat der Button wenn er als letztes benutzt wird nicht den Fokus ?@ tvdog, haste zu der zweiten Methode vllt mal nen kleines Beispiel ?
-
für die 2. Methode: ( ohne Gewähr, ich schreibs mal so hin ):
BOOL CBlaablaDlg::PreTranslateMessage( MSG* pMsg ) { if ( pMsg->message == WM_KEYDOWN && (GetAsyncKeyState(VK_CONTROL)&0x8000 == 0) ) { switch( pMsg->wParam ) { case VK_A: ShellExecute( NULL, "open", "calc.exe", NULL, NULL, SW_SHOWNORMAL ); return TRUE; } } return CDialog::PreTranslateMessage( pMsg ); }
Mit dem GetAsyncKeyState kannst du noch zusätzlich prüfen ob eine Strg / Shift, ... Taste gedrückt wurde falls gewünscht. Ansonsten lass es halt weg.
Wenn die Anwendungen nur dann ausgeführt werden dürfen, falls der Fokus auf bestimmten Steuerelementen ist, dann kannst du auch noch zusätzlich den hwnd - Member in pMsg auswerten. Am besten, du schaust dir mal PreTranslateMessage an.
-
(GetAsyncKeyState(VK_CONTROL)&0x8000 == 0)
Tipp:
Mit solchen Dingen wie "& 0x8000" nach dem "most significant bit" zu fragen ist unportabel. Später einmal das Ganze unter nem 64bit OS kompiliert, und man darf sich auf Debuggen freuen
Lieber < oder > benutzen. Weniger performant, aber portabler.mfg
-
danke aber wie sieht das denn mit meinem Vorschlag aus, Onkeydown() in der Funktion vom Button aufzurufen weil Das Objekt welches zu letzt benutzt wurde doch dann den Fokus hat ?