Подтвердить что ты не робот

Что я могу сделать с максимально развернутыми, стилизованными окнами, которые показывают свои границы на соседних мониторах?

В системе с несколькими мониторами "пустое" приложение VCL максимизирует штраф, но одно и то же приложение со включенными стилями (и выбрано по умолчанию) максимизируется неправильно. То, что я вижу, - это правый край окна, который распространяется на второй монитор (мой главный слева). Когда я начал сравнивать с другими приложениями Windows, я заметил, что в Windows 7 (по крайней мере) максимальные окна даже не имеют границ без клиента слева, справа или внизу. И действительно, стандартное приложение VCL (non-styled) ведет себя так же, без границ неклиента.

Как это исправить? Я заметил, что у TFormStyleHook есть обработчик для WMNCCalcSize, который я еще не разрезал, но заставляет меня задаться вопросом, может ли VCL неправильно обрабатывать это сообщение для максимального окна.

4b9b3361

Ответ 1

После некоторого времени на это, я считаю, это не ошибка в стиле vcl. Это действительно связано с поведением в статье, упомянутой в comment на вопрос mghie.

Конкретное поведение заключается в том, что размер максимально развернутого окна больше, чем рабочая область монитора, что окно максимизируется. Предположительно, оконный менеджер скрывает границы выступов. По-видимому, это не совсем так с настроенными кадрами. Обратите внимание, что MSDN собственный примерный пример кадра окна, похоже, страдает от той же проблемы (см. Сообщение под заголовком "Ошибка при максимальном увеличении окна" в сообществе содержание). Приложение VCL отличается от примера MSDN тем, что оно не основано на DWM, но я все еще думаю, что это та же проблема.

Границы свеса имеют размер границы размера системы (SM_C [X | Y] SIZEFRAME), но это не имеет отношения к обходному пути ниже, поскольку он игнорирует предлагаемый OS размер и положение и использует рабочую область.

К сожалению, я не думаю, что это обходное решение можно использовать вообще. Во-первых, упомянутое поведение не документировано, во-вторых, обходное решение не является совершенным; есть еще нечетный пиксель. Если вы привязаете окно точно на рабочей области, диспетчер окон решает смещать окно туда, где он считает, что окно (со скрытыми фреймами) должно быть размещено. (Возможно, VCL был изменен, чтобы делать то, что делает оконный менеджер, и принимать во внимание свес и не рисовать их или что-то подобное, но это было бы больше работы, и все равно было бы обойти недокументированное поведение.)

В любом случае,

type
  TForm1 = class(TForm)
    ..
  protected
    // overriding styles is not necessary since TFormStyleHook.WMGetMinMaxInfo
    // first calls the default window procedure 
    procedure WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo);
      message WM_GETMINMAXINFO;

..

procedure TForm1.WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo);
var
  R: TRect;
begin
  // always arrives with MinMaxInfo.ptMaxPosition = (-SM_CXFRAME, -SM_CYFRAME)
  // and MinMaxInfo.ptMaxSize = (PrimaryMonitor.Width (?) + 2 * SM_CXFRAME, ... )
  inherited;

  // should test for OS, styles etc. before running the below 
  R := Monitor.WorkareaRect;
  InflateRect(R, -1, -1);             // odd pixel
  OffsetRect(R, -Monitor.Left, -Monitor.Top);
  Message.MinMaxInfo.ptMaxPosition := R.TopLeft;
  Message.MinMaxInfo.ptMaxSize := Point(R.Width, R.Height);
end;

Ответ 2

Единственный способ, которым я нашел, - обработать событие WM_SIZE и изменить область окна, чтобы нарезать дополнительную границу.