3

我正在我的 Delphi 2009 应用程序中实现上下文相关帮助。除了在一种情况下,它工作正常。我无法确定我在主菜单中,以及打开了哪个菜单项。

我想要做的是,如果用户打开了文件菜单并且在打开时按下 F1,那么我将在文件菜单上显示我的帮助。如果他们打开“编辑”菜单并按 F1,那么我将在“编辑”菜单等上显示我的帮助。

我正在使用 ApplicationEventsHelp 来处理用户按下 F1,如下所示:

function MainForm.ApplicationEvents1Help(Command: Word; Data: Integer;
  var CallHelp: Boolean): Boolean;
begin
  if Command = HELP_COMMAND then begin
    Application.HelpSystem.ShowTopicHelp(PChar(Data), Application.CurrentHelpFile);
    CallHelp := false;
  end;
  Result := true;
end;

正如我所提到的,这适用于除主菜单之外的所有内容。我试过使用

FindVCLWindow(Mouse.CursorPos)

和其他识别活动控件的方法,看看他们是否会识别菜单,但他们似乎没有。

有没有办法告诉按下 F1 键时打开了哪个菜单项(如果有)?


谢谢大家的帮助和好主意。

只是为了记录我的最终解决方案,我发现系统并不是特别擅长找出它所在的控件,有时会出错并将不正确的数据传递给 ApplicationEventsHelp,这会显示一个不适当的帮助页面。

在尝试并使用解决方案来处理已接受答案中的菜单后,我发现最好确定我所在的控件以显示正确的帮助项。我最终甚至没有使用 HelpKeyword 属性,而是对其进行了硬编码。代码很清晰,并且可以正常工作。我的 RVEdit 窗口也有我的帮助,它会根据您所在的文档部分显示不同的帮助页面(我的 CurCursorID 告诉我)。

对于任何想像我一样这样做的人,这里是如何:

function TLogoAppForm.ApplicationEvents1Help(Command: Word; Data: Integer;
  var CallHelp: Boolean): Boolean;
var
  HelpKeyword: string;
  SType: string;

begin
  if Command = HELP_COMMAND then begin
    if PtInRect(RVEdit.ClientRect, RVEdit.ScreenToClient(Mouse.CursorPos)) then begin
      if CurCursorID = 'H' then HelpKeyword := 'RefTopReport'
      else if CurCursorID = 'T' then HelpKeyword := 'RefTableContents'
      else if CurCursorID = '~HNAME' then HelpKeyword := 'RefIndexNames'
      else if copy(CurCursorID, 1, 2) = 'N+' then HelpKeyword := 'RefIndexNames'
      else if CurCursorID = 'B' then HelpKeyword := 'RefBottomReport'
      else if CurCursorID <> '' then HelpKeyword := 'RefInformationArea'
      else HelpKeyword := 'RefEverythingReport';
      Application.HelpSystem.ShowTopicHelp(HelpKeyword, Application.CurrentHelpFile);
    end
    else if PtInRect(ElTree.ClientRect, ElTree.ScreenToClient(Mouse.CursorPos)) then
      Application.HelpSystem.ShowTopicHelp('RefTreeView', Application.CurrentHelpFile)
    else if PtInRect(TopToolbar.ClientRect, TopToolbar.ScreenToClient(Mouse.CursorPos)) then
      Application.HelpSystem.ShowTopicHelp('RefTopToolbar', Application.CurrentHelpFile)
    else if PtInRect(BottomToolbar.ClientRect, BottomToolbar.ScreenToClient(Mouse.CursorPos)) then
      Application.HelpSystem.ShowTopicHelp('RefBottomToolbar', Application.CurrentHelpFile)
    else
      Application.HelpSystem.ShowTopicHelp('RefMainWindow', Application.CurrentHelpFile);
    CallHelp := false;
  end
  else if Command = HELP_CONTEXTPOPUP then begin
    case Data of
      0: HelpKeyword := 'RefMenuBar';
      11: HelpKeyword := 'RefFileMenu';
      12: HelpKeyword := 'RefEditMenu';
      13: HelpKeyword := 'RefSearchMenu';
      14: HelpKeyword := 'RefNavigateMenu';
      15: HelpKeyword := 'RefViewMenu';
      16: HelpKeyword := 'RefOrganizeMenu';
      17: HelpKeyword := 'RefHelpMenu';
      else HelpKeyword := '';
    end;
    if HelpKeyword <> '' then begin
      Application.HelpSystem.ShowTopicHelp(HelpKeyword, Application.CurrentHelpFile);
      CallHelp := false;
    end;
  end;
  Result := true;
