【问题标题】:What is the best way to handle OnResize in FMX?在 FMX 中处理 OnResize 的最佳方法是什么?
【发布时间】:2014-03-04 19:59:47
【问题描述】:

当调整窗口大小时,我想在调整大小完成后处理 OnResize 事件,因为更新图形需要几秒钟。这很棘手,因为调整窗口大小会产生大量调整大小事件。由于更新窗口需要一段时间,我不希望每个事件都更新窗口。我尝试检测鼠标向上以将其标记为完成调整大小但从未检测到鼠标向上的事件。

TLama 有一个nice solution,但唉,那是 VCL,我需要它用于 Firemonkey。对 FMX 有什么建议吗?

【问题讨论】:

    标签: delphi resize delphi-xe5 firemonkey-fm3


    【解决方案1】:

    类似于Debounce() or Throttle() function in Underscore.js 的东西呢?这两个函数都提供了限制过程执行频率的方法。

    【讨论】:

      【解决方案2】:

      这是在 Windows 上的 FMX 中处理它的一种方法,您需要将表单更改为从 TResizeForm 继承并分配 OnResizeEnd 属性。不是很干净,因为它依赖于 FMX 内部,但应该可以工作。

      unit UResizeForm;
      
      interface
      
      uses
        Winapi.Windows,
        System.SysUtils, System.Classes,
        FMX.Types, FMX.Forms, FMX.Platform.Win;
      
      type
        TResizeForm = class(TForm)
        strict private
          class var FHook: HHook;
        strict private
          FOnResizeEnd: TNotifyEvent;
        public
          property OnResizeEnd: TNotifyEvent read FOnResizeEnd write FOnResizeEnd;
          class constructor Create;
          class destructor Destroy;
        end;
      
      implementation
      
      uses Winapi.Messages;
      
      var
        WindowAtom: TAtom;
      
      function Hook(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT stdcall;
      var
        cwp: PCWPSTRUCT;
        Form: TForm;
        ResizeForm: TResizeForm;
      begin
        try
          cwp := PCWPSTRUCT(lparam);
          if cwp.message = WM_EXITSIZEMOVE then
          begin
            if WindowAtom <> 0 then
            begin
              Form := TForm(GetProp(cwp.hwnd, MakeIntAtom(WindowAtom)));
              if Form is TResizeForm then
              begin
                ResizeForm := Form as TResizeForm;
                if Assigned(ResizeForm.OnResizeEnd) then
                begin
                  ResizeForm.OnResizeEnd(ResizeForm);
                end;
              end;
            end;
          end;
        except
          // eat exception
        end;
        Result := CallNextHookEx(0, code, wparam, lparam);
      end;
      
      class constructor TResizeForm.Create;
      var
        WindowAtomString: string;
      begin
        WindowAtomString := Format('FIREMONKEY%.8X', [GetCurrentProcessID]);
        WindowAtom := GlobalFindAtom(PChar(WindowAtomString));
        FHook := SetWindowsHookEx(WH_CALLWNDPROC, Hook, 0, GetCurrentThreadId);
      end;
      
      class destructor TResizeForm.Destroy;
      begin
        UnhookWindowsHookEx(FHook);
      end;
      
      end.
      

      【讨论】:

        【解决方案3】:

        作为一种解决方法,将TTimer 添加到表单中,将其初始状态设置为禁用,并将Interval 属性设置为100 ms。为了尽量减少您的应用程序对OnResize 事件做出反应的次数,请使用以下代码:

        procedure TForm1.FormResize(Sender: TObject);
        begin
            with ResizeTimer do
            begin
                Enabled := false;
                Enabled := true;
            end;
        end;
        
        procedure TForm1.ResizeTimerTimer(Sender: TObject);
        begin
            ResizeTimer.Enabled := false;
        
            // Do stuff after resize
        end;
        

        最小的延迟应该不会被用户注意到。

        【讨论】:

          猜你喜欢
          • 2010-09-06
          • 2011-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-15
          • 2011-04-29
          相关资源
          最近更新 更多