3
votes

I have an application in Delphi 7, which pops up modal dialogs for several conditions. I am trying to determine if the dialog from a specific unit is open from another unit and close it. So far, I've tried with following code:

Wnd := GetLastActivePopup(Application.Handle);
if (Wnd <> 0) and (Wnd <> Application.Handle) then
   PostMessage(Wnd, wm_close,0,0);

But, it closes all the opened dialogs. When I tried to specify for a specific form such as:

if (Wnd <> 0) and (Wnd <> FormTest.Handle) then

it throws Access Violation error.

How can I determine whether the dialog from specific unit is being popped up?

4

4 Answers

4
votes

Try looping through the Screen.Forms list looking for the desired modal form, and if found then close it:

var
  I: Integer;
  Frm: TForm;
begin
  for I := 0 to Screen.FormCount-1 do
  begin
    Frm := Screen.Forms[I];
    if fsModal in Frm.FormState then
    begin
      if Frm is TDesiredFormClass then
      // or: if Frm.ClassName = 'TDesiredFormClass' then
      // or: GetTypeData(PTypeInfo(Frm.ClassInfo))^.UnitName = 'DesiredUnitName' then
      // or: if (whatever other criteria you need) then
      begin
        Frm.Close; // sets ModalResult to mrCancel
        Break;
      end;
    end;
  end;
end;
2
votes
if (Wnd <> 0) and (Wnd <> FormTest.Handle) then

This leads to access violation if FormTest is not a valid instance reference. Either:

  1. FormTest is nil, or
  2. FormTest is not-nil, but refers to an object that has been destroyed.
1
votes

You can check the classname of the window with GetClassName function

0
votes

There is a simple solution that may work.

You could use:

procedure TForm1.Button2Click(Sender: TObject);
var
  h: hwnd;
begin
  h := FindWindow(PChar('TForm1'), PChar('Form1'));
  if h <> 0 then  
    PostMessage(h, WM_CLOSE, 0,0);
end;

It works well to identify if the there is a handle to the TForm1 window. The obvious thing here is that FindWindow will seek windows in the entire OS system. Now, if you want something faster, you could use @Remy solution, that will only seek for Application's forms.

From MSDN:

FindWindow function:

Retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search.

To Search for child windows use the following function:

FindWindowEx function:

Retrieves a handle to a window whose class name and window name match the specified strings. The function searches child windows, beginning with the one following the specified child window. This function does not perform a case-sensitive search.

These are links to the both functions, respectively: FindWindow and FindWindowEx