如何使表单像屏幕一样浮动在工作区中(移动、调整大小、最大化、最小化)?
我尝试 Freddie Bell 在 What is the best way to make a Delphi Application full screen? 问题上发布的代码,如下所示我需要什么。
我还将最小尺寸设置为原始尺寸。
with msg.MinMaxInfo^.ptMinTrackSize do
begin
// maximum size when maximised
x := original_width;
y := original_height;
end;
在 Form OnShow 事件中:
original_width := Width;
original_height := Height;
但我有这个问题: - Mainform有两个面板,其中一个对齐为alRight,另一个对齐为alLeft;所以工作区域是面板之间的空间。 Mainform 没有边框,它完全最大化到工作区域,
SystemParametersInfo(SPI_GETWORKAREA, 0, @working_desktop, 0);
- 当我移动表单时,它保持在面板之间的工作区域内。
- 当我调整表单大小时,它保留在该工作区域内。
- 但是,当我以任一方式(左或右)通过工作区域的边缘调整表单大小时,表单将其大小增加到另一侧。即,如果表单位于左边缘,并且您选择它来调整其大小并向左移动(朝向边缘),则表单会向右增加其宽度(但它会停在右边缘!)。
我尝试使用一些代码(捕获 WMSIZE 或 WMSIZING),但我可以阻止这种行为吗? 提前谢谢大家!
编辑(David Heffernan):关键代码似乎在这个单元中。
unit uFormularios;
interface
uses Windows, Messages, Forms, DBGrids, StdCtrls, Menus, Graphics, ComCtrls;
type
TForm_en_ventana = class(TForm)
private
ancho_original, alto_original: integer;
procedure WMShowWindow(var Message: TWMShowWindow); message WM_SHOWWINDOW;
procedure WMWindowPosChanging(Var Msg: TWMWindowPosChanging); Message WM_WINDOWPOSCHANGING;
procedure WMGetMinMaxInfo(Var msg: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
end;
TForm_en_ventana_centrado = class(TForm_en_ventana)
private
ancho_original, alto_original: integer;
procedure WMShowWindow(var Message: TWMShowWindow); message WM_SHOWWINDOW;
end;
procedure MaximizarFormulario(var F; MaximaAltura: integer = 0; MaximoAncho: integer = 0; Centrado: boolean = TRUE);
procedure InicializarVentanaTrabajo(const izq, der, arr, aba: integer);
var ESPACIO_DE_TRABAJO,
VENTANA_DE_TRABAJO : TRect;
implementation
procedure MaximizarFormulario(var F; MaximaAltura: integer = 0; MaximoAncho: integer = 0; Centrado: boolean = TRUE);
begin
LockWindowUpdate(TForm(F).Handle);
TForm(F).Left := ESPACIO_DE_TRABAJO.Left;
if MaximoAncho = 0 then
TForm(F).Width := ESPACIO_DE_TRABAJO.Right
else
begin
if ESPACIO_DE_TRABAJO.Right < MaximoAncho then
TForm(F).Width := ESPACIO_DE_TRABAJO.Right
else
TForm(F).Width := MaximoAncho;
end;
TForm(F).Top := ESPACIO_DE_TRABAJO.Top;
if MaximaAltura = 0 then
TForm(F).Height := ESPACIO_DE_TRABAJO.Bottom
else
begin
if ESPACIO_DE_TRABAJO.Bottom < MaximaAltura then
TForm(F).Height := ESPACIO_DE_TRABAJO.Bottom
else
TForm(F).Height := MaximaAltura;
end;
if ((MaximoAncho <> 0) or (MaximaAltura <> 0)) and (Centrado) then
begin
TForm(F).Left := (ESPACIO_DE_TRABAJO.Right - TForm(F).Width ) div 2;
TForm(F).Top := (ESPACIO_DE_TRABAJO.Bottom - TForm(F).Height) div 2;
end;
LockWindowUpdate(0);
end;
procedure InicializarVentanaTrabajo(const izq, der, arr, aba: integer);
begin
VENTANA_DE_TRABAJO.Left := izq;
VENTANA_DE_TRABAJO.Right := der;
VENTANA_DE_TRABAJO.Top := arr;
VENTANA_DE_TRABAJO.Bottom := aba;
end;
procedure TForm_en_ventana.WMWindowPosChanging(var Msg: TWMWINDOWPOSCHANGING);
begin
with Msg.WindowPos^ do
{
x: int; The position of the left edge of the window.
y: int; The position of the top edge of the window.
cx: int; The window width, in pixels.
cy: int; The window height, in pixels.
}
begin
if x <= VENTANA_DE_TRABAJO.Left then
x := VENTANA_DE_TRABAJO.Left;
if x + cx >= VENTANA_DE_TRABAJO.Right then
x := (VENTANA_DE_TRABAJO.Right) - cx;
if y <= VENTANA_DE_TRABAJO.Top then
y := VENTANA_DE_TRABAJO.Top;
if y + cy >= VENTANA_DE_TRABAJO.Bottom then
y := (VENTANA_DE_TRABAJO.Bottom) - cy;
end;
end;
Procedure TForm_en_ventana.WMGetMinMaxInfo(Var msg: TWMGetMinMaxInfo);
begin
inherited;
with msg.MinMaxInfo^.ptMaxPosition do
begin
// position of top when maximised
x := VENTANA_DE_TRABAJO.Left;
y := VENTANA_DE_TRABAJO.Top;
end;
with msg.MinMaxInfo^.ptMaxSize do
begin
// width and height when maximized
x := VENTANA_DE_TRABAJO.Right - VENTANA_DE_TRABAJO.Left;
y := VENTANA_DE_TRABAJO.Bottom - VENTANA_DE_TRABAJO.Top;
end;
with msg.MinMaxInfo^.ptMaxTrackSize do
begin
// maximum size when maximised
x := VENTANA_DE_TRABAJO.Right - VENTANA_DE_TRABAJO.Left;
y := VENTANA_DE_TRABAJO.Bottom - VENTANA_DE_TRABAJO.Top;
end;
with msg.MinMaxInfo^.ptMinTrackSize do
begin
// maximum size when maximised
x := ancho_original;
y := alto_original;
end;
end;
procedure TForm_en_ventana.WMSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType and $FFF0 = SC_MINIMIZE then
Application.Minimize
else
inherited;
end;
procedure TForm_en_ventana.WMShowWindow(var Message: TWMShowWindow);
begin
ancho_original := Width;
alto_original := Height;
end;
procedure TForm_en_ventana_centrado.WMShowWindow(var Message: TWMShowWindow);
begin
ancho_original := Width;
alto_original := Height;
Left := (((VENTANA_DE_TRABAJO.Right - VENTANA_DE_TRABAJO.Left) - Width) div 2) + VENTANA_DE_TRABAJO.Left;
Top := (((VENTANA_DE_TRABAJO.Bottom - VENTANA_DE_TRABAJO.Top) - Height) div 2) + VENTANA_DE_TRABAJO.Top;
end;
initialization
SystemParametersInfo(SPI_GETWORKAREA, 0, @ESPACIO_DE_TRABAJO, 0);
VENTANA_DE_TRABAJO := ESPACIO_DE_TRABAJO;
end.
I try code published by Freddie Bell at What is the best way to make a Delphi Application completely full screen? question, as is what i needed.
I also set minimun size to be the original size.
with msg.MinMaxInfo^.ptMinTrackSize do
begin
// maximum size when maximised
x := original_width;
y := original_height;
end;
And in Form OnShow event:
original_width := Width;
original_height := Height;
But i have this issue:
- Mainform has two panels, one of it is aligned as alRight, the other as alLeft; so the working_area is the space between the panels. Mainform has no borders and it is fully maximizad to the work area with
SystemParametersInfo(SPI_GETWORKAREA, 0, @working_desktop, 0);
- When i move the form, it keeps inside the working_area between the panels.
- When i size the form, it keeps inside that working_area.
- But, when i size the form in either way (left or right) passing the edge of the working_area, the form increased its size to the other side. i.e., if the form is on left edge, and you select it to resize it and you move to the left (towards the edge), the form increase its width to the right (but it stop at right edge!).
I try with some code (catching WMSIZE or WMSIZING), but i can prevent that behavior?
Thanks you all in advance!
EDIT (David Heffernan): The key code appears to be in this unit.
unit uFormularios;
interface
uses Windows, Messages, Forms, DBGrids, StdCtrls, Menus, Graphics, ComCtrls;
type
TForm_en_ventana = class(TForm)
private
ancho_original, alto_original: integer;
procedure WMShowWindow(var Message: TWMShowWindow); message WM_SHOWWINDOW;
procedure WMWindowPosChanging(Var Msg: TWMWindowPosChanging); Message WM_WINDOWPOSCHANGING;
procedure WMGetMinMaxInfo(Var msg: TWMGetMinMaxInfo); message WM_GETMINMAXINFO;
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
end;
TForm_en_ventana_centrado = class(TForm_en_ventana)
private
ancho_original, alto_original: integer;
procedure WMShowWindow(var Message: TWMShowWindow); message WM_SHOWWINDOW;
end;
procedure MaximizarFormulario(var F; MaximaAltura: integer = 0; MaximoAncho: integer = 0; Centrado: boolean = TRUE);
procedure InicializarVentanaTrabajo(const izq, der, arr, aba: integer);
var ESPACIO_DE_TRABAJO,
VENTANA_DE_TRABAJO : TRect;
implementation
procedure MaximizarFormulario(var F; MaximaAltura: integer = 0; MaximoAncho: integer = 0; Centrado: boolean = TRUE);
begin
LockWindowUpdate(TForm(F).Handle);
TForm(F).Left := ESPACIO_DE_TRABAJO.Left;
if MaximoAncho = 0 then
TForm(F).Width := ESPACIO_DE_TRABAJO.Right
else
begin
if ESPACIO_DE_TRABAJO.Right < MaximoAncho then
TForm(F).Width := ESPACIO_DE_TRABAJO.Right
else
TForm(F).Width := MaximoAncho;
end;
TForm(F).Top := ESPACIO_DE_TRABAJO.Top;
if MaximaAltura = 0 then
TForm(F).Height := ESPACIO_DE_TRABAJO.Bottom
else
begin
if ESPACIO_DE_TRABAJO.Bottom < MaximaAltura then
TForm(F).Height := ESPACIO_DE_TRABAJO.Bottom
else
TForm(F).Height := MaximaAltura;
end;
if ((MaximoAncho <> 0) or (MaximaAltura <> 0)) and (Centrado) then
begin
TForm(F).Left := (ESPACIO_DE_TRABAJO.Right - TForm(F).Width ) div 2;
TForm(F).Top := (ESPACIO_DE_TRABAJO.Bottom - TForm(F).Height) div 2;
end;
LockWindowUpdate(0);
end;
procedure InicializarVentanaTrabajo(const izq, der, arr, aba: integer);
begin
VENTANA_DE_TRABAJO.Left := izq;
VENTANA_DE_TRABAJO.Right := der;
VENTANA_DE_TRABAJO.Top := arr;
VENTANA_DE_TRABAJO.Bottom := aba;
end;
procedure TForm_en_ventana.WMWindowPosChanging(var Msg: TWMWINDOWPOSCHANGING);
begin
with Msg.WindowPos^ do
{
x: int; The position of the left edge of the window.
y: int; The position of the top edge of the window.
cx: int; The window width, in pixels.
cy: int; The window height, in pixels.
}
begin
if x <= VENTANA_DE_TRABAJO.Left then
x := VENTANA_DE_TRABAJO.Left;
if x + cx >= VENTANA_DE_TRABAJO.Right then
x := (VENTANA_DE_TRABAJO.Right) - cx;
if y <= VENTANA_DE_TRABAJO.Top then
y := VENTANA_DE_TRABAJO.Top;
if y + cy >= VENTANA_DE_TRABAJO.Bottom then
y := (VENTANA_DE_TRABAJO.Bottom) - cy;
end;
end;
Procedure TForm_en_ventana.WMGetMinMaxInfo(Var msg: TWMGetMinMaxInfo);
begin
inherited;
with msg.MinMaxInfo^.ptMaxPosition do
begin
// position of top when maximised
x := VENTANA_DE_TRABAJO.Left;
y := VENTANA_DE_TRABAJO.Top;
end;
with msg.MinMaxInfo^.ptMaxSize do
begin
// width and height when maximized
x := VENTANA_DE_TRABAJO.Right - VENTANA_DE_TRABAJO.Left;
y := VENTANA_DE_TRABAJO.Bottom - VENTANA_DE_TRABAJO.Top;
end;
with msg.MinMaxInfo^.ptMaxTrackSize do
begin
// maximum size when maximised
x := VENTANA_DE_TRABAJO.Right - VENTANA_DE_TRABAJO.Left;
y := VENTANA_DE_TRABAJO.Bottom - VENTANA_DE_TRABAJO.Top;
end;
with msg.MinMaxInfo^.ptMinTrackSize do
begin
// maximum size when maximised
x := ancho_original;
y := alto_original;
end;
end;
procedure TForm_en_ventana.WMSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType and $FFF0 = SC_MINIMIZE then
Application.Minimize
else
inherited;
end;
procedure TForm_en_ventana.WMShowWindow(var Message: TWMShowWindow);
begin
ancho_original := Width;
alto_original := Height;
end;
procedure TForm_en_ventana_centrado.WMShowWindow(var Message: TWMShowWindow);
begin
ancho_original := Width;
alto_original := Height;
Left := (((VENTANA_DE_TRABAJO.Right - VENTANA_DE_TRABAJO.Left) - Width) div 2) + VENTANA_DE_TRABAJO.Left;
Top := (((VENTANA_DE_TRABAJO.Bottom - VENTANA_DE_TRABAJO.Top) - Height) div 2) + VENTANA_DE_TRABAJO.Top;
end;
initialization
SystemParametersInfo(SPI_GETWORKAREA, 0, @ESPACIO_DE_TRABAJO, 0);
VENTANA_DE_TRABAJO := ESPACIO_DE_TRABAJO;
end.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
WM_WINDOWPOSCHANGING
的处理程序适用于移动操作,但对于大小调整操作需要有所不同。您无法从该消息处理程序中检测到这些内容,因此您需要替代方案。相反,请像这样使用WM_SIZING
和WM_MOVING
:您需要完全删除
WM_WINDOWPOSCHANGING
。Your handler for
WM_WINDOWPOSCHANGING
is fine for moving operations but needs to be different for sizing operations. You can't detect those from within that message handler so you need an alternative. Instead useWM_SIZING
andWM_MOVING
like this:You will need to remove the
WM_WINDOWPOSCHANGING
altogether.