Ответ 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;