gpt4 book ai didi

c# - 从控件子类化 ParentForm WndProc

转载 作者:行者123 更新时间:2023-11-30 17:14:41 24 4
gpt4 key购买 nike

我正在将自定义的 MenuStrip 控件集成到另一个 .NET 应用程序中。除了焦点问题外,MenuStrip 工作正常。如果承载 MenuStrip 的窗体未获得焦点,则用户需要单击两次 - 一次激活窗体,另一次选择菜单项。主机表单是我无法修改的独立 .NET 应用程序的一部分。我只能修改我的控件的源代码。

我找到了一个 solution at the WinForm level它覆盖了 Form WndProc 方法,除了我没有 WinForm 的源代码访问权限,也不能重新编译主机应用程序和表单。

有没有办法子类化控件的 ParentForm,以便在未获得焦点时自动激活 ParentForm?

最佳答案

我能够使用 ContainerControl.ParentForm 获取对宿主窗体的引用,但是在生产环境中 ParentForm 返回 null,我仍然需要找到解决方案。我将 NewWndProc 处理程序放在 try/catch 中,以防它抛出任何异常,尽管我不确定它会抛出什么(如果有的话)。我可能不得不只使用 Win32 函数而不使用 Form.Focused 和 Form.Activate() .NET 方法。无论如何,这是代码:

public class FocusFormWrapper
{
#region DllImport
public const int GWL_WNDPROC = (-4);
public const UInt32 WM_CLOSE = 0x0010;
public const UInt32 WM_PARENTNOTIFY = 0x0210;

public delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindow(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll", SetLastError = true)]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr newWndProc);

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string _ClassName, string _WindowName);

[DllImport("user32.dll", SetLastError = true)]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

[DllImport("user32.dll", SetLastError = true)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
#endregion DllImport

private Form myForm = null;
private IntPtr hWndTarget = IntPtr.Zero;
private IntPtr oldWndProc = IntPtr.Zero;
private WndProcDelegate newWndProc;

private FocusFormWrapper()
{
}

public FocusFormWrapper(Form sourceForm)
{
if (sourceForm == null)
throw new ArgumentNullException("sourceForm");
if (!IsWindow(sourceForm.Handle))
throw new ArgumentException("sourceForm IsWindow failed");

myForm = sourceForm;
hWndTarget = myForm.Handle;
AddSubclass();
}

~FocusFormWrapper()
{
RemoveSubclass();
myForm = null;
newWndProc = null;
}

private int AddSubclass()
{
int result = -1;
if (myForm != null && newWndProc == null)
{
newWndProc = new WndProcDelegate(NewWndProc);
oldWndProc = GetWindowLong(hWndTarget, GWL_WNDPROC);
result = SetWindowLong(hWndTarget, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(newWndProc));
}
return result;
}

public int RemoveSubclass()
{
int result = -1;
if (myForm != null && newWndProc != null)
{
result = SetWindowLong(hWndTarget, GWL_WNDPROC, oldWndProc);
newWndProc = null;
}
return result;
}

public IntPtr NewWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
try
{
if (msg == WM_PARENTNOTIFY && !myForm.Focused)
{
// Make this form auto-grab the focus when menu/controls are clicked
myForm.Activate();
}
if (msg == WM_CLOSE)
{
RemoveSubclass();
}
}
catch
{
}

return CallWindowProc(oldWndProc, hWnd, msg, wParam, lParam);
}
}

关于c# - 从控件子类化 ParentForm WndProc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8524519/

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