Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CTRL, SHIFT, ALT und WM_SYSKEYDOWN / WM_KEYDOWN

164 views
Skip to first unread message

Martin Rupprecht

unread,
Jun 5, 2003, 7:52:54 AM6/5/03
to
Hallo,

ist wahrscheinlich 'ne totale Anfängerfrage aber ich krieg's nicht raus:

In einem mit BCB 4 erstellten Programm zeigt mein Formular folgendes Verhalten:
Wenn ich versuche, in der Funktion MyWindowProc die Tasten CTRL und SHIFT
unter Verwendung von WM_KEYDOWN / KEYUP abzufragen, ist alles in Ordnung.
Im Gegensatz dazu tritt beim Abfragen der Taste ALT mit WM_SYSKEYDOWN/SYSKEYUP
nur beim ersten Drücken ein WM_SYSKEYDOWN auf, beim zweitenmal nicht mehr. Erst
wenn ich ALT zum drittenmal drücke tritt wieder ein WM_SYSKEYDOWN auf.
Außerdem kann ich die SHIFT und CTRL Tasten nicht mehr abfragen wenn ich
vorher ALT gedrückt habe.

Hier die Funktion:

void __fastcall TForm1::MyWindowProc(Messages::TMessage &Message)
{
if(Message.Msg == WM_KEYDOWN)
{
if(Message.WParam == VK_ESCAPE)
Panel1->Caption = "ESCAPE down";
else if(Message.WParam == VK_CONTROL)
Panel1->Caption = "CTRL down";
else if(Message.WParam == VK_SHIFT)
Panel1->Caption = "SHIFT down";

Panel2->Caption = "WM_KEYDOWN " + IntToStr(Message.Msg);
}
else if(Message.Msg == WM_KEYUP)
{
if(Message.WParam == VK_ESCAPE)
Panel1->Caption = "ESCAPE up";
else if(Message.WParam == VK_CONTROL)
Panel1->Caption = "CTRL up";
else if(Message.WParam == VK_SHIFT)
Panel1->Caption = "SHIFT up";

Panel2->Caption = "WM_KEYUP " + IntToStr(Message.Msg);
}
else if(Message.Msg == WM_SYSKEYDOWN)
{
if(Message.WParam == VK_MENU)
Panel1->Caption = "ALT down";

Panel2->Caption = "WM_SYSKEYDOWN " + IntToStr(Message.Msg);
}
else if(Message.Msg == WM_SYSKEYUP)
{
if(Message.WParam == VK_MENU)
Panel1->Caption = "ALT up";

Panel2->Caption = "WM_SYSKEYUP " + IntToStr(Message.Msg);
}

OldWindowProc(Message);
}

Wenn mir jemand sagen könnte wie ich mit der ALT Taste umgehen muss (liegt's
vielleicht am C Builder?) wäre mir echt geholfen.

Vielen Dank im Voraus

Martin

Chuck

unread,
Jun 5, 2003, 9:29:04 AM6/5/03
to
Hängt wohl damit zusammen, das bei einmaligen drücken der Alt Taste das Menü
hervorgehoben wird und somit das Menü alle Events erhält, bis wieder Alt
gedrückt wird...

Hmm versuch einfach mal den alt event nicht weiterzugeben..

Gruß Chucky


"Martin Rupprecht" <mrupp...@softec-nue.de> schrieb im Newsbeitrag
news:c00f902.03060...@posting.google.com...

Gunnar Roth

unread,
Jun 6, 2003, 5:56:33 AM6/6/03
to

"Chuck" <chuc...@gmx.de> schrieb im Newsbeitrag
news:bbngi6$22v6$1...@gwdu112.gwdg.de...

> Hängt wohl damit zusammen, das bei einmaligen drücken der Alt Taste das
Menü
> hervorgehoben wird und somit das Menü alle Events erhält, bis wieder Alt
> gedrückt wird...

Ja das kann gut so sein, wenn das Fenster ein Menue hat.


>
> Hmm versuch einfach mal den alt event nicht weiterzugeben..

Hmm naja... ;-)

Die Lösung für solche Sachen ( sprich man will alle Key-Messages Tasten
jederzeit bekommen)
liegt darin in seine Messageloop eine PreTranslateMessage Funktionsaufruf
einzubauen bevor man DispatchMessage aufruft,
so wie das z.b. die MFC macht. PreTranslateMessage ist eine eigene Funktion
die man schreibt. In dieser Funktion kann man sich alle msgs anschauen die
durch die MessageQueue kommen. Und die Tasten messages kommen alle durch.

Hoffe geholfen zu haben,
gruss gunnar


Chuck

unread,
Jun 6, 2003, 8:57:20 AM6/6/03
to
Hmm haja so gehts auch.. er könnte auch ne Hook installieren ;)


"Gunnar Roth" <gunna...@gmx.de> schrieb im Newsbeitrag
news:bbpogh$qpi$03$1...@news.t-online.com...

Gunnar Roth

unread,
Jun 6, 2003, 12:49:46 PM6/6/03
to

"Chuck" <chuc...@gmx.de> schrieb im Newsbeitrag
news:bbq32l$ict$1...@gwdu112.gwdg.de...

> Hmm haja so gehts auch.. er könnte auch ne Hook installieren ;)
Um einen solchen Hook zu nutzen muss man den aber in eine DLL tun.
Nen Hook nimmt man eigentlich nur wenn man die Nachrichten von anderen
Programmen hooken will.


gruss Gunnar


Chuck

