WS_EX_NOACTIVATE和WinForms有两个问题

在我的一些应用程序中,我使用WS_EX_NOACTIVATE 扩展窗口样式值 (例如,创建虚拟键盘或托管在另一个程序中的表单)。 此值可防止表单获得焦点。

以下是我的进展方式:

protected override CreateParams CreateParams { get { CreateParams p = base.CreateParams; p.ExStyle |= Win32.WS_EX_NOACTIVATE; return p; } } 

它运作良好,但我注意到这个解决方案有两个问题:

  1. 用户无法通过按“Tab”在控件之间移动
  2. 当用户拖动表单时,我们无法看到位移(表单在移动过程中不重绘)

那么,是否有可能解决这些问题,或者至少可以实施一些替代方案? 也许WS_EX_NOACTIVATE不是最好的解决方案吗?

非常感谢!

以下是我为每个问题找到的解决方案:


问题#1

 protected override bool ProcessKeyPreview(ref Message m) { if (m.Msg == Win32.WM_KEYDOWN && (Keys)m.WParam == Keys.Tab) { if (Control.ModifierKeys == Keys.Shift) { this.SelectNextControl(ActiveControl, false, true, true, true); // Bring focus to previous control } else { this.SelectNextControl(ActiveControl, true, true, true, true); // Bring focus to next control } } return base.ProcessKeyPreview(ref m); } 

问题#2 :您必须拦截从系统收到的相应消息( WM_SIZINGWM_MOVING )并使用SetWindowPos()设置表单的位置 – 这将强制它移动!

在您的表格课程中:

 public const int WM_SIZING = 0x0214; public const int WM_MOVING = 0x0216; [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } [DllImport("user32.dll", SetLastError = true)] private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInstertAfter, int x, int y, int cx, int cy, uint flags); protected override void WndProc(ref Message m) { if (m.Msg == WM_SIZING || m.Msg == WM_MOVING) { RECT rect = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT)); SetWindowPos(this.Handle, IntPtr.Zero, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, 0); } else { base.WndProc(ref m); } }