end;

我确实必须将 11 到 17 放入我的 7 个主菜单中 MenuItems 的 HelpContext 属性中,以便根据您所在的菜单提供正确的帮助。菜单项的检测是这个问题的答案的帮助提供给我。

好消息是这段代码很容易理解(使用 HelpKeywords 而不是 HelpContext 数字)并且即使在转换为 Delphi XE 和 FireMonkey 之后可能仍然可以工作。

4

3 回答 3

3

查看toCommand = HELP_COMMAND的演员表,您似乎使用基于关键字而不是上下文标识符(HelpType = htKeyword)的帮助系统。DataPChar

(这里在 Delphi 7 中)菜单项没有HelpTypeandHelpKeyword属性,因此您必须使用该HelpContext属性:

function TForm1.ApplicationEvents1Help(Command: Word; Data: Integer;
  var CallHelp: Boolean): Boolean;
begin
  if Command = HELP_COMMAND then
  begin
    //Application.HelpSystem.ShowTopicHelp(PChar(Data), Application.CurrentHelpFile);
    //Doesn't this do the same?
    Application.HelpKeyword(PChar(Data));
    CallHelp := False;
  end
  else if Command = HELP_CONTEXT then
  begin
    // Convert the context identifier to your keyword, or:
    Application.HelpContext(Data);
    CallHelp := False;
  end;
  Result := True;
end;
于 2011-10-22T07:55:21.030 回答
2

通过捕获 Windows 消息“WM_MENUSELECT”,可以跟踪选定的菜单项。

有关详细信息,请参阅菜单提示

例子 :

 type
    TForm1 = class(TForm)
    ...
    private
      fMyCurrentSelectedMenuItem : TMenuItem;
      procedure WMMenuSelect(var Msg: TWMMenuSelect) ; message WM_MENUSELECT;
    end

procedure TForm1.WMMenuSelect(var Msg: TWMMenuSelect) ;
 var
    menuItem : TMenuItem;
    hSubMenu : HMENU;
 begin
    inherited; // from TCustomForm (so that Application.Hint is assigned)

    menuItem := nil;
    if (Msg.MenuFlag <> $FFFF) or (Msg.IDItem <> 0) then
    begin
      if Msg.MenuFlag and MF_POPUP = MF_POPUP then
      begin
        hSubMenu := GetSubMenu(Msg.Menu, Msg.IDItem) ;
        menuItem := Self.Menu.FindItem(hSubMenu, fkHandle) ;
      end
      else
      begin
        menuItem := Self.Menu.FindItem(Msg.IDItem, fkCommand) ;
      end;
    end;

    //miHint.DoActivateHint(menuItem) ;
    fMyCurrentSelectedMenuItem := menuItem;
 end; (*WMMenuSelect*)

因此,当按下 F1 按钮时,您可以使用 fMyCurrentSelectedMenuItem 来激活正确的帮助。

于 2011-10-22T07:51:28.493 回答
1

您可以使用 GetMenuItemRect 函数:
1. 浏览主菜单中的所有项目并调用 GetMenuItemRect 以获取项目位置。仅当显示项目时功能才会起作用。
2. 使用 GetCursorPos 和 PtInRect 检查鼠标是否在菜单项上并调用适当的帮助主题。

于 2011-10-22T07:52:36.987 回答