gpt4 book ai didi

c# - 如何覆盖 WinForms RichTextBox 的 Ctrl+Shift+0(零)?

转载 作者:太空宇宙 更新时间:2023-11-03 13:33:32 25 4
gpt4 key购买 nike

对于我的子类 RichTextBox 类,我可以捕获、抑制 Ctrl+Shift+# 的默认行为并重新使用 Ctrl+Shift+#,只要 # 在 1 到 9 之间。对于 Ctrl+Shift+0 ,我不能。我在表单类中尝试了 ProcessCmdKey,在控件类中尝试了 onKeyDownPreProcessMessage

下面是用于应该抑制 Ctrl+Shift+0 但不抑制 Ctrl+Shift+0 的控件类的示例代码:

public override bool PreProcessMessage(ref Message msg)
{
bool cancel = false;
int vKeyCode = (int)msg.WParam;

if(msg.Msg == WinApi.WM_KEYDOWN)
{
bool ctrlDown = (WinApi.GetKeyState(Keys.ControlKey) & (1 << 16)) == (1 << 16);
bool altDown = (WinApi.GetKeyState(Keys.Alt) & (1 << 16)) == (1 << 16);
bool shiftDown = (WinApi.GetKeyState(Keys.ShiftKey) & (1 << 16)) == (1 << 16);

if(ctrlDown && shiftDown && vKeyCode == (int)Keys.D0)
{
Debug.WriteLine("Cancel!");
cancel = true;
}
}

return cancel ? true : base.PreProcessMessage(ref msg);
}

但是,将 Keys.D0 更改为 Keys.D1 表明示例在其他方面有效。

如果这是一条线索,RichTextBox 响应 Ctrl+Shift+0 的默认行为是更改字体。我去寻找将此作为内置快捷方式提及的文档,但我没有找到任何东西(也许我没有使用正确的搜索词)。

我应该如何检测 Ctrl+Shift+0 以便我可以抑制默认行为并编写我自己的行为?

最佳答案

经过一些尝试,我发现了如何真正抑制 Ctrl + Shift + D0。然而,新问题更加棘手,Ctrl + Shift + D0 被抑制 OK 但 beep sound 是在释放 Ctrl and Shift 时产生的,这太烦人了,因为你说你想覆盖这些键组合而不是丢弃它。因此不应生成哔声

在满怀希望地搜索之后,有一些样式可以应用于RichTextBox,以防止哔声或一些消息被丢弃,从而导致抑制 哔声 但没有任何此类事情。我几乎要失望了,打算让你的问题永远无人回答。我不想添加只是部分解决您的问题的答案。然而幸运的是,我尝试发送一些 key 而不是丢弃的0 key 使用 key 组合并制作 key 组合 有效 因此不会生成哔声。这是为您提供的完整代码,请注意,我们必须在这里使用一些全局低级键盘钩子(Hook),正如我所说,应用程序级消息过滤器也无济于事:

    [DllImport("user32")]
private static extern IntPtr SetWindowsHookEx(int hookType, KeyboardLowLevelProc proc, IntPtr moduleHandle, int threadID);
[DllImport("user32")]
private static extern int UnhookWindowsHookEx(IntPtr hHook);
[DllImport("user32")]
private static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32")]
private static extern IntPtr GetModuleHandle(string moduleName);

public struct KBDLLHOOKSTRUCT
{
public Keys key;
public int scanCode;
public int flags;
public int time;
public IntPtr extra;
}
public delegate IntPtr KeyboardLowLevelProc(int hCode, IntPtr wParam, IntPtr lParam);
public IntPtr KeyboardLowLevelCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0) {
KBDLLHOOKSTRUCT kbd = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
if (kbd.key == Keys.D0 && blockD0) {
if(ModifierKeys == (Keys.Control | Keys.Shift)) {
SendKeys.Send("{ESC}");
//Add custom code as the response to Ctrl + Shift + D0 here
//....
}
return new IntPtr(1);//Discard the default behavior
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
bool blockD0;
KeyboardLowLevelProc proc; //this should be declared in the form scope
IntPtr hHook;
//your Form1 constructor
public Form1(){
InitializeComponent();
//Get current module Handle
IntPtr currentModuleHandle = GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName);
//Set the keyboard hook
hHook = SetWindowsHookEx(13, proc, currentModuleHandle, 0);//WH_KEYBOARD_LL = 13
//register these Key events for your richTextBox1
richTextBox1.KeyDown += (s, e) => {
if(e.KeyCode != Keys.D0) blockD0 = true;
};
richTextBox1.KeyUp += (s, e) => {
if (ModifierKeys == Keys.None) blockD0 = false;
};
//Unhook keyboard when form is closed
FormClosed += (s,e) => {
if (hHook != IntPtr.Zero) {
UnhookWindowsHookEx(hHook);
hHook = IntPtr.Zero;
}
}
}

一些解释:我不明白为什么我们必须在这里使用Global Low-level Keyboard hook,我猜当键组合Ctrl + Shift + D0 被按下,可能有一些关键消息被克隆并发送到另一个线程,这就是为什么当前线程中的所有手动拦截无法拦截或覆盖 Ctrl + Shift + D0,但是 global low-level keyboard hook 可以处理 key messages 当前模块的所有线程,它可以拦截任何关键消息。

我提到了哔声的问题,如果你想体验它,只要去掉SendKeys.Send("{ESC}");,其实你可以尝试一些其他键,例如 12,...它们还使组合键 Ctrl + Shift + ... 有效并提供帮助避免任何哔声

更新

上面的解决方案工作正常,这是最好的解决方案,因为 Ctrl + Shift + D0 应该被彻底地丢弃。但是它有点长(如您所见)。我发现当您按下 Ctrl + Shift + D0 时,将发送消息 WM_INPUTLANGCHANGEREQUEST,此消息会导致您不希望出现的行为。所以我们可以尝试另一种解决方案,使用 PreProcessMessage 你仍然可以捕获组合 Ctrl + Shift + D0 但你不能丢弃它(因为它被分派(dispatch)到另一个线程) ,这意味着您可以在那里添加自己的代码,而不是丢弃 Ctrl + Shift + D0,我们可以通过丢弃消息 WM_INPUTLANGCHANGEREQUEST 来丢弃它引起的效果/行为.我们有以下代码:

//Create a custom RichTextBox class
public class CustomRichTextBox : RichTextBox {
protected override void WndProc(ref Message m){
if(m.Msg == 0x50) return; //WM_INPUTLANGCHANGEREQUEST = 0x50
base.WndProc(ref m);
}
public override bool PreProcessMessage(ref Message msg) {
if (msg.Msg == 0x100)//WM_KEYDOWN = 0x100
{
Keys keyData = (Keys)msg.WParam | ModifierKeys;
if(keyData == (Keys.Control | Keys.Shift | Keys.D0)){
//your own code goes here...
}
}
return base.PreProcessMessage(ref msg);
}
}

您可以看到第二种方法要短得多,但是正如我所说,它实际上抑制Ctrl + Shift + D0,它只是抑制由消息 WM_INPUTLANGCHANGEREQUEST 引起的默认行为。我想这足以解决您的问题。

关于c# - 如何覆盖 WinForms RichTextBox 的 Ctrl+Shift+0(零)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19556221/

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