本文介绍了WS_EX_NOACTIVATE 和 WinForms 的两个问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In some of my applications, I use the WS_EX_NOACTIVATE extended window style value (e.g. to create a Virtual Keyboard or for a form hosted in another program). This value prevents the form to get focus.

以下是我的处理方式:

protected override CreateParams CreateParams
{
    get
    {
        CreateParams p = base.CreateParams;

        p.ExStyle |= Win32.WS_EX_NOACTIVATE;

        return p;
    }
}

效果很好,但我注意到此解决方案存在两个问题:

It works well, but I notice two issues with this solution:

  1. 用户无法通过按Tab"键在控件之间移动
  2. 当用户拖动窗体时,我们看不到位移(窗体在移动过程中不会重绘)

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

So, is it possible to fix these issues or, at least, to implement some alternatives? Maybe WS_EX_NOACTIVATE is not the best solution to do that?

非常感谢!

推荐答案

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

Here are the the solutions I found for each issue:

问题 #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() - 这将迫使它移动!


Issue #2: you must intercept the appropriate messages received from system (WM_SIZING and WM_MOVING) and set the position of the form with SetWindowPos() - this will force it to move!

在您的表单类中:

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);
    }
}

这篇关于WS_EX_NOACTIVATE 和 WinForms 的两个问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 05:09