Link to home
Start Free TrialLog in
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.
Avatar of Lesko987
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š
Avatar of 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);
The solution hasn't worked, it still affects a small minority of users.  Any more solutions?
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.
Thanks kacor.
ASKER CERTIFIED SOLUTION
Avatar of modulo
modulo

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial