Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Problem bei der Verarbeitung von Systemnachrichten (https://www.delphipraxis.net/29070-problem-bei-der-verarbeitung-von-systemnachrichten.html)

Johannes Maier 3. Sep 2004 14:11


Problem bei der Verarbeitung von Systemnachrichten
 
Hallo,

Mit einem Hilfsprogramm sende ich meinem Hauptprogramm die message WM_QUIT. Diese möchte ich nun abfangen, und als Reaktion ShowMessage('text') aufrufen. Das Problem:
Wenn ich im Hilfsprogramm die Nachricht mit SendMessage() verschicke, kann ich sie im Hauptprogramm mit der WndProc-Prozedur abfangen. Wenn ich WM_QUIT allerdings mittels PostMessage versende, dann schließt sich das Programm sofort, dabei möchte ich, dass nur meine Nachricht erscheint.
Ich habe es im Fall PostMessage bisher so versucht:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := ApplicationEvents1Message;
end;

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
  if Msg.Message = WM_QUIT then begin
    Handled := True;
    ShowMessage('WM_QUIT ist eingegangen');
  end;
end;
Damit sollte es doch eigentlich funktionieren... Jedenfalls wird nie die MessageBox angezeigt, und ich weiß nicht wieso ...
Achja, WndProc hab ich auch probiert, aber hab erfahren, dass die mit PostMessage gesendete Nachrichten nicht erhält.
Und noch was: WM_CLOSE oder WM_DESTROY lassen sich damit abfangen und anzeigen, aber WM_QUIT geht immer sofort durch und beendet das Programm OHNE vorher meine MessageBox anzuzeigen.
Ich hoffe mal hier weiß einer, wie man das Problem lösen kann :?

Dax 3. Sep 2004 14:20

Re: Problem bei der Verarbeitung von Systemnachrichten
 
Zitat:

Zitat von MSDN
The WM_QUIT message indicates a request to terminate an application and is generated when the application calls the PostQuitMessage function. It causes the GetMessage function to return zero.

WM_QUIT
nExitCode = (int) wParam; // exit code


Parameters

nExitCode

Value of wParam. Specifies the exit code given in the PostQuitMessage function.



Return Values

This message does not have a return value, because it causes the message loop to terminate before the message is sent to the application's window procedure.

See Also

GetMessage, PostQuitMessage

Laut dieser beschreibung Terminiert die Message das Programm, ohne direkt eine Message and die App zu senden.

Johannes Maier 3. Sep 2004 14:30

Re: Problem bei der Verarbeitung von Systemnachrichten
 
Gibt es dann überhaupt eine Möglichkeit, sein Programm so umzuschreiben, dass es diese Nachricht erhält, bevor es terminiert wird? Ich kenn mich da so genau jetzt nicht aus, aber dass man was mit PostQuitMessage anstellen kann, oder mit GetMessage, so dass auch bei WM_QUIT nicht 0 zurückgegeben wird? Vll. diese Funktion in seinem Programm überschreiben, denn wie ich das verstanden hab, gehen da die Nachrichten ein, und alle außer WM_QUIT gehen nicht sofort durch, nur WM_QUIT wird 0 zurckgeliefert und sofort abgebrochen.
Wenn einer diese Idee (falls es überhaupt geht) in einem kleinen Codebeispiel darstellen würde, wäre ich sehr dankbar ;)

Dax 3. Sep 2004 14:33

Re: Problem bei der Verarbeitung von Systemnachrichten
 
Wie es im MSDN stand:

Dein programm wird terminiert, BEVOR es die Message erhält. Du müsstest dein OS umschreiben, damit es vorher die Message noch bekommt.

Johannes Maier 3. Sep 2004 15:04

Re: Problem bei der Verarbeitung von Systemnachrichten
 
Hmm wenn ich Linus Torvalds Programmierskills hätte würde ich das jetzt tun ;)
Also gibt es keine Möglichkeit, diese GetMessage-Funktion so zu ändern (nur für mein Programm, nicht systemweit), dass sie bei WM_QUIT nicht NULL ausgibt? Denn es heißt zwar, das Programm wird terminiert bevor es die message erhält, jedoch irgendwo muss diese ja ankommen, und zwar in dieser Message-Schleife ... Hmm aber so wichtig ist es nun auch wieder nicht ;) Dann mach ich es lieber anders, mit WM_DESTROY oder so ... So ein Problem wie das mit WM_QUIT reizt mich einfach delphitechnisch, allein durch die Beschäftigung in diesem Zusammenhang mit den Systemnachrichten hab ich viel über WinAPI, WndProc und so gelernt ;)

