gpt4 book ai didi

delphi - 如何防止快捷方式在Delphi中碰撞/交互?

转载 作者:行者123 更新时间:2023-12-03 15:26:11 29 4
gpt4 key购买 nike

我在主菜单上使用标准的剪切,复制,粘贴操作。它们具有快捷键Ctrl-X,Ctrl-C和Ctrl-V。

当我打开模态表单时FindFilesForm.ShowModal,然后所有快捷方式都可以从表单中使用。

但是当我打开非模式形式时,例如FindFilesForm.Show,然后快捷方式不起作用。

我认为,如果FindFilesForm是事件表单,则这些操作应该起作用。它的形式应该与它无关,还是我的想法不对?

但是,如何获得用于非模式形式的快捷方式?

卡里的回应后,我进一步研究了它。某些控件(例如TMemo或TEdit。

但这是对其他人的。具体来说,发生这种情况的地方包括:

  • TComboBox中的文本
  • TFindDialog中的文本
  • 一个TElTreeInplaceEdit控件,它是LMD的ElPack
  • 的一部分

    我将查看是否还有其他人,并将其添加到列表中。

    这些都是我程序中重要的非模式形式。

    所以我仍然需要一个解决方案。

    好的。我真的需要帮助。因此,这成为我悬赏的第一个问题。

    我与Cary的讨论是通过他的回答进行的,那里的评论更详细地描述了我的问题。

    正如我在其中一条评论中所提到的,似乎在讨论了一个相关的问题 here.

    我需要的是一种解决方案或解决方法,它允许Ctrl-X,Ctrl-C和Ctrl-V始终在“非模式”窗口的TComboBox和TFindDialog中工作。如果解决了这两个问题,我相信我的TElTreeInplaceEdit也能正常工作。

    正如卡里(Cary)所述,仅需几分钟即可建立一个简单的测试程序。希望有人能够解决这个问题。

    只是要警惕,似乎有些东西可以使其有时工作,但有时却不工作。如果可以更详细地隔离它,请在此处报告。

    感谢您能为我提供的任何帮助。

    Mghie努力工作以找到解决方案,他的OnExecute处理程序与他的ActionListUpdate处理程序结合在一起可以解决问题。因此,对于他的努力,我给他了可以接受的解决方案和奖励点。

    但是他的 Action 列表更新处理程序并不简单,您需要在其中指定要处理的所有情况。假设还有Ctrl + A用于全选,或者Ctrl-Y用于撤消。一般的程序会更好。

    因此,如果您在搜索答案时确实遇到了这个问题,请首先尝试我提供的答案,其中添加了IsShortcut处理程序。它对我有用,应该处理所有情况,不需要OnExecute处理程序,因此要简单得多。彼得·贝夫特(Peter Under)编写了该代码,乌韦·莫尔赞(Uwe Molzhan)获得了发现者费用。

    感谢Cary,mghie,Uwe和Peter帮助我解决了这个问题。没有你,做不到。 (也许我可以,但是可能要花我六个月的时间。)

    最佳答案

    好的,首先要考虑的是:这与模态或非模态形式无关,这是Delphi操作组件工作方式的限制(如果您要这样称呼)。

    让我通过一个简单的示例来证明这一点:创建一个具有新表单的新应用程序,将TMemoTComboBox放在其上,然后运行该应用程序。这两个控件都将具有系统提供的带有编辑命令的上下文菜单,并且将对它们做出正确的 react 。它们将对菜单快捷键执行相同的操作,但组合框不支持Ctrl +A。

    现在添加一个TActionList组件,其中包含用于剪切,复制和粘贴的三个标准 Action 。事情仍然会奏效,行为没有任何变化。

    现在添加一个主菜单,并从模板中添加“编辑菜单”。删除所有命令,但剪切,复制和粘贴命令除外。为菜单项设置相应的操作组件,然后运行应用程序。观察组合框如何仍然具有上下文菜单,并且那里的命令仍然有效,但是快捷方式不再起作用。

    问题在于标准编辑操作仅设计用于TCustomEdit控件。看一下StdActns.pas中的TEditAction.HandlesTarget()方法。由于组合框中的编辑控件,树形控件中的就地编辑器或 native 对话框中的编辑控件都不会被此控件捕获,因此将无法对其进行处理。当其中一个控件具有焦点时,菜单命令将始终被禁用。至于快捷方式仅在某些时间有效-这取决于VCL是否在某些时候将快捷方式映射到操作命令。如果没有,那么他们最终将到达 native 窗口过程并启动edit命令。在这种情况下,快捷方式仍然可以使用。我假设对于模态对话框, Action 处理被暂停,因此模态对话框和非模态对话框的行为是不同的。

    要解决此问题,您可以为这些标准操作的OnExecute提供处理程序。例如,粘贴命令:

    procedure TMainForm.EditPaste1Execute(Sender: TObject);
    var
    FocusWnd: HWND;
    begin
    FocusWnd := GetFocus;
    if IsWindow(FocusWnd) then
    SendMessage(FocusWnd, WM_PASTE, 0, 0);
    end;

    以及Cut命令( WM_CUT)和Copy命令( WM_COPY)的类似处理程序。在小型演示应用程序中执行此操作可使组合框再次正常工作。您应该尝试使用您的应用程序,但是我认为这会有所帮助。为所有 native 编辑控件正确启用和禁用主菜单命令是一项艰巨的任务。也许您可以发送 EM_GETSEL消息来检查焦点编辑控件是否具有选择。

    编辑:

    更多信息为什么模态对话框和非模态对话框上的组合框的行为不同(在Delphi 2009上进行了分析):有趣的代码在 TWinControl.IsMenuKey()中-它试图在父窗体的 Action 列表之一中查找 Action 组件处理快捷方式的集中控件的控件。如果失败,它将发送 CM_APPKEYDOWN消息,最终导致对应用程序主窗体的 Action 列表执行相同的检查。事情是这样的:仅在启用应用程序主窗体的窗口句柄的情况下才能执行此操作(请参见 TApplication.IsShortCut()代码)。现在,在表单上调用 ShowModal()将禁用所有其他表单,因此,除非模式对话框自身包含具有相同快捷方式的 Action ,否则 native 快捷方式处理将起作用。

    编辑:

    我可以重现该问题-关键是以某种方式使编辑操作被禁用。回想起来,这是显而易见的,当然也需要更新 Action 的 Enabled属性。

    请尝试使用此其他事件处理程序:
    procedure TForm1.ActionList1Update(Action: TBasicAction; var Handled: Boolean);
    var
    IsEditCtrl, HasSelection, IsReadOnly: boolean;
    FocusCtrl: TWinControl;
    FocusWnd: HWND;
    WndClassName: string;
    SelStart, SelEnd: integer;
    MsgRes: LRESULT;
    begin
    if (Action = EditCut1) or (Action = EditCopy1) or (Action = EditPaste1) then
    begin
    IsEditCtrl := False;
    HasSelection := False;
    IsReadOnly := False;

    FocusCtrl := Screen.ActiveControl;
    if (FocusCtrl <> nil) and (FocusCtrl is TCustomEdit) then begin
    IsEditCtrl := True;
    HasSelection := TCustomEdit(FocusCtrl).SelLength > 0;
    IsReadOnly := TCustomEdit(FocusCtrl).ReadOnly;
    end else begin
    FocusWnd := GetFocus;
    if IsWindow(FocusWnd) then begin
    SetLength(WndClassName, 64);
    GetClassName(FocusWnd, PChar(WndClassName), 64);
    WndClassName := PChar(WndClassName);
    if AnsiCompareText(WndClassName, 'EDIT') = 0 then begin
    IsEditCtrl := True;
    SelStart := 0;
    SelEnd := 0;
    MsgRes := SendMessage(FocusWnd, EM_GETSEL, WPARAM(@SelStart),
    LPARAM(@SelEnd));
    HasSelection := (MsgRes <> 0) and (SelEnd > SelStart);
    end;
    end;
    end;

    EditCut1.Enabled := IsEditCtrl and HasSelection and not IsReadOnly;
    EditCopy1.Enabled := IsEditCtrl and HasSelection;
    // don't hit the clipboard three times
    if Action = EditPaste1 then begin
    EditPaste1.Enabled := IsEditCtrl and not IsReadOnly
    and Clipboard.HasFormat(CF_TEXT);
    end;
    Handled := TRUE;
    end;
    end;

    我没有检查 native 编辑控件是否为只读,这可以通过添加以下代码来完成:
    IsReadOnly := GetWindowLong(FocusWnd, GWL_STYLE) and ES_READONLY <> 0;

    注意:我已经给了mghie答案,因为他做了很多工作并且答案是正确的,但是我已经实现了a simpler solution that I added as an answer myself

    关于delphi - 如何防止快捷方式在Delphi中碰撞/交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1852976/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com