Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Modal dialog not modal

Posted on 1998-06-29
13
Medium Priority
?
827 Views
Last Modified: 2010-04-04
In my app I create a dialog which I show with the ShowModal method.
After the dialog shows, a procedure is started (an other dialog method) where I run a loop which contains Application.ProcessMessages. Now the dialog no longer is modal: my app reacts to all other events, something I don't want. How can I show this dialog modal and still call Application.ProcessMessages? (I don't want to disable all controls of my main window to simulate a modal dialog). Or is this simply contradictory?

Wim
0
Comment
Question by:cadenza
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 3
  • +1
13 Comments
 
LVL 3

Accepted Solution

by:
rickpet earned 150 total points
ID: 1356395
Instead of calling Application.ProcessMessages you should use Application.HandleMessage;

As Danny Thorpe states..."TApplication.HandleMessage is a public method for situations where you need to implement a custom local message loop (like ShowModal) and want to retain the standard Delphi message filter behavior and the application idle behavior."..."use HandleMessage when you have nothing else to do but wait for a message based exit condition.  When all you're doing is processing messages, you don't care if the app goes idle-you can't do anything until you see the next message anyway."  Page 186 of Delphi Component Design by Danny Thorpe.

Rick
0
 
LVL 4

Expert Comment

by:d003303
ID: 1356396
Another thing would be to place your procedure in a seperate thread.
0
 

Author Comment

by:cadenza
ID: 1356397
Hi Rick and d003303,

HandleMessage nor a separate thread will do what I want. The app will still react on all messages, including messages sent to e.g. the buttonbar of my main form. What I want is that only the messages sent to my modal dialog (or its child controls) are handled. The messages relevant to me are: pressing the close button, scrolling a stringlist and some timer messages.

What I initially had hoped was that by showing the dialog modal, windows/delphi would ignore all messages sent to my app but not to the dialog.

More and more I get the feeling the only way to get this effect is to disable all controls of the main form (which is th only visible part of the app besides the dialog at the moment the dialog is shown)...
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
LVL 4

Expert Comment

by:d003303
ID: 1356398
What happens if you only use the ShowModal method and no ProcessMessages loop ? Like

MyDialog := TMyDialog.Create(Self);
MyDialog.Init;
if MyDialog.ShowModal = mrOK
 then UserPressedOK
 else UserPressedCancel;
MyDialog.Free;

Slash/d003303
0
 
LVL 3

Expert Comment

by:rickpet
ID: 1356399
I'm a little confused on the behavior that you are trying to get...like Slash/d003303 shows...if you just place it in Showmodal...this is the default behavior of Delphi...if that's not what you want then you can use this procedure to enable and disable all your children...Just feed the procedure your Forms...and it should disable all it's controls...and also do the reverse...

procedure EnableControls(Enabled: boolean; Control: TWinControl);
var
  i: integer;
begin
  for i:= 0 to Control.ControlCount -1 do
    if ((Control.Controls[i]) is TControl) then
      if ((Control.Controls[i]) is TWinControl) and (TWinControl(Control.Controls[i]).ControlCount > 0) then
        EnableControls(Enabled,TWinControl(Control.Controls[i]))
      else
        TControl(Control.Controls[i]).Enabled := Enabled;
end;

Rick

0
 
LVL 4

Expert Comment

by:d003303
ID: 1356400
...some cosmetics:

procedure TForm_Progress.VisualFeedback(Sender: TObject);
begin
  with ProgressThread do
   begin
     ProgressBar1.Position := Trunc(100 / TotalCount * Position);
     Label_Progress.Caption := Format('%d  of %d processed', [TotalCount, Position]);
   end;
end;

procedure TForm_Progress.FormShow(Sender: TObject);
var SaveCursor : TCursor;
begin
  SaveCursor := Screen.Cursor;
  Screen.Cursor := crHourGlass;
  StartThread;
  Screen.Cursor := SaveCursor;
end;

Slash/d003303
0
 
LVL 4

Expert Comment

by:d003303
ID: 1356401
oops, sorry, wrong thread :-|
0
 

Author Comment

by:cadenza
ID: 1356402
Rick & Slash,

I use the dialog to measure and present data from external equipment. I need a timer for time-out etc., so I need to call ProcessMessages once in a while to be able to catch the timer event. (this is reason 1 I need to call ProcessMessages)

 I can not put the loop in the OnShow event handler, since that would not show the dialog (and my measurements would not be shown). Therefor I send a user message to the dialog from the OnShow event handler. In the handler of the user message I put my measurement loop. This is handled after showing the dialog. If I would not call ProcessMessages in the loop, the click of the close button would not be handled. (reason 2).

