How to bring my application to the front?

后端 未结 8 662
孤城傲影
孤城傲影 2020-12-08 15:32

I know all the reasons why it is a bad idea. I dislike it if an application steals input focus, but this is for purely personal use and I want it to happen; it will not dist

相关标签:
8条回答
  • 2020-12-08 15:41

    This should work even in Windows7+8 OS. Only requirement is an application itself can call functions. It's trickier to use an external app to set another process's window front.

    Application.Restore; // unminimize window, makes no harm always call it
    SetWindowPos(self.Handle, HWND_NOTOPMOST,0,0,0,0, SWP_NOMOVE or SWP_NOSIZE);
    SetWindowPos(self.Handle, HWND_TOPMOST,0,0,0,0, SWP_NOMOVE or SWP_NOSIZE);
    SetWindowPos(self.Handle, HWND_NOTOPMOST,0,0,0,0, SWP_SHOWWINDOW or SWP_NOMOVE or SWP_NOSIZE);
    

    Edit Ok I found out one problem with this. Application is brought to front but focus is kept in an original application. Use this answer to fix the problem, its quite complex method but copypaste does the trick. Before calling ForceForegroundWindow(wnd) you may have to call Application.Restore unminimizing a window. https://stackoverflow.com/a/5885318/185565

    0 讨论(0)
  • 2020-12-08 15:45

    Form.bringtofront; ?

    Should work. If you put it in a timer it will stay at front.

    0 讨论(0)
  • 2020-12-08 15:47

    You could write an Executable to workaround that limitation. Take for example a simple (non-visual) application (basically a console app but without the {$APPTYPE CONSOLE}) with the only purpose to bring your desired window to front.

    Your monitoring background application calls the helper app via command line call (e.g. ShellExecute) whenever your bringtofront action is needed. Since this app is becoming the foreground process, it is then able to bring other windows to front (SetForeGroundWindow). You could use FindWindow to get a handle on your target window or pass appropriate parameters when starting your helper app.

    0 讨论(0)
  • 2020-12-08 15:57

    You can't do this reliably. Windows XP had a workaround that would allow it, but versions since then prohibit it for the most part (see note below). This is expressly stated in the remarks section of the MSDN documentation on SetForegroundWindow:

    The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

    • The process is the foreground process.
    • The process was started by the foreground process.
    • The process received the last input event.
    • There is no foreground process.
    • The foreground process is being debugged.
    • The foreground is not locked (see LockSetForegroundWindow).
    • The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
    • No menus are active.

    An application cannot force a window to the foreground while the user is working with another window. Instead, Windows flashes the taskbar button of the window to notify the user.

    Note the final paragraph of the quoted documentation, especially the first sentence.

    The problem with

    this is for purely personal use and I want it to happen; it will not disturb anything.

    is that any application could try to do the same thing. How does "purely personal use" tell it's you personally and not just any application? :-)

    Note: I've tried everything I can think of to get the IDE's documentation to show in the foreground when I click the help toolbutton, but all I can get is the flashing taskbar button (and I as the user want it to do so).

    0 讨论(0)
  • 2020-12-08 15:58

    I am doing something similar in one of my applications and this function works for me in xp/vista/w7:

    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
          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;
    

    Another solution is not to steal focus and just put the window TOPMOST in the z buffer:

    procedure ForceForegroundNoActivate(hWnd : THandle);
    
    begin
     if IsIconic(Application.Handle) then
      ShowWindow(Application.Handle, SW_SHOWNOACTIVATE);
     SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOMOVE);
     SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOMOVE);
    end;
    
    0 讨论(0)
  • 2020-12-08 16:04

    Here's something simple that seems to work, tested with multiple boxes consisting of XP, Server2003, Vista, Server2008, W7. Test application ran with a standard (or admin) account, stole the input focus from notepad while writing in the foreground.

    var
      Input: TInput;
    begin
      ZeroMemory(@Input, SizeOf(Input));
      SendInput(1, Input, SizeOf(Input)); // don't send anyting actually to another app..
      SetForegroundWindow(Handle);
    

    You can tweak it further f.i. for a minimized app or such if required.

    0 讨论(0)
提交回复
热议问题