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

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

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


person DaveS_Lifeway    schedule 07.06.2012    source источник
comment
Еще больше ошибок стилей VCL. Пожалуйста, проверьте это.   -  person David Heffernan    schedule 07.06.2012
comment
Веб-адрес QC: qc.embarcadero.com/wc/qcmain.aspx   -  person Warren P    schedule 07.06.2012
comment
Можете ли вы воспроизвести это поведение на одном мониторе? Я спрашиваю, потому что в моем текущем местоположении у меня нет другого монитора для проверки этой проблемы.   -  person RRUZ    schedule 08.06.2012
comment
Визуально поведение стилизованных приложений с одним монитором соответствует нестилевым приложениям, так что проблем нет.   -  person DaveS_Lifeway    schedule 08.06.2012
comment
Еще хуже обстоит дело с нерегулярно расположенными мониторами. Имейте дополнительный монитор с положительным верхом (+16 и т. Д.), Расположенный справа от основного монитора. Затем разверните форму на основном мониторе. Вы потеряете кнопки с субтитрами.   -  person Sertac Akyuz    schedule 08.06.2012
comment
Обязательно Ссылка Old New Thing: Почему развернутое окно имеет неправильный прямоугольник? (blogs.msdn.com/b/oldnewthing/archive /2012/03/26/10287385.aspx) описывает в последнем разделе, почему в последних версиях Windows нет границ для развернутых приложений, видимых на других мониторах. Код, выполняющий собственное рисование области ЧПУ, очевидно, не получает этой специальной обработки.   -  person mghie    schedule 08.06.2012
comment
Могу я проверить, правильно ли я понял. Вы используете ms-windows7, вы пишете приложение на delphi, используя vlc. Приложение не украшает себя должным образом в случае развернутой системы монитора дуэли, украшение всегда перетекает на другой экран. (следует использовать другую политику оформления для развернутых окон).   -  person ctrl-alt-delor    schedule 11.06.2012
comment
@mghie В этой статье есть полезная информация. Как упоминалось в этих комментариях, Photoshop действительно демонстрирует такое же поведение. В чем я не уверен, так это в том, как с этим справиться. Полагаю, я мог бы взять на себя всю отрисовку главного окна приложения, но это кажется большей головной болью, чем мне бы хотелось. У кого-нибудь есть предложения по возможным обходным путям?   -  person DaveS_Lifeway    schedule 11.06.2012
comment
@DaveS_Lifeway: Пробовали ли вы переключать стиль границы между одиночным и большим при увеличении / восстановлении окна?   -  person mghie    schedule 11.06.2012
comment
@mghie: Я пробовал это двумя способами: один в событии FormResize, а другой, перехватив сообщение WM_SYSCOMMAND. Ни один из них не работал идеально, но оба работали лучше (т.е. показывали меньшую часть края окна), чем вообще ничего. Перехват WM_SYSCOMMAND и установка BorderStyle: = bsSingle на SC_MAXIMIZE и BorderStyle: = bsSizeable на SC_RESTORE привели к наименьшей полосе на 2-м мониторе, но определенно все еще там.   -  person DaveS_Lifeway    schedule 12.06.2012
comment
Я тоже видел эту проблему. Я попытался ограничить MaxWidth формы на основе WorkareaRect активного монитора, но это создало другие проблемы, похуже исходной проблемы с границами. Если вы найдете обходной путь, опубликуйте его. Спасибо!   -  person James L.    schedule 29.06.2012


Ответы (2)


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

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

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

К сожалению, я не думаю, что это обходное решение вообще можно использовать. Во-первых, упомянутое поведение не задокументировано, во-вторых, обходной путь не идеален; все еще не хватает лишнего пикселя. Если вы привяжете окно точно к рабочей области, оконный менеджер решит сместить окно туда, где, по его мнению, должно быть размещено окно (со скрытыми рамками). (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;
person Sertac Akyuz    schedule 02.08.2012
comment
Раймонд специально говорит о визуальном трюке, поэтому я полагаю, мы не изменяем размер прямоугольника окна, а просто обрезаем выступающие границы? - person whosrdaddy; 02.08.2012
comment
@whos - Конечно, было бы намного лучше (тоже избавились бы от внутренних фреймов). Я думал, что для этого нам понадобится сотрудничество VCL, но, возможно, нет. - person Sertac Akyuz; 02.08.2012

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

person Dominique    schedule 14.10.2013