unread,
Jun 10, 2003, 2:49:56 AM6/10/03
to
hm net unbedingt.. du kannst eine hook auch nur für dein Programm
platzieren.., die ist dann eine static oder globale Funktion in deinem Code.
du erhältst dann nur Messages, die Dein Programm betreffen.

MSDN schlägt beide Möglichkeiten vor.. entweder über PreTranslateMessage
oder über hook..

je nachdem ob man die Klassen (Steuerelemente) überschreiben will oder
nicht..

ist, denke ich, geschmackssache und abhängig, von der bereits bestehenden
implementierung


"Gunnar Roth" <gunna...@gmx.de> schrieb im Newsbeitrag

news:bbqgna$6f9$01$1...@news.t-online.com...

Martin Rupprecht

unread,
Jun 10, 2003, 4:04:35 AM6/10/03
to
Hallo Chuck, hallo Gunnar,

danke für eure Tipps. Das mit der Messageloop ist mir nicht ganz klar.
Ich dachte eigentlich dass alle Messages durch die WndProc des
Formulars gehen (tut die Message für Alt ja auch aber scheint's leider
nicht immer). Laut BCB4 Hilfe übergibt WndProc die Messages an eine
Dispatch Methode. Wenn ich also wie in meinem Beispiel meine eigene
Methode aufrufe und zum Schluss die originale WndProc müsste der
zeitliche Ablauf doch so sein wie Gunnar mit PreTranslateMessage
meint, oder?
Mit der MFC bin ich leider nicht vertraut. Was muss ich den machen um
wirklich alle Messages für eine Anwendung zu bekommen? Gibt's
vielleicht irgendwo Beispiele?

Gruß

Martin

Chuck

unread,
Jun 10, 2003, 5:20:22 AM6/10/03
to
hmm wenn ich gunnar richtig verstanden habe , meinte er, das du die
MessageLoop ein jedes deiner Steuerelemente in deinem Dialog verändern
mußt, von denen due Nachrichten empfangen willst...

an der messageloop deines Dialogs mußt du nichts verändern...

oder gunnar? ;)

"Martin Rupprecht" <mrupp...@softec-nue.de> schrieb im Newsbeitrag

news:c00f902.03061...@posting.google.com...

Gunnar Roth

unread,
Jun 10, 2003, 8:09:25 AM6/10/03
to

"Chuck" <chuc...@gmx.de> schrieb im Newsbeitrag
news:bc47rr$2q91$1...@gwdu112.gwdg.de...

> hmm wenn ich gunnar richtig verstanden habe , meinte er, das du die
> MessageLoop ein jedes deiner Steuerelemente in deinem Dialog verändern
> mußt, von denen due Nachrichten empfangen willst...
>
> an der messageloop deines Dialogs mußt du nichts verändern...
>
> oder gunnar? ;)

Also nochmal MessageLoop und WndProc sind nicht das Gleiche!
WndProc ist die Fensterprozedur, die die Nachrichten bearbeitet, die an das
Fenster
geschickt werden, daher bestimmt sie das verhalten. es gibt für button, etc.
wndproc die windows bereitstellt
und die dafür sorgen, das sie sich wie ein button etc. verhalten.

die MessageLoop ist ein Programm konstrukt die meist so aussieht:

// Spin in message loop until shutdown
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
::TranslateMessage(&msg); // The TranslateMessage function translates
virtual-key messages into character messages. The character messages are
posted to the calling
//thread's message queue, to
be read the next time the thread calls the GetMessage or PeekMessage
function.
::DispatchMessage(&msg); //The DispatchMessage function dispatches a
message to a window procedure. It is typically used to dispatch a message
retrieved by the GetMessage function.
}

Bei der MFC sieht man die Messageloop nicht in seinem code, weil sie in
CWinApp::Run drinsteckt.
In reinen win32api programmen ohne ein Framework muss man sie selbst
schreiben.
Altenativ kann man eine PreTranslateMessage Funktion zufügen.
// Spin in message loop until shutdown
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
if (!PreTranslateMessage(&msg))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}


Die PreTranslateMessage implementiert mann selber, durch sie kommen alle
nachrichten die durch die messageloop
gehen. Aber achtung nicht alle nachrichten gehen durch die messageloop.
nachrichten die von dem thread mit SendMessage geschickt werden zu dem das
Fenster gehört,
gehen direkt in die windowproc, hier hilft nur ein hook. die key messages
vom system gehen aber auf alle fälle durch die MessageLoop.

Die Messageloop holt mit GetMessage die Nachrichten aus der MessageQueue,
diese Queue wird von windows für jeden Thread eingerichtet, der ein Fenster
erzeugt.

Modale Dialog, also solche die mit DialogBoxParam() oder MessageBox()
erzeugt werden, haben eine eigene Messageloop(diese steckt im windows code
dieser funktionen), da DialogBoxParam() oder MessageBox() erst nach
schliessen des dialogs zurückkehren muss das auch so sein. Daher wird für
diesen zeitraum auf kein PreTranslateMessage aufgerufen.


Hoffe das klärt das auf ;-)

Gruss Gunnar


Martin Rupprecht

unread,
Jun 18, 2003, 4:45:58 AM6/18/03
to
Hallo,

ich hab's jetz: BCB stellt einen Application->OnMessage EventHandler
zur Verfügung,
durch den sämtliche Messages gehen. Mit dem Flag Handled kann man
bestimmen ob die
Message nach einer Bearbeitung dispatcht werden soll. Nochmal vielen
Dank für eure Hilfe.

Martin

0 new messages