Delphi XE2: событие OnHideHint для автоматического восстановления предыдущего текста в строке состояния?

TAction имеет событие OnHint, но, к сожалению, не событие OnHideHint. У этого есть следующий недостаток: у меня есть ToolButtons и другие элементы управления, связанные с действиями. Всякий раз, когда мышь находится над таким элементом управления, в строке состояния отображается подсказка о действии; (Я установил для свойства AutoHint StatusBar значение True). Но когда мышь покидает ToolButton, предыдущий пользовательский текст в StatusBar (который не из подсказки) НЕ восстанавливается автоматически! Теперь я мог бы написать обработчик события OnMouseLeave для каждого элемента управления в форме, чтобы восстановить свой пользовательский текст в строке состояния, но это было бы громоздко! Нет ли чего-то, что автоматически восстанавливает предыдущий текст в строке состояния? Событие OnHideHint в TAction было бы идеальным!


person user1580348    schedule 10.06.2013    source источник


Ответы (2)


Это поведение по умолчанию. Когда AutoHint имеет значение True, строка состояния автоматически реагирует на действия подсказки, отображая длинную версию текста подсказки на первой панели.

Проблема, с которой вы столкнулись, заключается в том, что когда вы покидаете элемент управления с помощью мыши, вы в основном входите в другое окно, это родительский элемент управления. И поскольку этому родителю не назначено строковое значение Hint, действие HintAction обновляется до пустой строки.

Если вы хотите вернуть значение по умолчанию, когда подсказка не отображается, добавьте TApplicationEvents в форме и используйте событие TApplication.OnHint следующим образом:

var
  OriginalPanelText : String = 'BLA';

procedure TForm1.ApplicationEvents1Hint(Sender: TObject);
begin

   if StatusBar1.SimplePanel or (StatusBar1.Panels.Count = 0)
  then
    if Application.Hint <> ''
    then
       StatusBar1.SimpleText := Application.Hint
    else
       StatusBar1.SimpleText := OriginalPanelText
  else
    if Application.Hint <> ''
    then
      StatusBar1.Panels[0].Text := Application.Hint
    else
      StatusBar1.Panels[0].Text := OriginalPanelText;

end;
person Peter    schedule 10.06.2013

Вся магия AutoHint происходит в TStatusBar.ExecuteAction. Когда подсказка перестает показывать этот код, текст строки состояния становится пустым. Вы можете изменить поведение следующим образом:

type
  TStatusBar = class(ComCtrls.TStatusBar)
  private
    FRestoreTextAfterHintAction: string;
  public
    function ExecuteAction(Action: TBasicAction): Boolean; override;
  end;

function TStatusBar.ExecuteAction(Action: TBasicAction): Boolean;
var
  HintText: string;
begin
  if AutoHint and not (csDesigning in ComponentState) and
     (Action is THintAction) and not DoHint then begin
    HintText := THintAction(Action).Hint;
    if SimplePanel or (Panels.Count=0) then begin
      if HintText='' then begin
        SimpleText := FRestoreTextAfterHintAction;
      end else begin
        FRestoreTextAfterHintAction := SimpleText;
        SimpleText := HintText;
      end;
    end else begin
      if HintText='' then begin
        Panels[0].Text := FRestoreTextAfterHintAction;
      end else begin
        FRestoreTextAfterHintAction := Panels[0].Text;
        Panels[0].Text := HintText;
      end;
    end;
    Result := True;
  end else begin
    Result := inherited ExecuteAction(Action);
  end;
end;

Я использовал довольно грубый класс интерпозера и хрупкую переменную экземпляра для хранения восстанавливаемого текста. Вы можете начать это, чтобы быть немного более надежным, если хотите. Приведенный выше код, по крайней мере, показывает вам место, где вам нужно добавить свои хуки.

person David Heffernan    schedule 11.06.2013
comment
Хотел объяснить, но вы удалили его, прежде чем я смог оставить комментарий. Это первый раз, когда я проголосовал за один из ваших ответов, и по уважительной причине я не считаю, что необходимо преодолевать трудности с использованием классов вставок и изменением функции, когда вы можете сделать это гораздо более простым способом, почему начать взламывать его, когда явно уже реализован способ обойти это? И я не знаю, почему вы опубликовали сообщение через 12 часов после меня, я ясно объяснил, почему это происходит, и предложил хорошее решение, а потом пошли на хуй со мной. - person Peter; 11.06.2013
comment
@Peter Это просто другой способ сделать это. Инкапсуляция поведения в элементе управления позволяет избежать добавления обработчиков Application.OnHint. Какое отношение к этому имеет существование 12-часового ответа? Я думаю, вам нужно немного расслабиться здесь. Никто не собирается с тобой шутить. Это просто ТАК ответ ради бога! - person David Heffernan; 11.06.2013
comment
@PeterVonča Я не против отрицательного голоса. В любом случае, это стоит вам репутации! ;-) - person David Heffernan; 11.06.2013
comment
Спасибо обоим за хорошие идеи! Мне нравится простота решения Питера Вонча и ООП-подход решения Дэвида Хеффернана. Поскольку ситуация в моем коде довольно сложная, я фактически использую модификацию смеси идей в обоих решениях. Спасибо - ТАК правила! - person user1580348; 13.06.2013