Как увеличить форму до размера рабочего стола?

В приложении Delphi 10.4.2 Win32 VCL, работающем в Windows 10, в настройке с двумя мониторами, когда я устанавливаю свою основную форму (или любую другую вторичную форму) для запуска в развернутом виде, устанавливая WindowState := wsMaximized, тогда форма разворачивается только на основном мониторе .

Как я могу развернуть форму на весь рабочий стол, чтобы размер формы включал ОБА МОНИТОРА? Есть ли для этого встроенный метод класса TForm?


person user1580348    schedule 27.07.2021    source источник


Ответы (3)


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

«Простая

В этом случае я предполагаю, что вы хотите, чтобы окно было размещено следующим образом:

«Окно,

Однако что, если у пользователя такой макет:

Пейзаж + портрет + альбомная настройка экрана

Вы хотите

Видно все окно, но часть экрана не используется

(все окно видно, но часть экрана не используется) или

Нет неиспользуемого пространства, но некоторые части окна не видны.

(нет неиспользуемого пространства, но некоторые части окна не видны)?

Если вы хотите использовать все пространство виртуального рабочего стола — последний случай — это легко сделать:

BoundsRect := Screen.DesktopRect;

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

Также имейте в виду, что Windows не нравится такое поведение окон, поэтому пользователь может не получить приятного опыта использования приложения.

В общем, не делайте этого.


Обратите внимание, что даже установка с двумя мониторами, в которой оба монитора являются альбомными, может быть нетривиальной:

«Один

Геометрия может быть нетривиальной, даже если оба монитора имеют одинаковый размер:

«Два

person Andreas Rejbrand    schedule 27.07.2021
comment
Когда я выполняю Self.BoundsRect := Screen.DesktopRect; в обработчике формы OnCreate, форма по-прежнему развернута на основном мониторе. - person user1580348; 27.07.2021
comment
@ user1580348: НЕ устанавливайте WindowState на wsMaximized. Максимизированное окно будет использовать только один экран. (В Windows развернутое примерно означает, что используется (один) полный экран, поэтому, если вы хотите использовать два или три экрана, окно по определению не может быть развернуто.) - person Andreas Rejbrand; 27.07.2021
comment
Я отказался от идеи расширить свою форму на оба монитора. Вместо этого я переключу развернутую форму с одного монитора на другой. Я должен буду узнать, как это сделать. - person user1580348; 28.07.2021
comment
@user1580348: Хорошо, но это действительно работает! - person Andreas Rejbrand; 28.07.2021
comment
Может быть, это работает в Windows 7, но не в Windows 10? - person user1580348; 28.07.2021
comment
Вряд ли. Вы абсолютно уверены, что у вас есть WindowState = wsNormal? Используете ли вы масштабирование DPI (например, один монитор на 100%, а другой на 120%)? Это может быть проблемой. Тогда это может зависеть от осведомленности вашего приложения о DPI. - person Andreas Rejbrand; 28.07.2021
comment
Да, WindowState = wsNormal. - person user1580348; 28.07.2021
comment
И да, форма распространяется на оба монитора - но на этом втором мониторе выделение не работает. Так что я приму ваш ответ, но я должен выяснить, почему выбор не работает на втором мониторе. - person user1580348; 28.07.2021
comment
Хорошо, но тогда проблема связана не с созданием формы, охватывающей весь рабочий стол, а с каким-то другим кодом, который мы здесь не видим! Вероятно, какое-то преобразование координат пошло не так. В любом случае: несвязанная проблема. - person Andreas Rejbrand; 28.07.2021
comment
Если вы решите покрыть весь рабочий стол моей собственной формой, на которой я нарисую рабочий стол, другим подходом будет создание одной формы для каждого монитора. Тогда вы не тратите пространство растрового изображения на неиспользуемые области. Вы можете повторить Screen.Monitors (используя for i := 0 to Screen.MonitorCount - 1), чтобы получить границы для каждого монитора. - person Andreas Rejbrand; 28.07.2021
comment
@ Значит, мне придется создать n клонов моей формы, по одному на каждый монитор? - person user1580348; 28.07.2021
comment
Да, это была моя идея. Некоторые вещи могут быть проще в вашем конкретном сценарии. - person Andreas Rejbrand; 28.07.2021
comment
Люди используют ноутбуки и подключают к ним мониторы, используя оба экрана для разных задач. Хотя оба экрана отображают один рабочий стол, они имеют разные размеры и разные положения, скорее всего, не рядом друг с другом (экраны ноутбуков начинаются сразу со стола, мониторы редко могут это делать). Этот ответ описывает, как могут выглядеть разные среды. @user1580348 user1580348 Пусть пользователь решает, чего он хочет. - person AmigoJack; 28.07.2021

