一、前言
海康威视桌面板开发,追求简单快捷高效可选择Winform进行开发,追求界面好看当然自然需要选择WPF进行开发,WPF在布局也界面效果展示上面可以做的很漂亮。
WPF 和 Winform 开发类似,基本流程都是:1、海康SDK初始化;2、账号密码登录海康设备;3、传递画面播放句柄打开预览;
Winform中通常使用 PictureBox 组件进行画面播放,但是WPF中没有这个组件,通常做法是采用 WPF内嵌一个Winrom的PictureBox组件;
测试环境:VS2019+WPF+.Net5.0
二、步骤
1、界面布局准备:
WPF内嵌Winform PictureBox核心代码:
<WindowsFormsHost x:Name="Video_PBX" Background="#f8f8f9" HorizontalAlignment="Stretch" Grid.Row="0" >
<wf:PictureBox x:Name="Video_PBX_01" Cursor="Hand"/>
</WindowsFormsHost>
2、海康威视SDK初始化:
- 需要去官网下载海康SDK(若干Dll文件):
无需在项目引用,把整个HKWSDLL文件夹放在程序根目录 - 需要引用SDK各种方法的C#封装类CHCNetSDK.cs(1.5万行代码):
添加到项目中方便使用,注意代码中Dll引用路径要对 [DllImport(@“HKWSDLL\HCNetSDK.dll”)] - 海康SDK初始化:
if (CHCNetSDK.NET_DVR_Init())
{
MessageBox.Show("1、海康威视SDK初始化成功!");
}
3、准备登录相关参数信息:
DeviceDto tmpDeviceDto = new()
{
Name = "测试设备",
Login_Account = "admin",
Login_Password = "1234qwer",
LocalLogin_Port = 8000,
LocalLogin_IPAddress = "172.24.0.168"
};
//各种函数返回结果封装
public class MsgReturnedDto
{
public bool Success { get; set; }
public string Error { get; set; }
public string MsgType { get; set; }
public dynamic Result { get; set; }
public MsgReturnedDto(bool success = true, string error = "", object result = null, string msgtype = "")
{
Success = success;
Error = error;
Result = result;
MsgType = msgtype;
}
}
4、登录设备:
//海康登录成功后返回的设备基础信息
private CHCNetSDK.NET_DVR_DEVICEINFO_V30 DeviceInfo_V30 = new CHCNetSDK.NET_DVR_DEVICEINFO_V30();
private int UserId=-1;//登录成功后返回的用户编号:作为其他功能调用的参数
public MsgReturnedDto Login(DeviceDto DeviceInfo)
{
this.UserId = CHCNetSDK.NET_DVR_Login_V30(DeviceInfo.LocalLogin_IPAddress, DeviceInfo.LocalLogin_Port, DeviceInfo.Login_Account, DeviceInfo.Login_Password, ref DeviceInfo_V30);
if (this.UserId == HandleInfo.NOT_ON_PATROL)
{
uint tmpCode = CHCNetSDK.NET_DVR_GetLastError();
string tmpMsg = $"登录失败:{tmpCode}";
return new MsgReturnedDto(false, tmpMsg);
}
return new MsgReturnedDto(true, "登录成功");
}
5、开启预览:注意画面播放句柄
private int RealPlayHandle =-1;//开启预览成功返回句柄
public IntPtr PlayWnd =this.Video_PBX_01.Handle;//【重点】播放画面句柄
public MsgReturnedDto StartRealPlay()
{
//1、尝试停止预览 保证上次其他环节失败 导致重新打开预览失败
if (this.RealPlayHandle != -1)
{
CHCNetSDK.NET_DVR_StopRealPlay(this.RealPlayHandle);
}
//2、全局存储预览回调函数
if (this.RealPlayDataCallBackMethod == null)
{
//预览实时流回调函数:可以自己对视频流进行解码操作 比如衔接自己的画面捕捉识别等功能
this.RealPlayDataCallBackMethod = new CHCNetSDK.REALDATACALLBACK(this.RealDataCallBack);
}
//3、预览参数配置
IntPtr pUser = new IntPtr();//用户数据
CHCNetSDK.NET_DVR_PREVIEWINFO lpPreviewInfo = new CHCNetSDK.NET_DVR_PREVIEWINFO();
lpPreviewInfo.hPlayWnd = this.PlayWnd;//预览窗口 播放画面句柄 PictureBox组件句柄
lpPreviewInfo.lChannel = 1; //Int16.Parse(textBoxChannel.Text);//预览的设备通道
lpPreviewInfo.dwStreamType = 0;//码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推
lpPreviewInfo.dwLinkMode = 0;//连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP
lpPreviewInfo.bBlocked = true; //0- 非阻塞取流,1- 阻塞取流
lpPreviewInfo.dwDisplayBufNum = 1; //播放库播放缓冲区最大缓冲帧数
lpPreviewInfo.byProtoType = 0;
lpPreviewInfo.byPreviewMode = 0;
//4、打开预览 Start live view
this.RealPlayHandle = CHCNetSDK.NET_DVR_RealPlay_V40(this.UserId, ref lpPreviewInfo, null/*RealData*/, pUser);
//5、预览出错捕捉错误并返回
if (this.RealPlayHandle == -1)
{
uint tmpCode = CHCNetSDK.NET_DVR_GetLastError();
return new MsgReturnedDto(false, string.Format("单设备打开预览失败:", tmpCode));
}
//6、打开预览成功
return new MsgReturnedDto(true, "打开预览成功");
}
/// <summary>
/// 实时播放数据回调函数
/// </summary>
public void RealDataCallBack(Int32 lRealHandle, UInt32 dwDataType, IntPtr pBuffer, UInt32 dwBufSize, IntPtr pUser)
{
if (dwBufSize <= 0)
{
return;
}
byte[] sData = new byte[dwBufSize];
Marshal.Copy(pBuffer, sData, 0, (Int32)dwBufSize);
string str = "实时流数据.ps";
FileStream fs = new FileStream(str, FileMode.Create);
int iLen = (int)dwBufSize;
fs.Write(sData, 0, iLen);
fs.Close();
}
6、特别说明:
- 为了测试方便可以把上述代码直接放到 WPF页面的 .cs代码中;
- 优雅一点儿的做法是把上面的代码封装到一个独立的类里面方便使用;
7、结果欣赏:
三、总结
差不多就是这么个流程,对你有帮助不放收藏点赞一波,没有的素材内容可以加我微信索要:qingwatianya