Создание и уничтожение форм в OnMouseEnter; События OnMouseLeave в Дельфи - PullRequest
0 голосов
/ 02 ноября 2010

Извините, если такой вопрос уже был сделан ранее, но у меня нет времени копаться в stackoverflow db ...

Итак, у меня есть этот код:

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 происходит. Когда событие запускается, оно должно уничтожить форму, НО ТОЛЬКО ЕСЛИ пользователь ( НЕ активный контроль / фокусировка ) фактически оставляет управление мышью.

Что происходит сейчас, так это то, что либо новые формы вообще не уничтожаются или оба события идут бесконечным циклом (* frm_PrevBtn * создается и уничтожается снова и снова и снова ... ).

Какое будет лучшее решение?

Моя идея состоит в том, чтобы получить новые формы прямоугольника и проверять, когда мышь находится внутри этого прямоугольника. Если это так, выполните событие 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

    • Не повезло. Где проблема ...?

Замечания: глобальный var z: byte;

P.S. Спасибо за отрицательные голоса ... отличная мотивация для использования этого сайта в будущем ...

Ответы [ 3 ]

1 голос
/ 02 ноября 2010

Мышь входит в 'GraphPrevBtn', вы создаете форму поверх кнопки.Как только эта форма становится видимой, так как мышь больше не находится над GraphPrevBtn, запускается OnMouseLeave.Вы уничтожаете новую форму, и теперь мышь снова находится на кнопке, поэтому запускается OnMouseEnter, что приводит к бесконечному циклу.

В качестве решения вы можете переместить код, содержащий форму, в OnMouseEnter формы Form1:

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

... а что с 'GetLastError', это кажется совершенно неактуальным.Если вы собираетесь его использовать, по крайней мере установите последнюю ошибку на «0», вызвав GetLastError или SetLastError перед началом вашей операции.

1 голос
/ 02 ноября 2010

Может быть, что-то еще поможет вам:

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; 
0 голосов
/ 02 ноября 2010

Почему бы вам не сделать это следующим образом:

  1. MainForm.OnMouseOver: создать дополнительную форму.
  2. SecondaryForm.OnMouseOver: установить FLAG_ON_SECONDARY.
  3. SecondaryForm.OnMouseLeave: Очистить FLAG_ON_SECONDARY.
  4. MainForm.OnMouseLeave: если не FLAG_ON_SECONDARY, то уничтожить вторичную форму.

Это может не сработать в случае, если SecondaryForm.OnMouseOave срабатывает после MainForm.Ну, придумайте что-нибудь подобное.Другое решение состоит в том, чтобы запустить таймер, который уничтожает SecondaryForm и отключает себя, если мышь не находится ни на Main, ни на SecondaryForm.

...