Согласно MSDN:

Позиционирование объектов на нескольких мониторах

Окно или меню, которые находятся более чем на одном мониторе, вызывают визуальное нарушение для зрителя. Чтобы свести к минимуму эту проблему, система отображает меню и новые развернутые окна на одном мониторе.

Таким образом, если вы хотите, чтобы окно TForm растянулось на весь рабочий стол, использование WindowState=wsMaximize не подходит, так как оно будет работать только на один монитор, на котором чаще всего отображается форма.

Чтобы сделать то, что вы просите, вам нужно будет получить прямоугольник Виртуальный экран из GetSystemMetrics() (или Vcl.Forms.TScreen), а затем соответственно установите Left/Top/Width/Height формы, например:

if Screen.MonitorCount > 1 then
begin
  Form.WindowState := wsNormal;
  Form.Left := Screen.DesktopLeft;
  Form.Top := Screen.DesktopTop;
  Form.Width := Screen.DesktopWidth;
  Form.Height := Screen.DesktopHeight;
  // or:
  Form.SetBounds(Screen.DesktopLeft, Screen.DesktopTop, Screen.DesktopWidth, Screen.DesktopHeight);
  // or:
  Form.BoundsRect := Screen.DesktopRect;
end else
begin
  Form.WindowState := wsMaximized;
