Announcement

Collapse
No announcement yet.

Komponente empfängt Message nicht

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Komponente empfängt Message nicht

    Hallo,
    Hier was für Message-Spazialisten unter NT:<p>
    Ich möchte eine von TPanel abgeleitete Komponente bauen,
    die auf eine selbstgebaute Message reagiert.<br>
    Diese Message wird in einer globale Unit im Initialisierungsteil erzeugt:<p>
    <pre>
    implementation
    uses windows;
    const
    szPrivateMsgString='irgendwaseindeutiges';
    initialization
    GlobalerMessagewert := RegisterWindowMessage( szPrivateMsgString);
    end.
    </pre>

    In der Komponente selbst verwende ich diesen Wert in der überschriebenen WndProc-Procedure:<p>
    <pre>
    procedure TMsgPanelPTV.WndProc( var Message: TMessage);//override !!
    begin
    if (Message.Msg = GlobalerMessagewert) then
    begin
    Caption := DateTimeToStr(Now);
    end;
    inherited WndProc(Message);
    end;
    </pre>

    Das Programm dass diese Message 'lostritt' enthält natürlich die Unit mit dem 'GlobalerMessagewert' und arbeitet so:<p>
    <pre>
    dwRecipient := BSM_ALLCOMPONENTS;//BSM_APPLICATIONS;
    BroadcastSystemMessage(BSF_POSTMESSAGE, @dwRecipient,
    GlobalerMessagewert, wMsgValue, 0);
    </pre>

    Eigentlich sollte sich beim Auftreten der Message die Caption des abgeleiteten Panels ändern.<br>
    Praktisch tut sie das aber nicht.<br>
    Ein <b>Formular</b> dessen WndProc-Routine ich genauso überschrieben habe, reagiert richtig.<br>
    Warum das Eigenbau-Panel nicht?<p>
    Stimmt der dwRecipient - wert nicht?<br>
    Der Wert NULL, der sich ganz nett anhört ('If this parameter is NULL, the function broadcasts to all components', laut Windows-Hilfe), führt zur Fehlermeldung, dass ein Konvertierungsfehler aufgetreten ist.<br>
    Wer kann mir helfen?<br>
    Gruß an alle, Alex

  • #2
    Hi

    BroadcastSystemMessage() arbeitet in Deinem Fall mit <br>PostMessage(hwnd_Broadcast, GlobalerMessageWert, wParam, lParam);<br>

    Aber, da Dein TPanel ein ungerordnetes Child Windows vom TForm Window ist empfängt es diese Message NICHT. Nut sogenannte TOP LEVEL Fenster erhalten diese Messages. TOP LEVEL sind all Windows die KEINE direkten Childs sind, also entweder kein ParentWindow haben oder ParentWindow = hWnd_Dsktop/GetDesktopWindow.

    Du solltest also im Aufrufenden Process gezielt das TPanel Windows suchen und ansprechen, z.B. SendNotifyMessage(), PostMessage() etc.

    Solche "Interprocess Fenster" Kommunikation ist aber nicht der beste Weg.

    Gruß Hage

    Comment


    • #3
      Hallo, Hagen,<br>
      Danke erstmal für die schnelle Antwort.<p>
      Hintergrund meines Programms ist, dass der Aufrufer gar nicht weiss, wie viele der Eigenbau-Panels es gibt, daher kann er deren Adresse auch nicht kennen.<p>
      Angenommen, das Hauptfenster meines Empfängerprogramms bekommt diese Message. Kann es diese Message auf irgendeine Weise wieder per Message an alle im Empfängerprogramm enthaltenen EigenbauPanel-Komponenten weitergeben?<p>
      <b>Beispiel: Senderprogramm schickt Message ==> Empfängerprogramm empfängt sie und 'sagt' dann allen EigenbauPanels (in allen Fenstern im Empfängerprojekt!) bescheid, dass sie rot werden sollen.</b><p>

      So wie unten möchte ich es eigentlich NICHT in jedem Fenster machen müssen, da ich unüberschaubar viele Fenster habe. Zu den EigenbauPanels können auch noch andere Komponenten hinzukommen (EigenbauCombobox,etc.) die auch alle auf die Message lauern sollen.<br>
      <pre>
      //hab's nicht compiliert, müsste aber so funktionieren:
      procedure Rotmacher(Compo:TComponent);
      var
      I: Integer;
      Temp: TComponent;
      begin
      for I := Compo.ComponentCount - 1 downto 0 do
      begin
      Temp := Compo.Components[I];
      if not ((Temp is TEigenbauPanel) //or (Temp is TEigenbaucombobox)
      then
      Temp.Color := clRed;
      Rotmacher(Temp);
      end;
      end;
      </pre>
      Das wollte ich eigentlich <b>nicht</b> in jedem Fenster aufrufen, u.a. weil die Routine um jede Komponente erweitert werden muss, die "rot" werden soll.<p>
      Ich wollte das <b>einmal</b> machen und dann später ggf. "Rotwerd"-Komponenten basteln, die dann immer selbst wissen, wonach sie lauschen müssen.<p>

      Geht das nicht, dass eine Komponentengruppe darauf lauert, dass eine Message die Runde macht und dann irgendwie darauf reagiert?<p>

      Gruß<br>
      Ale

      Comment


      • #4
        Hi

        Ja geht. Ich empfehle Dir folgendes. Setze auf Dein Formular ein TApplicationEvents und bei dieser Komponente das Event "OnMessage".<br>

        Da das Application.Handle ein TOP LEVEL Window ist (versteckt) empfängt es auch Deine Message. Diese wird dann weitergeleitet an ApplicationEvents1.OnMessage. <br>

        <pre>

        procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
        var
        M: TMessage;
        begin
        if Msg.message = wm_Null then
        begin
        M.Msg := Msg.Message;
        M.WParam := Msg.wParam;
        M.LParam := Msg.lParam;
        Self.Broadcast(M);
        end;
        end;

        </pre>

        Aber es geht auch "sauberer". Du hast Dein Panel als neue Komponente erstellt, richtig ?<br>

        <pre>

        interface <br>

        type
        TMyPanel = class(TPanel)
        private
        function WndHook(var Msg: TMessage): Boolean;
        public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        end;<br>

        var
        wm_MyMsg: Cardinal = 0;<br>

        function TMyPanel.WndHook(var Msg: TMessage): Boolean;
        begin
        Result := False;
        if Msg.Msg = wm_MyMsg then
        ... setze Caption etc.
        end;<br>

        constructor TmyPanel.Create(AOwner: TComponent);
        begin
        inherited Create(AOwner);
        Application.HookMainWindow(WndHook);
        end; <br>

        destructor TMyPanel.Destroy;
        begin
        Application.UnhookMainWindow(WndHook);
        inherited Destroy;
        end; <br>

        initialization
        wm_MyMsg := RegisterWindowMessage('MyWindowMesage');
        end.

        </pre>

        gruß Hage

        Comment


        • #5
          Super, vielen Dank! Der Hook war genau das, was ich gesucht hab !<br>
          Vielen Dank !<p>
          Gruß<br>
          Ale

          Comment

          Working...
          X