TForm und WM_SYSCOMMAND
-
Guten morgen miteinander...
Es gibt mal wieder was, was ich nicht verstehe:
Ich hab ein TForm und fang da u.a. auch WM_SYSCOMMAND Messages ab. Kein Problem, nur geht das nicht, wenn das Fenster z.B. unsichtbar ist. Soll es aber. Also Hab ich mir gedacht, ich benutze AllocateHWnd und erzeuge mir ein Fenster welches diese Msg empfangen kann. Dies habe ich erst direkt in meiner TForm versucht, gab aber wilde Exceptions (ungültige Fensterkalsse etc.
) also hab ich ne eigene Klasse geschrieben (testhalber
)
class TTest { private: HWND hWnd; void __fastcall WndProc(Messages::TMessage &Message); public: __fastcall TTest() {hWnd = AllocateHWnd(WndProc);}; __fastcall ~TTest() {DeallocateHWnd(hWnd);}; }; //.... void __fastcall TTest::WndProc(Messages::TMessage &Message) { if(Message.Msg == WM_SYSCOMMAND) { //mach was } else Message.Result = DefWindowProc(hWnd, Message.Msg, Message.WParam, Message.LParam); } // also bis hier frei nach der hilfe :) //.... und in TForm Test = new TTest();
Allerdings ist der Effekt derselbe, das neue Fenster krieg nur Msg, wenn das andere irgendwie sichtbar ist bzw. anderweitig (z.b. aus der Tray) Messages bekommt. Irgendwie komm ich nicht weiter.
Vielleicht hab ich ja auch nur den Sinn von AllocateHWnd falsch verstanden
Wäre schon, wenn mir jemand nen Tip geben könnte..
-
original erstellt von Postman
**
Also Hab ich mir gedacht, ich benutze AllocateHWnd und erzeuge mir ein Fenster welches diese Msg empfangen kann**warum ? ist doch gar nicht notwendig. Leite deine klasse doch von TForm ab und schon hast du ein Fenster mit allem drum und dran. Warum das Rad neu erfinden...
[ Dieser Beitrag wurde am 05.06.2003 um 08:44 Uhr von AndreasW editiert. ]
-
Hm. Ich weiß nicht, ob ich dich da jetzt ganz richtig verstehe: Ich leite meine "Ttest" von TForm ab? Ich könnte mir gut vorstellen, das ich dann wieder vor dem selben Problem stehe: Fenster Minimiert/versteckt --> kein WM_SYSCOMMAND kommt für mich verwertbar an. Denn mein MainForm existiert ja immer noch (versteckt) und da gings ja eben nicht.
Aber danke, bin in Bälde wieder an nem Rechner mit Builder und werd das checken..
-
Habs grad getestet:
class TTest : public TForm { private: HWND hWnd; void __fastcall WndProc(Messages::TMessage &Message); public: __fastcall TTest(TComponent* Owner); __fastcall ~TTest() {DeallocateHWnd(hWnd);}; }; //... __fastcall TTest::TTest(TComponent* Owner) : TForm(Owner) { hWnd = AllocateHWnd(WndProc); }
bringt beim (tform-)konstruktor beim TTest eine Exception "Resource TTest not found". Seh ich u.U. sogar ein
Füge ich TTest als Formular über die IDE hinzu, ist es wieder der selbe Effekt, den ich schon mehrfach erwähnt habe (kein WM_SYSCOMMAND).
-
hallo,
ich weiß zwar nicht genau warum du das so gemacht hast wie du es gemacht hast, aber wenn ich wmsyscom abfangen will, fange ich die komplette botschaft ab:
class MyTest: public TForm { ... protected: void __fastcall WMSysCom(TWMSysCommand& SysCom); //Methode für WM_SYSCOMMAND. public: VCL_MESSAGE_HANDLER(TForm) //Dieser Code ist nicht syntaxkorrekt. VCL_MESSAGE_MAP(WMSysCom, TWMSysCommand, WM_SYSCOMMAND) END_VCL_MESSAGE }; void __fastcall MyTest::WMSysCom(TWMSysCommand& SysCom) { switch (SysCom.Cmd { case SC_CLOSE: this->Close(); break; default: TForm::Dispatch(&SysCom); //Für Standardbehandlung. } }
auf diese art werden all WMSysCommand botschaften direkt abgefangen, egal ob fenster minimiert, maximiert oder sonst was. allerdings hock ich an nem pc ohne compiler, deshalt ist vor allem das message-makro bestimmt nicht hasenrein, aber das wirst du schon in korrekter syntax hinbekommen, im cbuilder kannst du dir das ja per assi erstellen lassen. wenn dus nicht hinbekommst, schreib einfach nochmal, dann hilft die entweder einer von hier, oder ich wenn ich daheim bin.
mfg
murph
-
Erstmal danke. du wirsts kaum glauben. In dem guten glauben, das das geht, hatte ich es auch so gemacht (denn auf die art und weise handle ich am liebsten msgs), hier ein Stück von meinem "Originalcode" (nur das wichtigste) bevor ich auf das Problem gestoßen bin:
class TfrmMain : public TForm { public: void __fastcall WMSysCommand(TMessage &Msg); BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_SYSCOMMAND, TMessage, WMSysCommand) END_MESSAGE_MAP(TForm); //.... void __fastcall TfrmMain::WMSysCommand(TMessage &Msg) { switch(Msg.WParam) { //bla } TForm::Dispatch(&Msg); }
Und dann schaute ich ganz dumm, denn, wie gesagt, Fenster nicht sichtbar --> keine Msg... Ich hatte erst gedacht, es liegt daran, das ich noch andere Msg handle, aber ich hab das ganze in nem "nackten" Projekt getestet und ist dasselbe.
Bin jetzt schon den halben Tag am testen und kurz vorm durchdrehn
Auch umbiegen von Application->OnMessage bringt nix..
-
hallo,
was genau willst du denn machen, was soll geschehen, wenn das fenster minimiert ist?
mfg
murph
-
Verschiedenes.
u.a. den screensaver unterdrücken (dafür WM_SYSCOMMAND)
Mein Gedanke war halt AllocateHWnd zu nehmen, damit damit können sich Non-visual Controls "virtuelle Fenster" aloozieren, um Messages abzufangen....
-
hallo,
moment mal, die wm_syscommand-botschaften beziehen sich ja auf die systemelemente des fensters, also auf die drei buttons rechts oben, und auf das menü links das bei einem rechtsklick auf das icon aufgeht.
wenn jetzt dein programm inaktiv in der statusleiste liegt, und angenommen der screensaver irgendwann angeht, das system also inaktiv ist, mußt du andere botschaften abfangen. es gibt da z. b. WM_POWERBROADCAST
schau dich in der hilfe und dem sdk mal danach um, da findet sich was, mit sicherheit...mfg
m
-
WM_POWERBROADCAST ist es leider auch nicht
Ich befürchte, da muß ich mich wohl tiefer in die API eingraben. Vielleicht kann man ja mit Hooks was anfangen, ich hab allerdings noch kein Plan, wie.
Trotzdem vielen Dank..