end;
person Remy Lebeau    schedule 27.07.2021
comment
Что не так с простым Self.BoundsRect := Screen.DesktopRect? - person Andreas Rejbrand; 27.07.2021
comment
@AndreasRejbrand Смотрите мое обновление. Обычно я не работаю с несколькими мониторами, поэтому мне пришлось поискать. - person Remy Lebeau; 27.07.2021
comment
Этот код, кажется, правильно расширяет окно на оба монитора. Однако функциональность того, что я делаю, работает только на основном мониторе. Что я делаю: я копирую весь рабочий стол в графический элемент управления, который настроен на заполнение всей клиентской области формы. Это приводит к тому, что элемент управления графикой выглядит так же, как рабочий стол за формой. Затем я выбираю частичную область графического элемента управления и обрабатываю ее по своему усмотрению. Но поскольку этот код правильно показывает копию рабочего стола в графическом элементе управления, выбор работает только на основном мониторе. - person user1580348; 28.07.2021
comment
@ user1580348 Я действительно понятия не имею, что вы пытаетесь сделать. Какой смысл копировать рабочий стол в ваш пользовательский интерфейс? Почему бы вместо этого просто не работать с растровым изображением в памяти? Чего вы ДЕЙСТВИТЕЛЬНО пытаетесь достичь? - person Remy Lebeau; 28.07.2021
comment
Это то же самое, что открыть Блокнот и вручную перетащить его размер, чтобы заполнить оба монитора: часть окна Блокнота на основном мониторе принимает мои данные и работает как обычно, но часть окна Блокнота на втором мониторе едва видна. Отсюда делаю вывод: окно может быть активным только на одном мониторе и не может быть расширено на несколько мониторов для ввода/вывода. Таким образом, кажется, что то, что я пробовал, невозможно: иметь полностью рабочую форму, расширенную более чем на один монитор. - person user1580348; 28.07.2021
comment
@ user1580348: В моей системе это возможно. Я только что сделал приложение Delphi с TMemo и заставил его отображаться на моем полном рабочем столе, состоящем из четырех мониторов, не все одинаковые, и некоторого невидимого пространства. Я могу писать текст в нем просто отлично. - person Andreas Rejbrand; 28.07.2021
comment
Суть в том, чтобы создать у пользователя иллюзию того, что он видит настоящий рабочий стол. Затем он может выбрать часть этого изображения и скопировать его, чтобы получить снимок экрана из выбранной области с рабочего стола. - person user1580348; 28.07.2021
comment
Да, я понимаю, что этот вопрос является продолжением stackoverflow.com/questions/68467642/, stackoverflow.com/questions/68498524/ и stackoverflow.com/questions/68509311/. - person Andreas Rejbrand; 28.07.2021
comment
@AndreasRejbrand Вы правы. Когда это делается только с одним монитором, все работает отлично. Поэтому моим следующим шагом будет просто переключение моей формы с одного монитора на другой. - person user1580348; 28.07.2021
comment
@ user1580348 Смысл в том, чтобы создать у пользователя иллюзию того, что он видит настоящий рабочий стол. Затем он может выбрать часть этого изображения и скопировать его, чтобы получить снимок экрана из выбранной области с рабочего стола — тогда почему бы просто не работать с НАСТОЯЩИМ рабочим столом? Использовать крючок мыши, чтобы отслеживать, где пользователь выбирает, а затем делать скриншот реального рабочего стола? Я смущен... - person Remy Lebeau; 28.07.2021
comment
@RemyLebeau Поверьте мне, я пробовал это разными способами, но ничего не работает без проблем. Посмотрите на SO историю моих последних сообщений... - person user1580348; 28.07.2021
comment
Да, лучше использовать настоящий рабочий стол и использовать только прозрачное оверлейное окно для прямоугольника селектора. Во-первых, рабочий стол может меняться (например, приложение часов может перерисовываться каждую секунду, анимация/видео много раз в секунду). - person Andreas Rejbrand; 28.07.2021
comment
@AndreasRejbrand Это легко сказать, но я не смог этого добиться ... - person user1580348; 28.07.2021
comment
Вы пробовали с крючком для мыши? Что ж, копирование растрового изображения и отображение в вашей собственной форме также должно работать (но с большим потреблением памяти и ЦП и без обновления в реальном времени). - person Andreas Rejbrand; 28.07.2021
comment
@AndreasRejbrand Проблема не в крючке мыши, а в том, чтобы нарисовать рамку выбора на прозрачном слое ... Я пробовал это, но это невозможно. - person user1580348; 28.07.2021
comment
@user1580348 user1580348 создание отдельного полупрозрачного окна верхнего уровня, которое мышь может располагать и изменять размер над рабочим столом, должно быть очень простой задачей, а затем вы можете скрыть окно и сделать снимок экрана того, что было под ним по мере необходимости. - person Remy Lebeau; 28.07.2021
comment
@ user1580348: Разве ты не делал этого несколько дней назад? stackoverflow.com/questions/68509311/ - person Andreas Rejbrand; 28.07.2021
comment
@AndreasRejbrand Да, но это не сработало без проблем, на которые я указал. - person user1580348; 28.07.2021

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

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

procedure TMyForm.GoLarge();
var
  rctDesktop:   TRect;
  hDT:          HWND;
begin
  hDT:=GetDesktopWindow();
  if(hDT<>0) then
  begin
    GetWindowRect(hDT, rctDesktop);
    Self.SetBounds(rctDesktop.Left,  rctDesktop.Top, rctDesktop.Width, rctDesktop.Height);
  end;
end;

Это не учитывает панель задач или что-либо еще, что использует часть рабочего пространства.

person Rob Lambden    schedule 27.07.2021
comment
Что не так с простым Self.BoundsRect := Screen.DesktopRect? - person Andreas Rejbrand; 27.07.2021
comment
Даже это максимизирует вид на основной монитор. - person user1580348; 27.07.2021
comment
@ user1580348: В моей системе этого не происходит. Вы уверены, что НЕ установили WindowState в wsMaximized? - person Andreas Rejbrand; 27.07.2021
comment
@AndreasRejbrand Пожалуйста, смотрите мои комментарии в верхнем ответе. - person user1580348; 28.07.2021