Dax 3. Sep 2004 15:06

Re: Problem bei der Verarbeitung von Systemnachrichten
 
Nein, leider nicht.
Du musst wohl was anderes als WM_QUIT senden, vielleicht, .. WM_PRINT?

Johannes Maier 3. Sep 2004 15:29

Re: Problem bei der Verarbeitung von Systemnachrichten
 
Mich hatte einfach Nachrichtenbehandlung, die message-Direktive usw. interessiert, dann hab ich im Delphi-Forum ein paar Beiträge dazu gelesen, und dann was pber SendMessage, PostMessage und WndProc ;)
Als ich dann rausgefunden hab, wie man SendMessage-Nachrichten behandelt, und dass man mit der gleichen Methode keine PostMessage-Nachrichten behandeln kann, hab ich nach einer Lösung für dieses problem gesucht usw.
Dann hab ich herausgefunden, dass dies bei WM_QUIT nicht funktioniert und wollte schauen, ob es dafür auch eine solche Lösung gibt, dass die Message anders behandelt wird, aber dem war wohl nicht so ... ;)

Danke dann mal :-D

Luckie 3. Sep 2004 16:39

Re: Problem bei der Verarbeitung von Systemnachrichten
 
Noch mal im Klartext: MSDN-Library durchsuchenWM_QUIT beendet die MessageLoop deines Fensters>
Delphi-Quellcode:
while GetMessage(msg,0,0,0) do
  begin
    TranslateMessage(msg);
    DispatchMessage(msg);
  end;
Das heißt TranslateMessage bzw. in diesem Fall das wichtigere DispatchMessage wird nicht mehr aufgerufen und somit kann DispatchMessage die Nachricht nicht an die Zuständige Fensterprozedur weiterleiten. Du wirst also nie eine WM_QUIT zu sehen bekommen.

Wozu brauchst du denn das überhaupt?

Dax 3. Sep 2004 17:02

Re: Problem bei der Verarbeitung von Systemnachrichten
 
Zitat:

Zitat von Johannes Maier
Mich hatte einfach Nachrichtenbehandlung, die message-Direktive usw. interessiert, dann hab ich im Delphi-Forum ein paar Beiträge dazu gelesen, und dann was pber SendMessage, PostMessage und WndProc ;)


Golze 4. Sep 2004 09:45

Re: Problem bei der Verarbeitung von Systemnachrichten
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Johannes,
ich habe mal bei mir im Archiv nachgeschaut und ein kleines aber feines Testprogramm rausgebuddelt. Wenn du das Programm verstanden hast, versteht du auch die Hierarchie der Message-Verarbeitung durch die VCL. Das WM_QUIT-Ereingis wird innerhalb der VLC im Objekt TApplication einfach auf das Property Terminated umgesetzt :drunken: . Erhält dein Programm diese Nachricht, ist Application.Terminated immer True. Generell kannst du aber die Auswirkungen des Ereignisses nicht aufheben - also das Beenden des Programms. Du kannst es aber - siehe Beispielprogramm - abfangen und noch letzte arbeiten ganz in Ruhe durchführen lassen. Das Testprogramm ist als Anhang ebenfalls dabei.
Grüße Kay
:gruebel: :P :angel:
Delphi-Quellcode:
unit Main;
interface
uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

const
  MyMesage = {WM_QUIT} WM_USER; //test also WM_USER message to see the full functionality

type
  TMainForm = class(TForm)
    SendBtn: TButton;
    PostBtn: TButton;
    procedure SendBtnClick(Sender: TObject);
    procedure PostBtnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    OldWndProc: Pointer;
    WndProcPtr: Pointer;
    procedure HandleAppIdleState(Sender: TObject; var Done: Boolean);
    procedure WndMethod(var Msg: TMessage);
    procedure HandleAppMessage(var Msg: TMsg; var Handled: Boolean);
    procedure AppDeactivate(Sender: TObject);
  end;

