Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   WM_QUERYENDSESSION ohne Fenster (https://www.delphipraxis.net/171235-wm_queryendsession-ohne-fenster.html)

blablab 27. Okt 2012 16:27

WM_QUERYENDSESSION ohne Fenster
 
Hallo!

Ich habe ein Programm von der Art:
Delphi-Quellcode:
program

begin
   while True do
      ...
   end;
end.
Wie kann ich da Messages wie WM_QUERYENDSESSION abfangen? Bekomme ich die nur wenn ich ein Fenster habe? Oder reicht eventuell Application? Es muss nicht nonVCL sein, da ich Graphics benutze und somit das VCL sowieso schon mit drin habe.
Aber ich fände es jetzt irgendwie komisch ein leeres Fenster zu "designen" das sowieso niemals sichtbar wird...

Grüße
blablab

Sir Rufo 27. Okt 2012 16:48

AW: WM_QUERYENDSESSION ohne Fenster
 
Versuch dir mal folgende Frage zu beantworten: "Warum wählte Microsoft für sein Betriebssystem den Namen Windows?"

Danach ist deine Frage auch beantwortet :mrgreen:

haentschman 27. Okt 2012 17:50

AW: WM_QUERYENDSESSION ohne Fenster
 
Stichwort:
http://docwiki.embarcadero.com/Libra...s.AllocateHWnd 8-)

himitsu 27. Okt 2012 18:15

AW: WM_QUERYENDSESSION ohne Fenster
 
Zitat:

Zitat von haentschman (Beitrag 1188655)

Quasi ein MessageOnlyWindow verwenden. (unsichtbar und nur für den Nachrichtenempfang)

Und zusätzlich die MessageLoop nicht vergessen, denn ohne einen Code, welche die MessageQueue verarbeitet, bekommt das Fenster zwar die Message, aber keiner verarbeitet sie und sie leibt in der Queue stecken. :stupid:

blablab 15. Nov 2012 21:49

AW: WM_QUERYENDSESSION ohne Fenster
 
Ich hab folgendes Testprogramm, aber bekomme keine Messages:
Delphi-Quellcode:
program WinMsg;

uses
   Forms, Classes, Messages, SysUtils, Windows;

{$R *.res}

type
   TWndProcClass = class
   protected
      procedure WndProc(var msg: TMessage);
   public
      WinHandle: HWND;
   end;

procedure TWndProcClass.WndProc(var msg: TMessage);
begin
   MessageBox(0, pansichar(inttostr(msg.Msg)), 'msg', 0);
end;

var
   WndProcClass: TWndProcClass;
begin
   WndProcClass := TWndProcClass.Create;
   WndProcClass.WinHandle := AllocateHWnd(WndProcClass.WndProc);

   while True do begin
      Sleep(10);
   end;

   DeallocateHWnd(WndProcClass.WinHandle);
   WndProcClass.Free;
end.
Was mach ich falsch?

Edit:
Zitat:

Zitat von himitsu (Beitrag 1188659)
Und zusätzlich die MessageLoop nicht vergessen, denn ohne einen Code, welche die MessageQueue verarbeitet, bekommt das Fenster zwar die Message, aber keiner verarbeitet sie und sie leibt in der Queue stecken. :stupid:

Ich hab jetzt versucht eine MessageLoop zu improvisieren (hab sowas noch nie gemacht) und ich bekomme jetzt Messages. Aber wozu brauche ich denn jetzt das AllocateHWnd?

Edit2:
Ok, ich habs jetzt glaub ich so weit verstanden: Es gibt Messages für den Thread und andere für ein Window. Wenn ich also nur eine MessageLoop habe bekomme ich "Thread-Messages" aber keine "Window-Messages". Und scheinbar ist WM_QUERYENDSESSION eine solche "Window-Message".
Aber woher weiß ich denn welche Messages der Thread und welche nur ein Window bekommt? Gibt es da vielleicht eine Übersicht oder kennt jemand ein kleines Tutorial?

himitsu 15. Nov 2012 23:34

AW: WM_QUERYENDSESSION ohne Fenster
 
Alles, was per PostMessage/PostThreadMessage versendet wird, geht immer über die MessageQueue einen Threads. Alle Fenster und deren Message-Eingang sind mit einem Thread verknubblt ... genauer standardmäßig mit dem Thread, in dessen Kontext dieses "Fenster" (auch ein Edit oder Memo ist "nur" ein Fenster, weswegen Windows auch Windows heißt).

SendMessage geht zwar direkt an die Komponenten, es wird aber dennoch über diesen Thread synchronisiert.


Schöne Schleife, die nichts macht, außer zu schlafen und sich im Kreis drehen :zwinker: ... Wo werden da denn die Messages verarbeitet?
(in der VCL ist der Code quasi in Application.ProcessMessages versteckt und Dieses mußt du nun alles selber machen)
Schau dir mal die Delay-Prozedur in der CodeLib, bzw. im Forum an (da wird oftmals auch eine NonVCL-Version erwähnt) und nahezu sämtliche NonVCL-Tutorials sind auch geeignet, denn dort machen die fast immer alles selber.

Derartige Messages gehen oftmals über HWND_BROADCAST raus, was dann an alle Top-Level-Windows gesendet wird.
Bei Google suchenWM_QUERYENDSESSION wird aber, soweit ich das verstanden hab, nur an alle Top-Level-Windows in Desktop-Apps gesendet, also wohl nicht an Services und Co. :gruebel:


http://msdn.microsoft.com/en-us/libr.../ms644927.aspx
Abschnitt "Message Handling" ... Hier im Forum suchenGetMessage usw.

Bummi 15. Nov 2012 23:58

AW: WM_QUERYENDSESSION ohne Fenster
 
eine Minimalversion:

Delphi-Quellcode:
program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils,classes,messages,dialogs,windows;

type
   TWndProcClass = class
   protected
      procedure WndProc(var msg: TMessage);
   public
      WinHandle: HWND;
   end;


Function ProcessMessage(var Msg: TMsg): Boolean;

begin
  Result := False;
  if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
  begin
      PeekMessageA(Msg, 0, 0, 0, PM_REMOVE);
      Result := True;
      if Msg.Message <> WM_QUIT then
        begin
          TranslateMessage(Msg);
          DispatchMessageA(Msg);
    end;
  end;
end;


procedure ProcessMessages;
var
  Msg: TMsg;
begin
  while ProcessMessage(Msg) do {loop};
end;



procedure TWndProcClass.WndProc(var msg: TMessage);
begin
   writeln('MSG:' + inttostr(msg.Msg));
   msg.Result := -1;
end;

var
   WndProcClass: TWndProcClass;
begin
   WndProcClass := TWndProcClass.Create;
   WndProcClass.WinHandle := AllocateHWnd(WndProcClass.WndProc);
   writeln('HWND:' + InttoStr(WndProcClass.WinHandle));
   while True do begin
      Sleep(10);
      processMessages;
   end;

   DeallocateHWnd(WndProcClass.WinHandle);
   WndProcClass.Free;
end.

Aufrufbeispiel aus einer anderen Anwendung über das Handle, welches hier bei Writeln ausgegeben wurde

Delphi-Quellcode:
procedure TForm5.Button1Click(Sender: TObject);
begin
sendmessage(2689556,wm_close,0,0)
end;

blablab 16. Nov 2012 03:46

AW: WM_QUERYENDSESSION ohne Fenster
 
Vielen Dank!
Es funktioniert jetzt und ich hab es auch (so ziemlich:-D ) verstanden.

@Bummi:
Delphi-Quellcode:
  if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
   begin
       PeekMessageA(Msg, 0, 0, 0, PM_REMOVE);
warum nicht nur einmal:

Delphi-Quellcode:
  if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
?

himitsu 16. Nov 2012 08:35

AW: WM_QUERYENDSESSION ohne Fenster
 
Das Erste stammt quasi noch aus dem Code, wo man auch noch Unicode mit behandelt

Nja, wenn man sowieso nur ales selber macht, reicht es, wenn an das Genutzte Unterstützt.
In dem Fall würde ich einfach das A (xxxA) weglassen und alle API-Aufrufe über die dynamischen Typen laufen lassen. Außer man will prozessübergreifend, abeiten, dann entweder ANSI und Unicode verarbeiten oder auf eine Schnittstelle einigen, also ANSI (xxxA) oder Unicode (xxxW).

Bummi 16. Nov 2012 08:54

AW: WM_QUERYENDSESSION ohne Fenster
 
@blablab
weil ich müde war und beim reduzieren nicht aufgepasst habe...


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:14 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