C# 仅当显示对话框时,正在取消对窗体的填充

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窗体被隐藏时,您需要触发一个事件以获取窗口句柄

这与通过互操作显示C#表单的VB6应用程序有关

C#窗体中的事件会导致其中一个VB6应用程序窗体显示

通常,当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的警告不适用。让我们知道它是否有效-如果有效,请将其作为您自己问题的答案发布。