【问题标题】:How to make a form float in a workarea as it is the screen (move, size, maximize, minimize)?如何使表单在​​工作区中浮动,因为它是屏幕(移动、调整大小、最大化、最小化)?
【发布时间】:2012-01-23 22:38:41
【问题描述】:

我尝试了 Freddie Bell 在What is the best way to make a Delphi Application completely full screen? question 上发布的代码,这正是我所需要的。

我还将最小尺寸设置为原始尺寸。

  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;所以 working_area 是面板之间的空间。主窗体没有边界,它完全最大化了工作区域

SystemParametersInfo(SPI_GETWORKAREA, 0, @working_desktop, 0);
  • 当我移动表单时,它保持在面板之间的工作区域内。
  • 当我调整表单大小时,它会保留在工作区域内。
  • 但是,当我以任何一种方式(左或右)通过工作区边缘调整表单大小时,表单将其大小增加到另一侧。即,如果表单位于左边缘,并且您选择它来调整它的大小并且向左移动(朝向边缘),则表单会向右增加其宽度(但它会停在右边缘!)。

我尝试使用一些代码(捕获 WMSIZE 或 WMSIZING),但我可以阻止这种行为吗? 提前谢谢大家!

EDIT (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.

【问题讨论】:

  • 我无法理解这个问题。
  • 对不起与我说的帖子有关。我可以发布代码(我不知道如何)。如果你看到它真的很简单,也许很难解释,而且我的英语太多了“我泰山,你简”:)。问题是当您从左边缘调整表单大小并到达左面板的边框(设置工作区域的左边界)并通过它时,不释放鼠标按钮,表单仍然调整大小但到大小合适。
  • 表单停止向左调整大小(当它达到左侧限制时),但开始向右增加宽度。
  • 您的代码的哪个方面导致了这种关闭行为?是WM_GETMINMAXINFO处理吗?
  • 我不能说。我试图抓住时刻或消息,以避免在达到任一限制时调整大小,但我能找到方法。我不熟悉 Windows 消息。

标签: forms delphi resize maximize


【解决方案1】:

WM_WINDOWPOSCHANGING 的处理程序适用于移动操作,但对于调整大小操作需要有所不同。您无法从该消息处理程序中检测到那些,因此您需要一个替代方案。而是像这样使用WM_SIZINGWM_MOVING

procedure WMSizing(Var msg: TMessage); message WM_SIZING;
procedure WMMoving(Var msg: TMessage); message WM_MOVING;

....

procedure TForm_en_ventana.WMSizing(var msg: TMessage);
var
  R: PRect;
begin
  R := PRect(msg.LParam);
  R.Left := Max(R.Left, VENTANA_DE_TRABAJO.Left);
  R.Right := Min(R.Right, VENTANA_DE_TRABAJO.Right);
  R.Top := Max(R.Top, VENTANA_DE_TRABAJO.Top);
  R.Bottom := Min(R.Bottom, VENTANA_DE_TRABAJO.Bottom);
end;

procedure TForm_en_ventana.WMMoving(var msg: TMessage);
var
  R: PRect;
  dx, dy: Integer;
begin
  R := PRect(msg.LParam);
  dx := 0;
  dy := 0;
  if R.Left<VENTANA_DE_TRABAJO.Left then
    dx := VENTANA_DE_TRABAJO.Left-R.Left;
  if R.Right>VENTANA_DE_TRABAJO.Right then
    dx := VENTANA_DE_TRABAJO.Right-R.Right;
  if R.Top<VENTANA_DE_TRABAJO.Top then
    dy := VENTANA_DE_TRABAJO.Top-R.Top;
  if R.Bottom>VENTANA_DE_TRABAJO.Bottom then
    dy := VENTANA_DE_TRABAJO.Bottom-R.Bottom;
  OffsetRect(R^, dx, dy);
end;

您需要完全删除 WM_WINDOWPOSCHANGING

【讨论】:

  • 我只将此代码添加到 WMSHOWWINDOW 消息procedure TForm_en_ventana.WMShowWindow(var Message: TWMShowWindow); begin ancho_original := Self.Width; alto_original := Self.Height; Constraints.MinHeight := height; Constraints.MinWidth := width; end;
  • 我不知道你的评论是什么意思。你在问另一个问题吗?
  • 不,对不起!!!只是为看到这个问题的人完成代码(对我来说,这个问题已经结束并得到了回答)。在 WMShowWindow 中,我通过设置表单的约束来设置最小尺寸。再次感谢!!!
猜你喜欢
  • 2011-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-27
  • 2013-02-05
  • 2014-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多