【问题标题】:Constant flickering in C++ Windows desktop app when a child window is made the child of a C# desktop app?当子窗口成为 C# 桌面应用程序的子窗口时,C++ Windows 桌面应用程序中的持续闪烁?
【发布时间】:2015-06-20 19:44:50
【问题描述】:

我已使用以下 SO 帖子中的信息使我的 C++ 桌面应用程序中的图片控件的父级成为我的 C# 应用程序中的面板控件的子级。 C++ 和 C# 应用程序是在各自进程中运行的独立应用程序:

Various issues using SetParent to embed window into external process

Embedding HWND into external process using SetParent

我正在使用下面显示的代码进行重新育儿。 C# 应用程序启动 C++ 应用程序,并在命令行上将 Panel 控件的 Windows 句柄传递给它,该控件应承载 C++ 应用程序的 Picture 控件。当我运行 C# 应用程序时,我确实在 C# 应用程序本机的指定 Panel 控件上看到了 C++ Picture 控件的轮廓。

但是,我遇到了以下问题:

1) C++ 和 C# 应用程序都闪烁得非常厉害,就好像它们都在一秒钟内被重新绘制了很多次一样。

2) C++ 应用程序中的图片控件通常显示来自我的网络摄像头的视频源。我 BitBlt() 将网络摄像头中的帧放入 C++ 图片控件中。没有重新养育它可以正常工作,但有了它,我根本看不到任何框架。

注意:闪烁绝对是绘制到现在重新设置父级的子窗口的结果。如果我禁用该操作,则不会发生闪烁。

有谁知道出了什么问题以及我该如何解决?这是 C++ 应用程序中的代码,它执行重新父级处理并将 C++ 主输入线程(拥有图片控件的线程)附加到属于 C# 应用程序主线程的输入线程(拥有的线程面板控件):

// The following code executes in the wWinMain() function of the C++
//  app after the main dialog window and it's child controls have been
//  setup and initialized.  The value assigned to g_VideoHostContainerHWnd
//  was passed to the C++ app by the C# app that launched it, as a 
//  command line argument, using the Panel control's Handle property
//  converted to an unsigned integer.
g_OurMainThreadID = GetCurrentThreadId();

if (g_VideoHostContainerHWnd > 0)
{
    // Make our video stream window a parent of the designated window
    //  in the HiveMind client.

    // Get the window handle for the video stream window: IDC_PANEL_PICTURE.
    HWND videoStreamWindow =
        GetDlgItem(
        g_HwndDlg,
        IDC_PANEL_PICTURE);

    if (videoStreamWindow > 0)
    {
        // Get the thread ID for the thread that owns the video host container window.

         g_VideoHostThreadID = GetWindowThreadProcessId(
            g_VideoHostContainerHWnd,
            &g_VideoHostProcessID);

         if (g_VideoHostThreadID > 0)
         {
             // Make the video stream window a child of the HiveMindClient window.
             if (NULL == SetParent(videoStreamWindow, g_VideoHostContainerHWnd))
                 OutputDebugString(L"The reparenting of the video stream window FAILED.");
             else
                 OutputDebugString(L"The reparenting of the video stream window SUCCEEDED.");

             // Attach the our input thread to the thread ID for the process that launched us
             //  (i.e. - owns the video host window).
             if (AttachThreadInput(g_OurMainThreadID, g_VideoHostThreadID, true))
                 OutputDebugString(L"Attaching our input thread to the video host thread SUCCEEDED.");
             else
                 OutputDebugString(L"Attaching our input thread to the video host thread FAILED.");
         }
         else
         {
             OutputDebugString(L"The thread ID of the video host container's owner thread is ZERO.");
         } // else - if (g_VideoHostThreadID > 0)
    }
    else
        OutputDebugString(L"The video stream window handle is INVALID.");
} // if (g_VideoHostContainerHWnd > 0)

【问题讨论】:

  • 这行不通。放弃吧。
  • @DavidHeffernan Unity 3D 应用程序使用其 parentHWND 命令行参数完美地做到了这一点,所以这不是真的:forum.unity3d.com/threads/…
  • 我不相信。你可以使用 SetParent 跨进程是一个 Win16 回兼容的 bodge。看起来您负责所有代码。让它成为一个过程。
  • Unity 3D 使用 GDI 还是使用 opengl/direct X?闪烁通常是由于强制系统重绘而不是在位图中缓冲绘图并在绘制时对其进行模糊处理而引起的。 C++ 代码是直接在屏幕上绘制还是仅在获得 WM_PAINT 时才绘制?

标签: c# c++ multithreading winapi cross-process


【解决方案1】:

我也遇到了这个问题,解决方法是父hwnd需要标志WS_CLIPCHILDREN。

【讨论】:

  • 你对这个答案的参考是什么?
猜你喜欢
  • 2012-04-11
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 2011-06-01
  • 2020-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多