Delphi - Win7 Window Focus. - PullRequest
       16

Delphi - Win7 Window Focus.

1 голос
/ 04 мая 2011

Я выполняю exe-файл с помощью CreateProcess () и устанавливаю процесс переднего плана с помощью SetForegroundWindow ().но это не работает в Win7, поэтому я должен щелкнуть значок на панели задач.

Как мне реализовать желаемое поведение (то есть Launch и BringToForeground)?

Ответы [ 3 ]

8 голосов
/ 04 мая 2011

Ты даже не должен пытаться это делать.Изменение в SetForegroundWindow было преднамеренным - оно препятствует тому, чтобы приложения украли фокус от того, что пользователь хочет сфокусировать.См. Раздел «Примечания» по ссылке выше.

Вероятно, Win7 не позволит неадминистративным пользователям изменять необходимые параметры реестра, тем более делать это без перезапуска системы.

Вам следуетпросто используйте FlashWindow , чтобы привлечь внимание пользователя, как рекомендует Microsoft.Любое приложение, которое настаивает на том, чтобы отвлечь внимание от того, что я выбрал, будет немедленно удалено.

3 голосов
/ 04 мая 2011

Я собирался опубликовать ссылку (в комментарии) на фрагмент кода, который мне когда-то приходилось применять для решения собственной проблемы.Ссылка теперь оказалась неработающей, поэтому я выкладываю здесь код того, что он стоит (он был протестирован в Windows XP Pro SP2 и Windows Server 2003, но не в Windows 7 ):

function ForceForegroundWindow(hwnd: THandle): boolean;
{
found here:
http://delphi.newswhat.com/geoxml/forumhistorythread?groupname=borland.public.delphi.rtl.win32&messageid=501_3f8aac4b@newsgroups.borland.com
}
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);  // bingo
        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 }

end.

Я ничего не добавил в функцию, кроме небольшого комментария «бинго», которое отмечает строку, которая фактически привела к желаемому эффекту.

Так что вы, ребята, не сделалине думаю, что я злоупотребляю опытом пользователей с этой функцией, вот некоторые объяснения.

Эта функция использовалась в приложении, которое вызывалось удаленно с помощью программного обеспечения Citrix, установленного на планшетных ПК пользователей, иПриложение работает в полноэкранном режиме.Типичная рабочая сессия почти полностью состояла из этого приложения (другие части были просто системными компонентами, с которыми пользователь никогда не взаимодействовал).

Теперь некоторые части нашего приложения должны были быть реализованы как отдельные небольшие приложения, и они были разработаны дляоставайтесь поверх всех остальных окон, пока не закроете, как модальные окна.Время от времени они теряли свой Z-порядок и прятались под главным окном главного приложения, и это было полной катастрофой для пользователей.Использовать свойство top-most там не было возможности, поэтому мы должны были найти способ поддержать их позиции в Z-порядке.И поэтому мы использовали эту функцию.

0 голосов
/ 06 ноября 2017

ForceForegroundWindow работает у меня в Win10. Тем не менее, он не активирует внешнюю программу. Это только делает его видимым и сверху. Программа также делает то же самое при вызове себя. Я предполагаю, что если он активируется, он также настроит фокус для пользователя.

Rick

Я нашел разрешение для активации и настройки фокуса ... В процедуре «SetAppRestore» я инициировал его с помощью «MainFrm.visible: = false». Затем он переходит к SwitchApp и вызывает ForceForegroundWindow. После того, как он возвращается в «SetAppRestore», я вставил «MainFrm.visible: = true». Это заставило приложение стать активным и сосредоточиться на определенном компоненте: DataPge.SetFocus.

Прошу прощения за то, что не поместил код в блок кода. Я не мог понять инструкции. Поэтому я положил все это между 2 ===== барами.

// ==========================

function TMainFrm.FindWindowExtd(partialTitle: string): HWND;  // get with wildcard
var                                   // by Dorin Duminica, September 10, 2009
  hWndTemp: hWnd;
  iLenText: Integer;
  cTitletemp: array [0..254] of Char;
  sTitleTemp: string;
begin
  hWndTemp := FindWindow(nil, nil);
  while hWndTemp <> 0 do
    begin
    iLenText := GetWindowText(hWndTemp, cTitletemp, 255);
    sTitleTemp := cTitletemp;
    sTitleTemp := UpperCase(copy( sTitleTemp, 1, iLenText));
    partialTitle := UpperCase(partialTitle);
    if pos(partialTitle, sTitleTemp) <> 0 then Break;
    hWndTemp := GetWindow(hWndTemp, GW_HWNDNEXT);
    end;
  result := hWndTemp;
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);  // bingo
                  Result:= (GetForegroundWindow = hwnd);
                  //showmessage('case 1');
                  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);
                  //showmessage('case 2');
                  end;
               end
               else begin
                    BringWindowToTop(hwnd); // IE 5.5 related hack
                    SetForegroundWindow(hwnd);
                    //showmessage('case 3');
                    end;
          Result:= (GetForegroundWindow = hwnd);
          end;
end; { ForceForegroundWindow }

procedure TMainFrm.SwitchApp(AppCaption:string); // application.restore;
          begin
          //TmpAppHandle:= FindWindow(nil, PChar(AppCaption)); // uses Windows unit - must be entire caption
          TmpAppHandle:= FindWindowExtd(AppCaption);   //  finds 'notepad' as partial of 'Document - Notepad'
          if (TmpAppHandle<>0)
             then begin
                  //SetForegroundWindow(TmpAppHandle); // worked by itself for WinXP and Win7
                  ForceForegroundWindow(TmpAppHandle);
                  end
             else ShowAlert(AppCaption+' *not found*');
          end;

// application.restore can't restore from MainForm.windowstate:=wsMinimized
// SetAppMinimize and SetAppRestore fix that issue and manual minimizations
procedure TMainFrm.SetAppMinimize; // application.minimize
          begin
          if not(MainFrm.WindowState=wsMinimized) then
             begin
             MainFrm.WindowState:= wsMinimized;
             end;
          SwitchApp(ServerName); // autocad or bricscad
          end;

procedure TMainFrm.SetAppRestore; // application.restore
          begin
          MainFrm.visible:= false;  // ** to reinsate and focus in win10 **
          if (MainFrm.WindowState=wsMinimized) then
             begin
             MainFrm.WindowState:= wsNormal;
             end;
          SwitchApp('CmdData');  // partial string for app title
          MainFrm.visible:= true;   // ** to reinsate and focus in win10 **
          FormatGrid; // added for activex crash
          DataPge.SetFocus;
          Update;
          end;

// ==========================

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...