Announcement

Collapse
No announcement yet.

Wie kann ich ein messagedlg automatisch schließen ?

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

  • Wie kann ich ein messagedlg automatisch schließen ?

    Hallo, allerseits!

    Mein Programm muss sich aus allen Tiefen nach Ablauf einer Zeitspanne automatisch schließen, wenn keine User-Aktionen mehr stattfinden. Dies ist für alle erzeugten eigenen Forms auch gelöst.

    Der Fall wird zwar selten eintreten (aber nichts ist unmöglich) : Ein User läßt das Programm in einer MsgBox stehen. Wie sende ich einen Click an die Box bzw schließe diese?

    Die User/Programm Aktion behandle ich mit Screen.OnActiveControlChange
    Das aktuelle TWinControl läge also vor. Weiss jemand Rat?

    für baldige Hilfe wäre ich sehr dankbar.
    gruss, bernhard

  • #2
    Hi,

    Und wie willst du bei Dialogen vorgehen, die eine Entscheidung des Nutzers verlangen ??

    Gruß
    Gesin

    Comment


    • #3
      Hi Gesine, schön gerade von Dir zu hören. Habe einiger Deiner Beiträge bereits mit Interesse gelesen. Zur Sache:

      Ich nehme grundsätzlich den worst-Case an.

      Tritt ein Major-Problem in der application auf, ist ja in 99.5% der Fälle sowieso nur der mbOK zu betätigen.

      In der Programmierung kann ich für den user entscheiden. Das Programm läuft auf einer Intensiv-Station im Krkhs. Insofern ist ohnehin im Programm definiert, was auf keinen Fall aus "Versehen" passieren darf.

      Insofern ist die automatische Entscheidung immer der Abbruch der begonnen Aktion. Das Problem liegt darin, dass die Form die msgbox nicht zerstört(logisch), sich aber dennoch verabschiedet. Beim Einloggen komme ich aber nicht wieder in den Zustand ante zurück. (Da fehlt's dann an Gehirn bei mir)

      Danke fürs kümmern

      Gruß, Bernhard :

      Comment


      • #4
        Hallo Bernhard,<br>
        <br>
        anbei ein kleines Muster wie Du vorgehen könntest.<br>
        Ich gehe dabei davon aus, dass Du die normale MessageDlg Komponente verwendest.<br>
        <br>
        Ich verwende auf dem Formular zwei TEdit Felder, zwei TButton und einen TTimer.<br>
        In Edit1 wird dabei der Name des zu schliessenden Fensters eingegeben, und in<br>
        Edit2 der Name des zu klickenden Buttons.<br>
        Bei den üblichen Dialog Fenstern kommt als Fensterklasse nur #32770 in Frage, und ist<br>
        deshalb fest verdrahtet.<br>
        Standardmässig ist das Timer.Interval auf 0 gesetzt.<br>
        Mit Button1 wird es dann auf 1000 gesetzt (Start) und mit Button2 auf 0 (Stop).<br>
        <br>
        (btw: Kann mir mal jemand verraten, wie ich hier bei Sourcen die Formatierung beibehalten<br>
        kann? So HTML fest bin ich nicht. Danke)<br>
        <br>
        unit MAIN;<br>
        <br>
        interface<br>
        <br>
        uses<br>
        Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br>
        ExtCtrls, StdCtrls;<br>
        <br>
        type<br>
        TForm1 = class(TForm)<br>
        Timer1: TTimer;<br>
        Edit1: TEdit;<br>
        Button1: TButton;<br>
        Button2: TButton;<br>
        Edit2: TEdit;<br>
        procedure Timer1Timer(Sender: TObject);<br>
        procedure Button1Click(Sender: TObject);<br>
        procedure Button2Click(Sender: TObject);<br>
        private<br>
        { Private-Deklarationen }<br>
        public<br>
        { Public-Deklarationen }<br>
        end;<br>
        <br>
        var<br>
        Form1: TForm1;<br>
        <br>
        implementation<br>
        <br>
        {$R *.DFM}<br>
        <br>
        procedure TForm1.Timer1Timer(Sender: TObject);<br>
        <br>
        Var<br>
        hMessageDlg : THandle;<br>
        hButton : THandle;<br>
        bButtonFound : Boolean;<br>
        sText : String;<br>
        <br>
        begin<br>
        Timer1.Interval := 0;<br>
        hMessageDlg := FindWindow(PChar('#32770'),PChar(Edit1.Text));<br>
        bButtonFound := False;<br>
        hButton := GetWindow(hMessageDlg,GW_CHILD);<br>
        While (hButton > 0)<br>
        and<br>
        (not bButtonFound) do<br>
        Begin<br>
        sText := StringOfChar(#00,Length(Edit2.Text)+1);<br>
        GetWindowText(hButton,PChar(sText),Length(sText)); <br>
        if Trim(sText) = Edit2.Text then<br>
        Begin<br>
        bButtonFound := True;<br>
        end<br>
        else<br>
        Begin<br>
        hButton := GetWindow(hButton,GW_HWNDNEXT);<br>
        end;<br>
        end;<br>
        if bButtonFound then<br>
        Begin<br>
        SendMessage(hButton,BM_CLICK,0,0);<br>
        end;<br>
        Timer1.Interval := 1000;<br>
        end;<br>
        <br>
        procedure TForm1.Button1Click(Sender: TObject);<br>
        begin<br>
        Timer1.Interval := 1000;<br>
        end;<br>
        <br>
        procedure TForm1.Button2Click(Sender: TObject);<br>
        begin<br>
        Timer1.Interval := 0;<br>
        end;<br>
        <br>
        end.<br>
        <br>
        <br>
        Ciao<br>
        Chris<br&gt

        Comment


        • #5
          Hi Bernhard,

          Vor Anzeige eines MessageDlg startest/initialisierst Du einen Timer, in dessen OnTimer-Event folgendes steht um den Defaultbutton zu betätigen:

          <pre>
          procedure TFormMain.Timer1Timer(Sender: TObject);
          begin
          // Default-Button betätigen
          keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN,0), 0, 0);
          keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN,0), KEYEVENTF_KEYUP, 0);
          end;
          </pre>

          Gruß
          Gesine

          P.S.:

          Um zu erkennen ob der Dialog vom Anwender verlassen wurde oder der Timer abgelaufen ist, könntest Du eine globale Variable IsTimeOut in der Event-Methode setzen

          Comment


          • #6
            Gesine und Christian !

            Vielen Dank

            Werde ein wenig experimentieren, und melde dann Ergebnis.
            glUserTimeOut verwende ich bereits, also kann auch ein glIsMsgTimeOut dazu kommen

            Herzlichen Dank

            gruß, bernhard :

            Comment


            • #7
              Gesine und Christian !

              Vielen Dank für Eure Tips

              Die Kombination von Euch Beiden ist genial! (sorry)

              Folgende Lösung funktioniert bestens

              function AutoCloseMessage:Boolean;

              var

              hMEssageDlg : THandle;

              sText : string;

              begin

              result := false;

              sText := StringOfChar(#00,255);

              hMessageDlg := GetActiveWindow;

              GetClassName(hMessageDlg, PChar(sText),Length(sText));

              if trim(sText) = 'TMessageForm' then begin

              keybd_event (VK_RETURN, MapVirtualKey(VK_RETURN,0),0,0);

              keybd_event (VK_RETURN, MapVirtualKey(VK_RETURN,0),KEYEVENTF_KEYUP,0);

              result := true;

              end;

              end;

              Nochmal vielen Dank für Eure Hilfe!

              gruß, bernhard :

              Comment


              • #8
                Hallo Bernhard,<br>
                <br>
                was mir noch eingefallen ist:<br>
                Bei der Methode die Du jetzt verwendest deckst Du 0,5% der Fälle<br>
                eventuell nicht ab. (Jedenfalls, so wie Du es beschrieben hast)<br>
                Ich meine die 0,5% , die nicht nur mit OK Button zu bestätigen<br>
                sind, denn wenn es mehr als ein Button ist besteht die Möglichkeit,<br>
                das der Button, den Du mit Return drückst, nicht der ursprüngliche<br>
                Default Button ist.<br>
                Vielleicht funktioniert es bei Dir ja, wenn Du ersatzweise VK_ESCAPE<br>
                nimmst. Bringt zumindest wenig Änderungsaufwand.<br>
                <br>
                Ciao<br>
                Chri

                Comment


                • #9
                  Hallo Chris,

                  vielen Dank für Dank den Hinweis.

                  Ciao,
                  Bernhar

                  Comment


                  • #10
                    <b>keybd_event</b> halte ich für keine gute Idee.<p>
                    <i>Worste case: </i>Windows hat beschlossen, das aus irgendeinem Grund die Festplatte formatiert werden muß (ist zufällig gerade voll geworden) und bringt wegen der Wichtigkeit seines Einfalles eine sytstemmodale MessageBox mit der Frage ja/nein/doch. Leider hat der Entwickler "vergessen", den Abbruch-Button als Default zu definieren... shade, daß keiner da ist, um dem Spektakel beizuwohnen =)<p>

                    OK, es ist maßlos übertrieben und (fast) unrealistisch -- doch ich hoffe, Du weißt was ich meine:<br>
                    Wer garantiert Dir, das Deine Anwendung noch den Fokus hat.

                    Gruß Nico

                    PS: Alternativ einen Extra-Thread abspalten, der die MessageBox anzeigt, dies läßt sich gut in eine Funktion packen (ich hatte hier schon irgendwo mal ein Beispiel geschrieben...

                    Comment


                    • #11
                      Besser als Keyb_event sollte der Aufruf Application.Terminate sein. Intern erkennt die MessageBox() das und kehrt dann sofort zur Anwendung zurück. Rückgabewert ist der Code des DefaultButton's.

                      Gruß Hage

                      Comment

                      Working...
                      X