How to temporarily stop a control from being paint?

后端 未结 4 2222
伪装坚强ぢ
伪装坚强ぢ 2021-02-09 01:43

We have a win control object which moves its clients to some other coordiantes. The problem is, when there are too many children - for example 500 controls - the code is really

4条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-02-09 02:30

    As Cosmin Prund explains, the cause for the long duration is not an effect of repainting but of VCL's realignment requisites at control movement. (If it really should take as long as it does, then you might even need to request immediate repaints).

    To temporarily prevent realignment and all checks and work for anchors, align settings and Z-order, use DisableAlign and EnableAlign. And halve the count of calls to SetBounds by called it directly:

    procedure TForm1.FormCreate(Sender: TObject);
    var
      I: Integer;
      Control: TControl;
    begin
      for I := 0 to 499 do
      begin
        Control := TButton.Create(Self);
        Control.SetBounds((I mod 10) * 40, (I div 10) * 20, 40, 20);
        Control.Parent := Panel1;
      end;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var
      I: Integer;
      C: TControl;
    begin
      // Disable Panel1 paint
      SendMessage(Panel1.Handle, WM_SETREDRAW, Integer(False), 0);  
      Panel1.DisableAlign;
      try
        for I := 0 to Panel1.ControlCount - 1 do
        begin
          C := Panel1.Controls[I];
          C.SetBounds(C.Left + 10, C.Top + 5, C.Width, C.Height);
        end;
      finally
        Panel1.EnableAlign;
        // Enable Panel1 paint  
        SendMessage(Panel1.Handle, WM_SETREDRAW, Integer(True), 0);
        // Update client area   
        RedrawWindow(Panel1.Handle, nil, 0, RDW_INVALIDATE or RDW_UPDATENOW or RDW_ALLCHILDREN); 
      end;
    end;
    

提交回复
热议问题