基础表单消失但仅在显示对话框时
Posted
技术标签:
【中文标题】基础表单消失但仅在显示对话框时【英文标题】:Underyling form disappearing but only if dialog shown 【发布时间】:2012-09-22 14:05:00 【问题描述】:这与通过互操作显示 C# 表单的 VB6 应用程序有关。
C# 表单中的事件会导致显示其中一个 VB6 应用程序表单。
通常,当隐藏此 VB6 表单 (Form.Hide
) 时,底层 C# 表单会被置于最前面。
但是,如果 VB6 表单在其生命周期中导致显示 MsgBox
,那么当 VB6 表单被隐藏时,底层 C# 表单将不会位于最前面。
为什么会这样?这就像MsgBox
正在改变表单的 Z-Order。
【问题讨论】:
【参考方案1】:“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);
参考:SetForegroundWindow Win32-API not always works on Windows-7
【讨论】:
这里底部的NativeWindow
类怎么样:social.msdn.microsoft.com/Forums/lt/vbinterop/thread/…
+1 请注意,Windows 大师 Raymond Chen 指出,在某些情况下,这种AttachThreadInput
解决方法can cause your program to stop responding。但是,我自己从未遇到过这些错误。 YMMV。
@MarkJ:我在上面的评论中采用的方法怎么样?
@CJ7 我看到了,结果如何? ps 这个VB6 Froms contain c# forms 反之亦然是我想知道的原因。
@CJ7 听起来很有希望。它不使用AttachThreadInput
,因此Raymond 的警告不适用。让我们知道它是否有效 - 如果有效,请将其发布为您自己问题的答案。【参考方案2】:
我通过使用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
要求您知道窗口标题的文本才能获取句柄。
【讨论】:
以上是关于基础表单消失但仅在显示对话框时的主要内容,如果未能解决你的问题,请参考以下文章
调用 facebook 对话框后 Flash (wmode=window) 消失
Facebook 分享对话框始终仅在 Android 上显示验证码
Feed Like对话框上的Facebook Like Button帖子消失了
尝试在 Django 中的表单上使用脆表单过滤器时收到“无效表单:脆”错误,但仅在一个 django 应用程序中而不是另一个?