对于我的子类RichTextBox类,只要#介于1到9之间,就可以捕获、抑制和重用Ctrl+Shift+#的默认行为。对于Ctrl+Shift+0,我做不到。我在form类中尝试了ProcessCmdKey,在控制类中使用了onKeyDown和PreProcessMessage。
下面是用于控件类的示例代码,这些代码应该禁止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,以便能够抑制默认行为并编写自己的行为?
发布于 2013-10-24 16:38:06
经过几次尝试,我发现了如何真正地抑制Ctrl + Shift + D0。然而,新的问题更加严重,Ctrl + Shift + D0被抑制了,但是beep sound是在发布Ctrl and Shift时生成的,这太烦人了,因为您说要重写--这些键组合--而不是丢弃。因此不应该生成beep sound。
在进行了大量的搜索之后,希望有一些style可以应用于RichTextBox以防止beep sound,或者有一些消息要丢弃,从而导致了beep sound的抑制,但是没有任何这样的东西。我几乎感到失望,并打算让你的问题永远没有答案。我不想再加一个只是部分解决了你的问题的答案。不过,幸运的是,我尝试了sending some key,而不是废弃的0 key,以consume键组合,并使keys combination 有效的,这样就不会生成beep sound。下面是您的全部代码,请注意,这里我们必须使用一些global low-level keyboard 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,但是d33可以处理当前模块的E 135中的D34所有线程E 236,并且它可以拦截任何密钥消息。
我提到了beep sound问题,如果您想要体验它,只需删除SendKeys.Send("{ESC}");,实际上您可以尝试一些其他键,如1、2、.它们还使组合键Ctrl + Shift + ...有效,并有助于避免任何beep sound。
更新
上面的解决方案工作正常,这是最好的解决方案,因为Ctrl + Shift + D0应该彻底抛弃,完全抛弃。不过,它有点长(如你所见)。我发现当您按下Ctrl + Shift + D0,消息WM_INPUTLANGCHANGEREQUEST被发送时,这条消息会导致您不想要的行为。因此,我们可以尝试另一种解决方案,使用PreProcessMessage,您仍然可以捕获组合Ctrl + Shift + D0,但您不能丢弃它(因为它被分派到另一个线程),这意味着您可以在那里添加自己的代码,而不是放弃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所导致的默认行为。我想这足以解决你的问题。
https://stackoverflow.com/questions/19556221
复制相似问题