Delphi避免在调整大小时没有边框从右边距和下边距闪烁的形式

时间:2015-10-02 13:30:50

标签: delphi resize flicker

我已经完成了我的工作,但是当我想要从左边距或底部边距重新调整我的表格(在BorderStyle属性中有bsNone)时,我得到了这个闪烁的问题,请先尝试这个例子(完整代码里面):
My Example =>

最后这里是代码:

const
  // frame Width
  BORDER_WIDTH = 5;
  // Key performance indicators (top-left, top-right ...)
  EDGE_SIZE = 15;    
var
  Form1: TForm1;    
implementation    
{$R *.dfm} 
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  fRect: TRect;
  fPos: TPoint;
  fChangedCursor: Boolean;
begin
  // Change cursor when the mouse pointer is located on the edge    
  fChangedCursor := False;
  fPos := Point(X, Y);    
  // top margin
  fRect := Rect(EDGE_SIZE, 0, Width - EDGE_SIZE, BORDER_WIDTH);
  if PtInRect(fRect, fPos) then
  begin
    fChangedCursor := True;
    Cursor := crSizeNS;
    if ssLeft in Shift then
    begin
    // here the bottom Margin flickering
      ReleaseCapture;
      PerForm(WM_SysCommand, $F003, 0);
    end;
  end;    
  // right margin
  fRect := Rect(Width - BORDER_WIDTH, EDGE_SIZE, Width, Height - EDGE_SIZE);
  if PtInRect(fRect, fPos) then
  begin
    fChangedCursor := True;
    Cursor := crSizeWE;
    if ssLeft in Shift then
    begin
      ReleaseCapture;
      PerForm(WM_SysCommand, $F002, 0);
    end;
  end;    
  // Bottom margin
  fRect := Rect(EDGE_SIZE, Height - BORDER_WIDTH, Width - EDGE_SIZE,    Height);
  if PtInRect(fRect, fPos) then
  begin
    fChangedCursor := True;
    Cursor := crSizeNS;
    if ssLeft in Shift then
    begin
      ReleaseCapture;
      PerForm(WM_SysCommand, $F006, 0);
    end;
  end;    
  // left margin
  fRect := Rect(0, EDGE_SIZE, BORDER_WIDTH, Height - EDGE_SIZE);
  if PtInRect(fRect, fPos) then
  begin
    fChangedCursor := True;
    Cursor := crSizeWE;
    if ssLeft in Shift then
    begin
    // here the Right Margin flickering
      ReleaseCapture;
      PerForm(WM_SysCommand, $F001, 0);
    end;
  end;    
  // Top left corner
  fRect := Rect(0, 0, EDGE_SIZE, EDGE_SIZE);
  if PtInRect(fRect, fPos) then
  begin
    fChangedCursor := True;
    Cursor := crSizeNWSE;
    if ssLeft in Shift then
    begin
      // here the Both Margins flickering
      ReleaseCapture;
      PerForm(WM_SysCommand, $F004, 0);
    end;
  end;    
  // Top right corner
  fRect := Rect(Width - EDGE_SIZE, 0, Width, EDGE_SIZE);
  if PtInRect(fRect, fPos) then
  begin
    fChangedCursor := True;
    Cursor := crSizeNESW;
    if ssLeft in Shift then
    begin
      // here the both Margins flickering
      ReleaseCapture;
      PerForm(WM_SysCommand, $F005, 0);
    end;
  end;    
// Bottom right corner
  fRect := Rect(Width - EDGE_SIZE, Height - EDGE_SIZE, Width, Height);
  if PtInRect(fRect, fPos) then
  begin
    fChangedCursor := True;
    Cursor := crSizeNWSE;
    if ssLeft in Shift then
    begin
    // here the both Margins flickering a Little
      ReleaseCapture;
      PerForm(WM_SysCommand, $F008, 0);
    end;
  end;    
  // Bottom left corner
  fRect := Rect(0, Height - EDGE_SIZE, EDGE_SIZE, Height);
  if PtInRect(fRect, fPos) then
  begin
    fChangedCursor := True;
    Cursor := crSizeNESW;
    if ssLeft in Shift then
    begin
    // here the Right Margin flickering
      ReleaseCapture;
      PerForm(WM_SysCommand, $F007, 0);
    end;
  end;    
  // Standardcursor    
 if not fChangedCursor then
    Cursor := crDefault;
end;

1 个答案:

答案 0 :(得分:0)

我不确定您遇到的闪烁原因是什么,但是您检测鼠标是否在边缘的代码有点缺陷。

我认为您的代码的主要问题是您指定的矩形彼此重叠。

所以当鼠标光标放在让我们说Top Left corner时,Top borderLeft borderTop Left角的代码就会执行。

这会导致连续三次调用ReleaseCapturePerForm(WM_SysCommand, ...)

所以我的第一个建议是更改边界检测代码,以防止同时调用多个单独边框的代码。

以下是我在其中一个项目中使用的边界检测代码的简化示例:

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var LeftEdge,RightEdge,TopEdge,BottomEdge: Boolean;
    BorderPosition: TBorderPos;
    BorderWidth: Integer;
begin
  BorderWidth := 20;
  LeftEdge := False;
  RightEdge := False;
  TopEdge := False;
  BottomEdge := False;
  //Check if mouse cursor is on left or right edge
  if X < BorderWidth then
  begin
    LeftEdge := True;
  end
  else if X > Self.Width-BorderWidth then
  begin
    RightEdge := True;
  end;

  //Check if mouse cursor is on top or bottom edge
  if Y < BorderWidth then
  begin
    TopEdge := True;
  end
  else if Y > Self.Height-BorderWidth then
  begin
    BottomEdge := True;
  end;

  //Get border position by using if..else if..else clause in order for if block
  //to break as soon as one of the conditions is met
  //First check for corners
  if TopEdge and LeftEdge then BorderPosition := bpTopLeft
  else if TopEdge and RightEdge then BorderPosition := bpTopRight
  else if BottomEdge and LeftEdge then BorderPosition := bpBottomLeft
  else if BottomEdge and RightEdge then BorderPosition := bpBottomRight
  //and only then check for individual edges
  else if TopEdge then BorderPosition := bpTop
  else if BottomEdge then BorderPosition := bpBottom
  else if LeftEdge then BorderPosition := bpLeft
  else if RightEdge then BorderPosition := bpRight
  //mouse cursor is not on any border edge
  else BorderPosition := bpNone;

  //Finally you can use case statement to execute needed code based on which
  //border edge is your mouse cursor positioned
  case BorderPosition of
    bpNone: Label1.Caption := 'Not on border';
    bpLeft: Label1.Caption := 'Left border';
    bpRight: Label1.Caption := 'Right border';
    bpTop: Label1.Caption := 'Top border';
    bpBottom: Label1.Caption := 'Bottom border';
    bpTopLeft: Label1.Caption := 'Top Left corner';
    bpTopRight: Label1.Caption := 'Top Right corner';
    bpBottomLeft: Label1.Caption := 'Bottom Left corner';
    bpBottomRight: Label1.Caption := 'Bottom Right corner';
  end;
end;

如果需要,您甚至可以用四个变量(每个变量用于自己的边缘)替换当前的BorderWidth变量。

如果没有别的,我的代码应该会为你提供更好的性能,因为它可以避免像你的代码一样在矩形上检查点位置八次。