var
  MainForm: TMainForm;

implementation
{$R *.DFM}

var
  WProc: Pointer;

function NewWndProc(Handle: hWnd; Msg, wParam, lParam: Longint): Longint; stdcall;
{Description:
  This is a Win32 API-level window procedure. It handles the messages
  received by the Application window.
}
begin
  {If it's our user-defined message, then alert the user.
  }
  if Msg = MyMesage then
    MessageBox(0, PChar(Format('Message seen by NewWndProc! Value is: %u', [Msg])),
                  PChar('Check WM_QUIT Message'), MB_OK);
  {Pass message on to old window procedure
  }
  Result := CallWindowProc(WProc, Handle, Msg, wParam, lParam);
end;

procedure TMainForm.HandleAppMessage(var Msg: TMsg; var Handled: Boolean);
{Description:
 OnMessage handler for Application object.
}
begin
  {if it's the user-defined message, then alert the user.
  }
  if Msg.Message = MyMesage then
    MessageBox(0, PChar(Format('Message seen by OnMessage! Value is: %u', [Msg.Message])),
                  PChar('Check WM_QUIT Message'), MB_OK);
end;

procedure TMainForm.WndMethod(var Msg: TMessage);
begin
  {if it's the user-defined message, then alert the user.
  }
  if Msg.Msg = MyMesage then
    MessageBox(0, PChar(Format('Message seen by WndMethod! Value is: %u', [Msg.Msg])),
                  PChar('Check WM_QUIT Message'), MB_OK);
  {Pass message on to old window procedure.
  }
  with Msg do
    Result := CallWindowProc(OldWndProc, Application.Handle, Msg, wParam, lParam);
end;

procedure TMainForm.HandleAppIdleState(Sender: TObject; var Done: Boolean);
var Msg: TMsg;
begin
  {Get the message from the queue.
  }
  if PeekMessage(Msg, 0, 0, 0, PM_NoREMOVE) then
  begin
    if Msg.Message = MyMesage then
      MessageBox(0, PChar(Format('Message seen by HandleAppIdleState! Value is: %u', [Msg.Message])),
                    PChar('Check WM_QUIT Message'), MB_OK);
  end;
end;

procedure TMainForm.AppDeactivate(Sender: TObject);
begin
  if Application.Terminated then
    MessageBox(0, PChar('Message seen by AppDeactivate! WM_QUIT'),
                  PChar('Check WM_QUIT Message'), MB_OK);
end;

procedure TMainForm.SendBtnClick(Sender: TObject);
begin
  {The SendMessage function sends the specified message to a window or windows. The
   function calls the window procedure for the specified window and does not return
   until the window procedure has processed the message. The PostMessage function, in
   contrast, posts a message to a thread's message queue and returns immediately.
  }
  SendMessage(Application.Handle, MyMesage {WM_QUIT}, 0, 0);
end;

procedure TMainForm.PostBtnClick(Sender: TObject);
begin
  {The PostMessage function places (posts) a message in the message queue associated
   with the thread that created the specified window and then returns without waiting
   for the thread to process the message.
  }
  PostMessage(Application.Handle, MyMesage {WM_QUIT}, 0, 0);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Application.OnDeactivate := AppDeactivate;
  Application.OnIdle := HandleAppIdleState;
  Application.OnMessage := HandleAppMessage;    // set OnMessage handler
  WndProcPtr := MakeObjectInstance(WndMethod);  // make window proc
  {Set window procedure of application window.
  }
  OldWndProc := Pointer(SetWindowLong(Application.Handle, GWL_WNDPROC,
                                      Integer(WndProcPtr)));
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  if Application.Terminated then
    MessageBox(0, PChar('Message seen by FormDestroy! WM_QUIT'),
                  PChar('Check WM_QUIT Message'), MB_OK);
  {Restore old window procedure for Application window
  }
  SetWindowLong(Application.Handle, GWL_WNDPROC, Longint(OldWndProc));
  {Free our user-created window procedure
  }
  FreeObjectInstance(WndProcPtr);
end;

initialization
  {Set window procedure of Application window.
  }
  WProc := Pointer(SetWindowLong(Application.Handle, GWL_WNDPROC,
                                 Integer(@NewWndProc)));
end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:18 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz