sách gpt4 ai đã đi

Làm thế nào để ngăn chặn các phím tắt xung đột/tương tác trong Delphi?

In lại 作者:行者123 更新时间:2023-12-03 15:26:11 30 4
mua khóa gpt4 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帮助我解决了这个问题。没有你,做不到。 (也许我可以,但是可能要花我六个月的时间。)

    1 Câu trả lời

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

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

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

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

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

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

    procedure TMainForm.EditPaste1Execute(Sender: TObject);
    khác nhau
    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消息来检查焦点编辑控件是否具有选择。

    biên tập:

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

    biên tập:

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

    请尝试使用此其他事件处理程序:
    procedure TForm1.ActionList1Update(Action: TBasicAction; var Handled: Boolean);
    khác nhau
    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/

    30 4 0
    行者123
    Hồ sơ cá nhân

    Tôi là một lập trình viên xuất sắc, rất giỏi!

    Nhận phiếu giảm giá Didi Taxi miễn phí
    Mã giảm giá Didi Taxi
    Giấy chứng nhận ICP Bắc Kinh số 000000
    Hợp tác quảng cáo: 1813099741@qq.com 6ren.com