OnMouseEnter中的表单创建和销毁; Delphi中的OnMouseLeave事件

时间:2010-11-02 08:55:04

标签: delphi events forms dynamic controls

很抱歉,如果之前已经提出过这样的问题,但我现在没有时间去挖掘stackoverflow数据库......

所以,我有这段代码:

procedure TForm1.GraphPrevBtnMouseEnter(Sender: TObject);
var frm_PrevBtn : TForm;
begin
  GraphPrevBtn.Width := 75;
  if z = 0 then begin
    frm_PrevBtn := TForm.Create(nil);
    with frm_PrevBtn do begin
      Name := 'frm_PrevBtn';
      BorderStyle := bsNone;
      Position := poDesigned;
      Top := Form1.Top + GraphprevBtn.Top + (form1.Height - Form1.ClientHeight) - 3;
      Left := Form1.Left + GraphprevBtn.Left + 3;
      Width := GraphprevBtn.Width; Height := GraphprevBtn.Height; transparentColor := True; TransparentColorValue := clbtnFace;
      Show;
    end;
    GraphPrevBtn.Parent := frm_PrevBtn;
    if GetLastError = 0 then z := frm_prevBtn.GetHashCode;
  end;
end;

procedure TForm1.GraphPrevBtnMouseLeave(Sender: TObject);
    var frm_PrevBtn_H : THandle;
    begin
    // if form is created then- if mouse is under button then- if z = formshashcode ( form is on creatin stage )
      if not (FindVCLWindow(Mouse.CursorPos) = GraphPrevBtn) and ((FindControl(FindWindow('TForm','frm_PrevBtn')) as TForm).Visible = True) and (GraphPrevBtn.Parent = FindControl(FindWindow('TForm','frm_PrevBtn')) as TForm) then begin // if mouse is not under graphprevBtn
        ShowMessage(FindVCLWindow(Mouse.CursorPos).Name); // 
        if z = 112                                                       // then if form is created
        then begin
            GraphPrevBtn.Parent := Form1;
            GraphPrevBtn.bringtoFront;
            GraphPrevBtn.Top := 29; GraphPrevBtn.Left := 226;
            (FindControl(FindWindow('TForm','frm_PrevBtn')) as TForm).Free;
            if GetLastError = 0 then z := 0;
          end;
      end;
   end;

所以,我希望如下: 当我使用鼠标输入此GraphPrevBtn时,将创建表单。至于创造,焦点从控制到新形式。由于重点是新表单,因此会触发 OnMouseLeave 事件。当事件被触发时,它应该破坏表单,但仅在用户( 主动控件/焦点)实际上通过鼠标控制。< / p>

现在发生的事情是,任何新表单都不会被破坏 两个事件都会无限循环(* frm_PrevBtn *会被一次又一次地创建和销毁。 ..)。

什么是最好的解决方案?

我的想法是获取新的表格rect并检查鼠标是否在此矩形内。如果是,则执行allow OnMouseLeave 事件,否则取消它......它会起作用吗?

我尽量尝试这些样本:

  1. http://delphi.about.com/od/windowsshellapi/a/get-active-ctrl.htm
  2. http://delphi.about.com/od/delphitips2010/qt/is-some-delphi-tcontrol-under-the-mouse.htm

    • 没有运气。问题出在哪里......?
  3. 备注:global var z:byte;

    P.S。 感谢负面投票......将来使用此网站的动力很大......

3 个答案:

答案 0 :(得分:1)

鼠标进入'GraphPrevBtn',您在按钮上创建一个表单。一旦这个表单变得可见,因为鼠标不再是'GraphPrevBtn','OnMouseLeave'被触发。你破坏了新的表单,现在鼠标再次出现在按钮上,因此'OnMouseEnter'被触发,因此无限循环。

作为解决方案,您可以将表单处理代码移动到Form1的“OnMouseEnter”:

procedure TForm1.FormMouseEnter(Sender: TObject);
begin
  if z = 112
  then begin
    GraphPrevBtn.Parent := Form1;
    [...]


..和'GetLastError'有什么关系,看起来完全无关紧要。如果你打算使用它,至少在开始操作之前调用GetLastErrorSetLastError将最后一个错误设置为'0'。

答案 1 :(得分:1)

也许更像这样的东西可以帮到你:

var
  frm_PrevBtn : TForm = nil;

procedure TForm1.GraphPrevBtnMouseEnter(Sender: TObject); 
var
  P: TPoint;
begin 
  GraphPrevBtn.Width := 75; 
  if frm_PrevBtn = nil then begin 
    P := GraphPrevBtn.ClientOrigin;
    frm_PrevBtn := TForm.Create(nil);
    with frm_PrevBtn do begin
      BorderStyle := bsNone; 
      Position := poDesigned; 
      SetBounds(P.X, P.Y, GraphPrevBtn.Width, GraphPrevBtn.Height);
      TransparentColor := True;
      TransparentColorValue := clBtnFace; 
      GraphPrevBtn.Parent := frm_PrevBtn;
      GraphPrevBtn.Top := 0;
      GraphPrevBtn.Left := 0;
      Show; 
    end;
  end; 
end; 

procedure TForm1.GraphPrevBtnMouseLeave(Sender: TObject); 
begin 
  if (FindVCLWindow(Mouse.CursorPos) <> GraphPrevBtn) and (frm_PrevBtn <> nil) then begin
    GraphPrevBtn.Parent := Self;
    GraphPrevBtn.BringToFront; 
    GraphPrevBtn.Top := 29;
    GraphPrevBtn.Left := 226; 
    FreeAndNil(frm_PrevBtn);
  end; 
end; 

答案 2 :(得分:0)

你为什么不这样做:

  1. MainForm.OnMouseOver:创建辅助表单。
  2. SecondaryForm.OnMouseOver:设置FLAG_ON_SECONDARY。
  3. SecondaryForm.OnMouseLeave:清除FLAG_ON_SECONDARY。
  4. MainForm.OnMouseLeave:如果不是FLAG_ON_SECONDARY则销毁次要表格。
  5. 如果在MainForm.OnMouseLeave之后触发SecondaryForm.OnMouseOver,则可能无效。好吧,想想类似的东西。另一种解决方案是启动一个计时器,如果鼠标既不在Main也不在SecondaryForm上,它会销毁SecondaryForm并自行禁用。