2013-12-12 1 views
4

У меня есть приложение, предназначенное для нескольких мониторов. Он запускается, и мы стараемся не активировать окна, которые не нужно активировать, потому что пользователь вводит только ввод с клавиатуры в одном месте, и каждый раз, когда мы активируем новую форму на дополнительном мониторе, он захватывает фокус клавиатуры, что-то мы хочу избежать.Как я могу сделать видимую форму и максимизировать ее, чтобы заполнить дополнительный монитор без активации?

Наш дом в базовый класс ТГогт имеет метод, как это, который с помощью функции Win32 ShowWindow напрямую, избегая внутренней системы изменения видимости фреймворка VCL, которая захватывает внимание:

procedure TOurForm.ShowWithoutActivate; 
begin 
    ShowWindow(Self.Handle, SW_SHOWNOACTIVATE); 
    Self.Visible := true; 
end; 

Если бы я просто сделал это было бы захватить внимание:

Self.Visible := true; // TWindow.Visible = true, will grab focus, plus make window visible. 

Это работает, но следующая вещь, которую я хотел бы быть в состоянии сделать, это установить развернутое состояние, так что формы будет максимально себя на мониторе, что в настоящее время на. Как мы получаем его на конкретный монитор? Точно так же он всегда работал, с изменением свойств Left и Top формы. Мы должны позаботиться о том, что если мы сохраним Left/Top/Width/Height в форме, а затем восстановим его, результаты будут действительны при перезагрузке. Это НЕ то, о чем я прошу.

Я спрашиваю о том, как максимизировать форму теперь, когда я «показал» ее, используя вышеуказанную пользовательскую функцию. Один взлом порождает еще один хак. Вот как далека по этой кроличьей норе я пошел:

  • Когда ТГет, который также является частным полем FShowing TWinControl ложно, установка Form.Maximized не имеет никакого эффекта.
  • Когда TForm имеет поле TWinControl.FShowing, значение true, установка windowState для wsMaximized также вызывает активацию формы.

Возможно ли сделать эту форму видимой и заставить ее принять состояние окна, которое я хочу, чтобы оно было выполнено без активации? Если я не смогу это сделать, тогда пользователи потеряют фокус клавиатуры, когда я покажу эту форму на дополнительном мониторе, чего я действительно хочу избежать.

То, что я пытался это использовать Win32 API ShowWindow сделать SW_SHOWMAXIMIZED:

ShowWindow(Self.Handle, SW_SHOWMAXIMIZED); 

выше, кажется, чтобы захватить фокус (реактивировать).

ответ

6

При создании окна верхнего уровня установлен расширенный стиль окна

WS_EX_NOACTIVATE | WS_EX_APPWINDOW 

WS_EX_NOACTIVATE останавливает окно активирующий. Это также заставляет его исчезнуть с панели задач, поэтому вам нужно WS_EX_APPWINDOW, чтобы исправить эту проблему.

Звоните ShowWindow(hWnd, SW_MAXIMIZE), и окно будет максимально, но не активировано.

Вы должны быть в состоянии активировать окно, когда она видна, поэтому в WM_ACTIVATE обработчиком вам нужно очистить WS_EX_NOACTIVATE флаг таким образом (ирония!):

case WM_ACTIVATE: 
    { 
     DWORD exstyle = GetWindowLong(hWnd, GWL_EXSTYLE); 
     if (exstyle & WS_EX_NOACTIVATE) 
     { 
      SetWindowLong(hWnd, GWL_EXSTYLE, exstyle & ~(DWORD)WS_EX_NOACTIVATE); 
     } 
    } 

Извинения для C++. Это должно быть просто перевести на Delphi.

+1

Это очень легко переводит на любой язык, спасибо! –

4

EnumDisplayMonitors API перечисляет мониторы и их координаты на совместном рабочем столе, в котором конкретный монитор отображает свое конкретное положение.

Чтобы узнать, какой монитор является «текущим», вы хотели бы сравнить текущее положение окна с координатами монитора. rcMonitor/rcWork. Или у вас есть MonitorFromPoint и друзья, чтобы помочь вам.

Однажды решила, какой монитор вы хотите, вы можете переместить окно (MoveWindow, SetWindowPos) для монитора рабочей зоны, или использовать этот прямоугольник в ответ на WM_GETMINMAXINFO сообщений, чтобы отправить окно в такое положение, как часть стандартной максимизации ,

Чтобы добавить к этому приложению, этот маленький С ++ [1, 2, 3] DemoS концепцию, упомянутого выше, показывает мониторинг информации, и изменяет положение, где окно будет развернуто на.

+0

Так что вместо вызова Win32 'ShowWindow (Win32Handle, SW_SHOWMAXIMIZED)' Я должен, может быть, назвать SetWindowPos? –

+0

С помощью 'SetWindowPos' вы можете указать corrdinates (которые могут быть теми, которые вы хотите, или вместо этого можете использовать флаг максимизации). «ShowWindow» с параметром максимизации запрашивает у вас информацию min/max из вашего окна - вы можете обрабатывать ее там и предоставлять координаты для максимизации, которая может быть «текущей рабочей областью монитора» или чем-либо еще по вашему усмотрению. –

Смежные вопросы