基础表单消失但仅在显示对话框时

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帖子消失了

显示对话框片段时与状态栏重叠,仅在Android4.4中

尝试在 Django 中的表单上使用脆表单过滤器时收到“无效表单:脆”错误,但仅在一个 django 应用程序中而不是另一个?

Android - 仅在 AsyncTask 未完成时单击按钮时显示进度对话框