我正在使用DirectShow.NET为WPF创建网络摄像头控件。我已经成功创建了一个图表,可以从相机中获取视频以显示在我的屏幕上。但是,视频输出完全独立于正在创建的WPF控件。
我通过调用videoWindow.put_owner(hWnd)
来设置视频窗口的所有者,其中hWnd
是当前WPF窗口的窗口句柄。我使用WindowInteropHelper
得到了那个窗口句柄。
这是主要例程:
public void CaptureVideo()
{
int hr = 0;
IBaseFilter sourceFilter = null;
try
{
hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
DsError.ThrowExceptionForHR(hr);
sourceFilter = FindCaptureDevice();
hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");
DsError.ThrowExceptionForHR(hr);
hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, null, null);
DsError.ThrowExceptionForHR(hr);
Marshal.ReleaseComObject(sourceFilter);
SetupVideoWindow();
hr = this.mediaControl.Run();
DsError.ThrowExceptionForHR(hr);
}
catch
{
Console.WriteLine("An unrecoverable DirectShow error has occurred.");
}
}
SetupVideoWindow()的代码:
public void SetupVideoWindow()
{
int hr = 0;
Window window = Window.GetWindow(this);
var wih = new WindowInteropHelper(window);
IntPtr hWnd = wih.Handle;
hr = this.videoWindow.put_Owner(hWnd);
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_WindowStyle(DirectShowLib.WindowStyle.Child | DirectShowLib.WindowStyle.ClipChildren);
DsError.ThrowExceptionForHR(hr);
this.videoWindow.SetWindowPosition(0, 0, (int)this.Width, (int)this.Height);
hr = this.videoWindow.put_Visible(OABool.True);
DsError.ThrowExceptionForHR(hr);
}
答案 0 :(得分:2)
特别是在窗口模式下运行的视频渲染器(同样适用于无窗口)要求您提供有效的HWND
窗口句柄,以便视频可以与标准UI准确集成。您的SetupVideoWindow
代码段正在准确初始化视频"作为子控件"。
WPF是一种新的UI概念,它不需要为每个UI控件创建窗口句柄,并且没有明确的直接属性来请求句柄以便传递给VMR初始化。因此,除了有效句柄之外,正确使用的WindowInteropHelper
在实际分配时才可用,这不是表单构造函数。
使用零句柄指示视频渲染器将视频发送到桌面窗口,您所看到的行为是可预期且易于理解的。
您需要使用调试器检查句柄值,如果它为零,则将配置代码移动到表单构造的稍后阶段。设置时非零有效窗口句柄应将视频放置到位。
答案 1 :(得分:0)
据我记忆,DirectShow使用直接视频内存访问在屏幕上显示内容以获得最佳性能,因此this.videoWindow.SetWindowPosition(0, 0, (int)this.Width, (int)this.Height);
很可能需要在屏幕坐标中。
即。你需要在屏幕上获取托管WPF窗口的位置和它的大小(使用WinApi),并传递给SetWindowPosition
方法。当窗口移动/调整大小时,每次都这样做。
很抱歉答案不完整(没有提供确切的代码来解决问题),因为我多年前在C ++中使用WinApi完成了这项工作。