将一个窗体的WindowState
属性设置为wsMaximized
有时会导致该窗体不能最大化,而出现下面的情况:
长期存在的问题:这是我在2003年首次在Borland新闻组中提出的问题:
然后在2006年再次提出:
然后在2008年又一次提出:
有人在2012年在Embarcadero论坛上提出了这个问题:
现在是将这个18年老问题移植到Stackoverflow的时候了,也许终于有人想出了解决方法。
复现步骤:
我的帖子包含了半打失败模式,但最简单的是:
在表单上放置一个
Label
和一个Edit
:为
TEdit
添加一个OnEnter
事件:procedure TForm1.Edit1Enter(Sender: TObject); begin Label1.Font.Style := Label1.Font.Style + [fsBold]; end;
并设置表单:
WindowState
为wsMaximizedAutoScroll
为False
然后,嘣,失败了。
2008年帖子中的另一组步骤之一:
- 创建新应用程序和一个表单。
- 在设计时间将表单设置为最大化(WindowState = wsMaximized)。
- 在表单上放置 ListView 控件。
在 OnShow 过程中向列表视图添加 20 个空项:
procedure TForm1.FormShow(Sender: TObject); var i: Integer; begin for i := 1 to 20 do ListView1.Items.Add; end;
在设计时将表单的AutoScroll属性设置为false(AutoScroll = False)
当然,我不是想要“在RadStudio版本n中修复了此问题,请使用该版本”。 我正在寻找实际的解决方法(如果有),这可能包括引用CodeGear最终修复它时VCL源代码的相关更改。 (如果有修复的话)。
注意:将Position
从poDesigned更改为任何其他值都无法解决该问题。
解决方法
我曾经使用过的一个可怕、丑陋、可耻的解决方法是在OnShow
期间启动一个计时器,然后当计时器触发时,将窗体最大化:
procedure TForm1.tmrVclMaximizeHackTimer(Sender: TObject);
begin
Self.WindowState := wsMaximized;
end;
后来我改进了这个技巧,在 OnShow
期间发布一条消息;这本质上与定时器消息相同,而不必使用定时器:
const
WM_MaximizeWindow = WM_APP + $03;
procedure TForm1.FormShow(Sender: TObject);
begin
if (Self.WindowState = wsMaximized) then
begin
Self.WindowState := wsNormal;
PostMessage(Self.Handle, WM_MaximizeWindow , 0, 0);
end;
end;
private
procedure WMMaximizeWindow(var Message: TMessage); message WM_MaximizeWindow;
procedure TForm1.WMMaximizeWindow(var Message: TMessage);
begin
Self.WindowState := wsMaximized;
end;
有时候我会发明一个Delphi从未有过的OnAfterShow
事件:const
WM_AfterShow = WM_APP + $02;
procedure TForm1.FormShow(Sender: TObject);
begin
PostMessage(Self.Handle, WM_AfterShow, 0, 0);
if (Self.WindowState = wsMaximized) then
begin
Self.WindowState := wsNormal;
FMaximizeNeeded := True;
end;
end;
private
procedure WMAfterShow(var Message: TMessage); message WM_AfterShow;
procedure TForm1.WMAfterShow(var Message: TMessage);
begin
if FMaximizeNeeded then
begin
FMaximizeNeeded := False;
Self.WindowState := wsMaximized;
end;
end;
但是没有黑客比黑客更好。