Reputation: 629
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.
Here is how I proceed:
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:
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?
Many thanks!
Upvotes: 2
Views: 1275
Reputation: 629
Here are the the solutions I found for each issue:
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);
}
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!
In your Form's class:
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);
}
}
Upvotes: 3