小能豆

WPF 调用海康SDK回放视频流,不用句柄方式,也不想嵌套winform控件

javascript

WPF 调用海康SDK回放视频流,不用句柄方式,也不想嵌套winform控件


阅读 51

收藏
2024-06-23

共1个答案

小能豆

在 WPF 中直接调用海康 SDK 进行视频回放,而不使用句柄方式或嵌套 WinForms 控件,是一个相对复杂的任务,因为海康 SDK 主要是为 WinForms 设计的。实现这种功能需要使用 Interop 技术来直接在 WPF 中操作低级的 Win32 API 和 DirectShow 接口。

下面是一个大致的步骤说明,如何在 WPF 中直接使用海康 SDK 进行视频回放,而不嵌套 WinForms 控件。

步骤 1: 创建 WPF 项目并添加引用

  1. 创建一个新的 WPF 项目。
  2. 确保海康 SDK 的 DLL 文件已添加到项目中,并在项目属性中将它们的“复制到输出目录”设置为“始终复制”。
  3. 引用 System.Runtime.InteropServices 命名空间,用于调用非托管代码。

步骤 2: 定义海康 SDK 的 P/Invoke

你需要使用 P/Invoke 来调用海康 SDK 的函数。这是一个示例定义:

using System;
using System.Runtime.InteropServices;

public class HikvisionSdk
{
    [DllImport("HCNetSDK.dll")]
    public static extern bool NET_DVR_Init();

    [DllImport("HCNetSDK.dll")]
    public static extern bool NET_DVR_Cleanup();

    // 其他需要的 P/Invoke 定义
}

步骤 3: 创建 HwndHost 以显示视频

由于 WPF 本身不支持直接操作窗口句柄(Hwnd),我们可以使用 HwndHost 来嵌入一个原生的窗口,以便海康 SDK 使用。

using System;
using System.Windows;
using System.Windows.Interop;

public class VideoHost : HwndHost
{
    private IntPtr _hwndHost;
    private IntPtr _hParentWnd;

    public VideoHost(IntPtr hParentWnd)
    {
        _hParentWnd = hParentWnd;
    }

    protected override HandleRef BuildWindowCore(HandleRef hwndParent)
    {
        _hwndHost = CreateWindowEx(0, "static", "",
            WS_CHILD | WS_VISIBLE,
            0, 0, (int)Width, (int)Height,
            hwndParent.Handle,
            (IntPtr)HOST_ID,
            IntPtr.Zero,
            0);

        return new HandleRef(this, _hwndHost);
    }

    protected override void DestroyWindowCore(HandleRef hwnd)
    {
        DestroyWindow(hwnd.Handle);
    }

    [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Auto)]
    private static extern IntPtr CreateWindowEx(int dwExStyle, string lpszClassName,
        string lpszWindowName, int style,
        int x, int y, int width, int height,
        IntPtr hwndParent, IntPtr hMenu, IntPtr hInst, [MarshalAs(UnmanagedType.AsAny)] object pvParam);

    [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Auto)]
    private static extern bool DestroyWindow(IntPtr hwnd);

    private const int WS_CHILD = 0x40000000;
    private const int WS_VISIBLE = 0x10000000;
    private const int HOST_ID = 0x00000002;
}

步骤 4: 在 WPF 窗体中使用 VideoHost

public partial class MainWindow : Window
{
    private VideoHost _videoHost;

    public MainWindow()
    {
        InitializeComponent();
        Loaded += MainWindow_Loaded;
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        _videoHost = new VideoHost(new WindowInteropHelper(this).Handle);
        hostContainer.Child = _videoHost; // hostContainer 是一个 WindowsFormsHost
        InitSdk();
        PlayVideo();
    }

    private void InitSdk()
    {
        HikvisionSdk.NET_DVR_Init();
    }

    private void PlayVideo()
    {
        // 使用海康 SDK 播放视频
        // 使用 _videoHost.Handle 作为视频播放的句柄
    }

    protected override void OnClosed(EventArgs e)
    {
        HikvisionSdk.NET_DVR_Cleanup();
        base.OnClosed(e);
    }
}

步骤 5: XAML 中的布局

在 XAML 中添加一个容器,例如 WindowsFormsHost,来承载 VideoHost

<Window x:Class="YourNamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <WindowsFormsHost x:Name="hostContainer" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
    </Grid>
</Window>

总结

上述步骤演示了如何在 WPF 中使用 HwndHost 来嵌入一个原生窗口,并使用海康 SDK 播放视频。这个方法不使用句柄方式和 WinForms 控件,而是直接在 WPF 中创建一个可供 SDK 使用的窗口句柄。具体的播放逻辑需要根据海康 SDK 的文档来实现。

2024-06-23