If I don't call ProcessMessages, I have a modal dialog which can not be closed anymore and the timer event goes unnoticed. If I do call ProcessMessages, the dialog becomes modeless, effectively.

I think the only solution is Ricks disabling of all child controls, so I'll give him the points.

Both Rick and Slash many thanks for your contributions!

Wim
0
 
LVL 3

Expert Comment

by:rickpet
ID: 1356403
Note...instead of watching for all the messages...you could have your timer...kickoff it's own personal message(using PostMessage and Wm_User)...that you watch for in your HandleMessage loop in your dialog...

Rick
0
 

Author Comment

by:cadenza
ID: 1356404
Uhh, I think you may be right. Sounds quite complicated, though. And I'll have to do the same trick with some other components, like the close button? It seems to me that following your other suggestion with the recursive disableing of child controls is more straightforward to program.

I think I'll go for the easy solution now (disabling), keeping in mind what you wrote last, and try that later, when I have more time (instrument i/o always takes a lot of time to get right).

Thanks again,

Wim
0
 
LVL 4

Expert Comment

by:d003303
ID: 1356405
mmh, what about the following thought:
unit _tempform;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ExtCtrls;

type
  TForm_Temperature = class(TForm)
    Button1: TButton;
    ProgressBar1: TProgressBar;
    Label1: TLabel;
    Label2: TLabel;
    ProgressBar2: TProgressBar;
    Label3: TLabel;
    ProgressBar3: TProgressBar;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form_Temperature: TForm_Temperature;

implementation

{$R *.DFM}

procedure TForm_Temperature.Timer1Timer(Sender: TObject);
begin
  // get measuer values form whatever API
  // just fake here
  ProgressBar1.Position := ProgressBar1.Position + Trunc(Random(20) + 0.6) - 10;
  ProgressBar2.Position := ProgressBar2.Position + Trunc(Random(20) + 0.6) - 10;
  ProgressBar3.Position := ProgressBar3.Position + Trunc(Random(20) + 0.6) - 10;
end;

procedure TForm_Temperature.FormShow(Sender: TObject);
begin
  Timer1.Enabled := true;
end;

end.

// form code

object Form_Temperature: TForm_Temperature
  Left = 200
  Top = 108
  BorderStyle = bsDialog
  Caption = 'Temperatures'
  ClientHeight = 127
  ClientWidth = 258
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 176
    Top = 12
    Width = 69
    Height = 13
    Caption = 'Temperature 1'
  end
  object Label2: TLabel
    Left = 176
    Top = 36
    Width = 69
    Height = 13
    Caption = 'Temperature 2'
  end
  object Label3: TLabel
    Left = 176
    Top = 60
    Width = 69
    Height = 13
    Caption = 'Temperature 3'
  end
  object Button1: TButton
    Left = 172
    Top = 92
    Width = 75
    Height = 25
    Caption = '&Close'
    Default = True
    ModalResult = 2
    TabOrder = 0
  end
  object ProgressBar1: TProgressBar
    Left = 12
    Top = 12
    Width = 149
    Height = 13
    Min = 0
    Max = 100
    Position = 50
    TabOrder = 1
  end
  object ProgressBar2: TProgressBar
    Left = 12
    Top = 36
    Width = 149
    Height = 13
    Min = 0
    Max = 100
    Position = 50
    TabOrder = 2
  end
  object ProgressBar3: TProgressBar
    Left = 12
    Top = 60
    Width = 149
    Height = 13
    Min = 0
    Max = 100
    Position = 50
    TabOrder = 3
  end
  object Timer1: TTimer
    Enabled = False
    Interval = 100
    OnTimer = Timer1Timer
    Left = 12
    Top = 92
  end
end

Slash/d003303

0
 
LVL 3

Expert Comment

by:rickpet
ID: 1356406
Slash...

I think you posted to the wrong thread again....

Rick
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 4629927
Bought this Q
0

Featured Post

Ask an Anonymous Question!

Don't feel intimidated by what you don't know. Ask your question anonymously. It's easy! Learn more and upgrade.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Video by: ITPro.TV
In this episode Don builds upon the troubleshooting techniques by demonstrating how to properly monitor a vSphere deployment to detect problems before they occur. He begins the show using tools found within the vSphere suite as ends the show demonst…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Suggested Courses

596 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question