这与通过互操作显示 C# 表单的 VB6 应用程序有关。
C# 窗体中的事件会导致显示其中一个 VB6 应用程序窗体。
通常,当这个 VB6 表单被隐藏(Form.Hide
)时,底层的 C# 表单被带到前面。
但是,如果 VB6 窗体在其生命周期内导致 aMsgBox
被显示,那么当 VB6 窗体被隐藏时,底层 C# 窗体将不会位于最前面。
为什么会这样?就像MsgBox
正在改变表格的 Z 顺序一样。
这与通过互操作显示 C# 表单的 VB6 应用程序有关。
C# 窗体中的事件会导致显示其中一个 VB6 应用程序窗体。
通常,当这个 VB6 表单被隐藏(Form.Hide
)时,底层的 C# 表单被带到前面。
但是,如果 VB6 窗体在其生命周期内导致 aMsgBox
被显示,那么当 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);
}
}
我通过使用NativeWindow类使其工作,遵循此线程中的最后一个答案:http: //social.msdn.microsoft.com/Forums/en-US/2692df26-317c-4415-816b-d08fe6854df8/vbnet-vb6 -win32-api-problems?forum=vbinterop
该代码用于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
需要您知道窗口标题的文本才能获取句柄。