Avatar of Deliciosa
Deliciosa
 asked on

Focus problems when using multiple forms and message boxes in Delphi

I'm having focus problems with my application in Delphi.  It's complicated and uses Word_TLB, which is where the problem form is launched from.  It's mainly a problem on PC's running Office 2003 for some reason and barely affects PC's running Office 2000.

I try to set focus on modal forms, as Delphi doesn't always set focus to them correctly for some reason.  Sometimes it just keeps focus on the main application, which won't respond as it's waiting for the modal form to close.  The only way to get focus onto the modal window is to alt+tab round a few times until the child window gains focus.

I have tried various solutions including one which tries various methods depending on which file is in the root, it tries this every 1.5 seconds:

procedure TSenWPFileNameFrm.Timer1Timer(Sender: TObject);
begin
     If ((Application.Active)or(m_shown<2)) then
      begin
       Inc(m_shown);
       If FileExists('c:\focus.a') then
        begin
         SetForegroundWindow(handle);
         SetActiveWindow(handle);
         Invalidate;
        end
       Else
        begin
         If FileExists('c:\focus.b') then
          begin
           Application.BringToFront;
          end
         Else
          begin
           If FileExists('c:\focus.c') then
            Self.SetFocusOnForm
           Else
            if GetForegroundWindow<>Self.handle then
             ForceForegroundWindow(Self.handle);
          end;
        end;
      end;
end;



function ForceForegroundWindow(hwnd: THandle): boolean;
const
  SPI_GETFOREGROUNDLOCKTIMEOUT = $2000;
  SPI_SETFOREGROUNDLOCKTIMEOUT = $2001;
var
  ForegroundThreadID: DWORD;
  ThisThreadID      : DWORD;
  timeout           : DWORD;
begin
  if IsIconic(hwnd) then ShowWindow(hwnd, SW_RESTORE);

  if GetForegroundWindow = hwnd then Result := true
  else begin

    // Windows 98/2000 doesn't want to foreground a window when some other
    // window has keyboard focus

    if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4))

or
      ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and
      ((Win32MajorVersion > 4) or ((Win32MajorVersion = 4) and
(Win32MinorVersion > 0)))) then
    begin

      // Code from Karl E. Peterson, www.mvps.org/vb/sample.htm
      // Converted to Delphi by Ray Lischner
      // Published in The Delphi Magazine 55, page 16

      Result := false;
      ForegroundThreadID :=
GetWindowThreadProcessID(GetForegroundWindow,nil);
      ThisThreadID := GetWindowThreadPRocessId(hwnd,nil);
      if AttachThreadInput(ThisThreadID, ForegroundThreadID, true) then
begin
        BringWindowToTop(hwnd); // IE 5.5 related hack
        SetForegroundWindow(hwnd);
        AttachThreadInput(ThisThreadID, ForegroundThreadID, false);
        Result := (GetForegroundWindow = hwnd);
      end;
      if not Result then begin

        // Code by Daniel P. Stasinski

        SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @timeout, 0);
        SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0),
SPIF_SENDCHANGE);
        BringWindowToTop(hwnd); // IE 5.5 related hack
        SetForegroundWindow(hWnd);
        SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
TObject(timeout), SPIF_SENDCHANGE);
      end;
    end
    else begin
      BringWindowToTop(hwnd); // IE 5.5 related hack
      SetForegroundWindow(hwnd);
    end;

    Result := (GetForegroundWindow = hwnd);
  end;
end; { ForceForegroundWindow }


Any help would be greatly appreciated. Thanks.
Delphi

Avatar of undefined
Last Comment
modulo

8/22/2022 - Mon
Lesko987

Hi Deliciosa,

We also had some problems with forums showing behind main window. But we solved that with calling someform.BringToFront.

And another problem we had was when showing some messages. We  solved that with use of following routines.

Procedure msgError (Const S: String);
begin
  Application.NormalizeAllTopMosts ;
  Application.MessageBox ( PChar ( S ) , PChar ('Error') , mb_OK Or mb_IconError ) ;
  Application.RestoreTopMosts ;
//  DebugLog.Writeln ( '' , S ) ;
end;

Procedure msgWarOK (Const S: String);
begin
  Application.NormalizeAllTopMosts ;
  Application.MessageBox ( PChar ( S ) , PChar ('Warning'), mb_OK Or mb_IconWarning ) ;
  Application.RestoreTopMosts ;
end;

Procedure msgWarOK (Const S, Caption: String);
begin
  Application.NormalizeAllTopMosts ;
  Application.MessageBox ( PChar ( S ) , PChar (Caption), mb_OK Or mb_IconWarning ) ;
  Application.RestoreTopMosts ;
end;

function msgWarYN ( Const S : String ) : Boolean;
begin
  Application.NormalizeAllTopMosts ;
  Result := Application.MessageBox ( PChar ( S ) , 'Warning' , mb_YesNo Or mb_IconWarning ) = id_Yes ;
  Application.RestoreTopMosts ;
end;

function msgWarYN ( Const S, Caption : String; Options: Integer = 0) : Boolean;
begin
  Application.NormalizeAllTopMosts ;
  Result := Application.MessageBox ( PChar (S) , PChar (Caption), mb_YesNo Or mb_IconWarning Or Options ) = id_Yes ;
  Application.RestoreTopMosts ;
end;

function  msgWarYNC (Const S: String) : Integer;
begin
  Application.NormalizeAllTopMosts ;
  Result := Application.MessageBox ( PChar (S) , 'Warning', mb_YesNoCancel Or mb_IconWarning);
  Application.RestoreTopMosts ;
end;

function  msgWarYNC (Const S, Caption: String) : Integer;
begin
  Application.NormalizeAllTopMosts ;
  Result := Application.MessageBox ( PChar (S) , PChar (Caption), mb_YesNoCancel Or mb_IconWarning);
  Application.RestoreTopMosts ;
end;

Maybe this will help you with your problem.

Regards Aleš
Deliciosa

ASKER
So far it looks like the following code is going to work, I'll know more in a few weeks - it's currently in testing:

SetWindowPos(Self.Handle, HWND_TopMost,0,0,0,0,SWP_NOMove or SWP_NOSize);
Deliciosa

ASKER
The solution hasn't worked, it still affects a small minority of users.  Any more solutions?
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Deliciosa

ASKER
I didn't accept the answer as it didn't solve the problem.  I was hoping for a new solution that resolved the focus issue but noone has provided one.
Deliciosa

ASKER
Thanks kacor.
ASKER CERTIFIED SOLUTION
modulo

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.