Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

z order problem

Posted on 2013-12-06
3
Medium Priority
?
967 Views
Last Modified: 2013-12-12
I have a windows application written with Delphi 2010 and occasionally forms that I have opened modal will get stuck behind my main application form.  What causes this?

Thanks for your help

Daniel
0
Comment
Question by:DanielManchester
[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
3 Comments
 
LVL 19

Expert Comment

by:MerijnB
ID: 39702223
Do you have the formstyle of your main form set to stayontop? If yes, set the formstyle of your modal form to stayontop too.
0
 
LVL 27

Accepted Solution

by:
Sinisa Vuk earned 1000 total points
ID: 39704468
This is know problem with parent-modal forms. I use this procedure to solve this issue.

Put this in definition section (before implementation)
procedure SwitchToThisWindow(h1: hWnd; x: bool); stdcall; external user32 Name 'SwitchToThisWindow';

Open in new window


.. and call procedure in OnShow event of modal form:
SwitchToThisWindow(Self.Handle, True);

Open in new window

0
 
LVL 38

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 1000 total points
ID: 39705678
this is a bug
which unfortunately can't be reproduced, so it's difficult to solve

handling it in the onshow is not always enough ...
sometimes the window isn't visible until after that event :-)

there is 2 questions on this with solutions
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_26286057.html
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_23461413.html

i'd use a timer which puts the top form in front:
Maybe add some intelligence to detect changes to the form list ?
procedure TfrmMain.TimerLoginDialogTimer(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to Screen.FormCount-1 do
    if fsModal in Screen.Forms[I].FormState then
    begin
      if Screen.Forms[I].Visible and Application.Active then
      begin
        Screen.Forms[I].BringToFront;
        Exit;
      end;
    end;
end;

Open in new window


I setup a small test to test the bad behaviour
unit Unit2;

interface

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

type
  TForm2 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Timer1: TTimer;
    Timer2: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Timer2Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

uses Unit3, TypInfo;

function GetOrdValue(Info: PTypeInfo; const SetParam): Integer;
begin
  Result := 0;

  case GetTypeData(Info)^.OrdType of
    otSByte, otUByte:
      Result := Byte(SetParam);
    otSWord, otUWord:
      Result := Word(SetParam);
    otSLong, otULong:
      Result := Integer(SetParam);
  end;
end;

function SetToString(Info: PTypeInfo; const SetParam; Brackets: Boolean): AnsiString;
var
  S: TIntegerSet;
  TypeInfo: PTypeInfo;
  I: Integer;
begin
  Result := '';

  Integer(S) := GetOrdValue(Info, SetParam);
  TypeInfo := GetTypeData(Info)^.CompType^;
  for I := 0 to SizeOf(Integer) * 8 - 1 do
    if I in S then
    begin
      if Result <> '' then
        Result := Result + ',';
      Result := Result + GetEnumName(TypeInfo, I);
    end;
  if Brackets then
    Result := '[' + Result + ']';
end;

procedure TForm2.Button1Click(Sender: TObject);
var frm: TForm;
begin
  frm := TForm3.Create(Application);
  frm.Show;
  frm.BringToFront;
  frm.Update;

  frm := TForm3.Create(Application);
  frm.Visible := False;
  frm.ShowModal;
end;

procedure TForm2.Timer1Timer(Sender: TObject);
var I: Integer;
  F: TForm;
  P: PTypeInfo;
  FS: TFormState;
  S: String;
begin
  Memo1.Clear;
  for I := 0 to Screen.FormCount - 1 do
  begin
    F := Screen.Forms[I];
    Fs := F.FormState;
    S := SetToString(PTypeInfo(TypeInfo(TFormState)), FS, False);
    memo1.Lines.Add('#: ' + IntToStr(I) + ', Form: ' + F.Name + ', FormState: ' + S +
      'Visible, ' + BoolToStr(F.Visible));
  end;
end;

procedure TForm2.Timer2Timer(Sender: TObject);
var I: Integer;
begin
// fix the form in front problem
  for I := 0 to Screen.FormCount-1 do
    if fsModal in Screen.Forms[I].FormState then
    begin
      if Screen.Forms[I].Visible and Application.Active then
      begin
        Screen.Forms[I].BringToFront;
        Exit;
      end;
    end;
end;

end.

Open in new window

object Form2: TForm2
  Left = 138
  Top = 118
  Caption = 'Form2'
  ClientHeight = 525
  ClientWidth = 963
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 32
    Top = 24
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
  object Memo1: TMemo
    Left = 24
    Top = 72
    Width = 849
    Height = 401
    Lines.Strings = (
      'Memo1')
    TabOrder = 1
  end
  object Timer1: TTimer
    Interval = 1000
    OnTimer = Timer1Timer
    Left = 176
    Top = 32
  end
  object Timer2: TTimer
    Interval = 10000
    OnTimer = Timer2Timer
    Left = 276
    Top = 32
  end
end

Open in new window


unit Unit3;

interface

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

type
  TForm3 = class(TForm)
    Timer1: TTimer;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Timer1Timer(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
  public
    constructor Create(AOwner: TComponent); override;
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

constructor TForm3.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Width := 200;
  Height := 200;
end;

procedure TForm3.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

procedure TForm3.FormShow(Sender: TObject);
begin
  if fsModal in FormState then
    Caption := 'Modal'
  else Caption := 'Modeless';

end;

procedure TForm3.Timer1Timer(Sender: TObject);
begin
  if not (fsModal in FormState) then
    BringToFront;
  timer1.Enabled := False;
end;

end.

Open in new window


object Form3: TForm3
  Left = 287
  Top = 165
  Caption = 'Form3'
  ClientHeight = 525
  ClientWidth = 963
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  Position = poOwnerFormCenter
  Visible = True
  OnClose = FormClose
  OnShow = FormShow
  PixelsPerInch = 96
  TextHeight = 13
  object Timer1: TTimer
    OnTimer = Timer1Timer
    Left = 104
    Top = 40
  end
end

Open in new window


The test:
After clicking the button it creates 2 forms.
first modeless, the next modal
a second later, the modeless form is put in front
(with timer on form3)

as the modal form only allows input and not the modeless form on top
nothing can be done with the app anymore.
> same problem as you have probably

after timer 2 has run (every 10 seconds) it should bring the modal form to the front
and the app should be responsive again
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…
Suggested Courses

730 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