C# 仅当显示对话框时,正在取消对窗体的填充
这与通过互操作显示C#表单的VB6应用程序有关 C#窗体中的事件会导致其中一个VB6应用程序窗体显示 通常,当VB6表单被隐藏(C# 仅当显示对话框时,正在取消对窗体的填充,c#,winforms,vb6,com-interop,z-order,C#,Winforms,Vb6,Com Interop,Z Order,这与通过互操作显示C#表单的VB6应用程序有关 C#窗体中的事件会导致其中一个VB6应用程序窗体显示 通常,当VB6表单被隐藏(form.Hide)时,底层的C#表单会被放在前面 但是,如果VB6窗体在其生命周期内导致显示MsgBox,则当VB6窗体被隐藏时,底层C#窗体将不在前面 为什么会发生这种情况?这就像是MsgBox正在更改窗体的Z顺序。如何在VB6隐藏后使C#窗体显示?是否必须使用窗口句柄 假设您同意孤立的msgbox保持打开状态。当VB6窗体被隐藏时,您需要触发一个事件以获取窗口句柄
form.Hide
)时,底层的C#表单会被放在前面
但是,如果VB6窗体在其生命周期内导致显示MsgBox
,则当VB6窗体被隐藏时,底层C#窗体将不在前面
为什么会发生这种情况?这就像是MsgBox
正在更改窗体的Z顺序。如何在VB6隐藏后使C#窗体显示?是否必须使用窗口句柄
假设您同意孤立的msgbox保持打开状态。当VB6窗体被隐藏时,您需要触发一个事件以获取窗口句柄:
public static int FindWindow(string windowName, bool wait)
{
int hWnd = FindWindow(null, windowName);
while (wait && hWnd == 0)
{
System.Threading.Thread.Sleep(500);
hWnd = FindWindow(null, windowName);
}
return hWnd;
}
然后将C#窗口置于顶部:
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
// When you don't want the ProcessId, use this overload and pass IntPtr.Zero for the second parameter
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
/// <summary>The GetForegroundWindow function returns a handle to the foreground window.</summary>
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool BringWindowToTop(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool BringWindowToTop(HandleRef hWnd);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, uint nCmdShow);
private static void ForceForegroundWindow(IntPtr hWnd)
{
uint foreThread = GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero);
uint appThread = GetCurrentThreadId();
const uint SW_SHOW = 5;
if (foreThread != appThread)
{
AttachThreadInput(foreThread, appThread, true);
BringWindowToTop(hWnd);
ShowWindow(hWnd, SW_SHOW);
AttachThreadInput(foreThread, appThread, false);
}
else
{
BringWindowToTop(hWnd);
ShowWindow(hWnd, SW_SHOW);
}
}
[DllImport(“user32.dll”,SetLastError=true)]
公共静态外部单元GetWindowThreadProcessId(IntPtr hWnd,out单元lpdwProcessId);
//当您不需要ProcessId时,请使用此重载并将IntPtr.Zero传递给第二个参数
[DllImport(“user32.dll”)]
公共静态外部单元GetWindowThreadProcessId(IntPtr hWnd,IntPtr ProcessId);
[DllImport(“kernel32.dll”)]
公共静态外部uint GetCurrentThreadId();
///GetForeGroundIndow函数返回前台窗口的句柄。
[DllImport(“user32.dll”)]
公共静态外部IntPtr GetForegroundWindow();
[DllImport(“user32.dll”)]
公共静态外部bool AttachThreadInput(uint-idAttach、uint-idAttachTo、bool-fAttach);
[DllImport(“user32.dll”,SetLastError=true)]
公共静态外部布尔布林温多图(IntPtr hWnd);
[DllImport(“user32.dll”,SetLastError=true)]
公共静态外部bool Bringwindowtop(HandleRef hWnd);
[DllImport(“user32.dll”)]
公共静态外部布尔显示窗口(IntPtr hWnd、uint nCmdShow);
专用静态无效力ForeGroundIndow(IntPtr hWnd)
{
uint foreThread=GetWindowThreadProcessId(GetForegroundWindow(),IntPtr.Zero);
uint appThread=GetCurrentThreadId();
Constuint SW_SHOW=5;
if(前线程!=appThread)
{
AttachThreadInput(前线程、appThread、true);
布林温多托(hWnd);
展示窗口(hWnd、SW_展示);
AttachThreadInput(前线程、appThread、false);
}
其他的
{
布林温多托(hWnd);
展示窗口(hWnd、SW_展示);
}
}
参考:我通过使用该类,按照本线程中的最后一个答案,使其工作: 该代码使用
FindWindowEx
获取VB6
窗口的句柄,这是不必要的,因为您只需将VB6
窗口的句柄传递到.NET
表单:
public void ShowDotNetForm(IntPtr hwndMain)
{
NativeWindow vb6Window = new NativeWindow();
vb6Window.AssignHandle(hwndMain);
f.Show(vb6Window);
}
VB6
表单中的代码为:
dotNetObj.ShowDotNetForm Me.hWnd
从
VB6
传递窗口句柄更好,因为FindWindowEx
需要知道窗口标题的文本才能获得句柄。下面找到的NativeWindow
类如何:+1请注意Windows专家Raymond Chen指出,这是AttachThreadInput
解决方法在某些情况下。然而,我自己从来没有遇到过这些错误。YMMV@MarkJ:我在上面的评论中采用了什么方法?@CJ7我看到了,结果如何?ps这就是我想知道的原因,反之亦然。@CJ7听起来很有希望。它不使用AttachThreadInput
,因此Raymond的警告不适用。让我们知道它是否有效-如果有效,请将其作为您自己问题的答案发布。