1. 将以下四个dll拷贝到system32目录下,这几个文件均在根目录的Bin目录下
DS40xxSDK.dll
hikclient.dll
HikPlayM4.dll
HikServer.dll
2. 先用自带的客户端Net Client Demo(Soft Decdoe)运行下确认没有问题再根据VC++客户端的例子写对应的C#代码。
3. 最好装一个Microsoft Visual C++ 6.0,这样能把VC++的例子跑起来并调试。注意他是Win32 Release的,需要切换至Win32 Debug模式才能断点调试!!
4. 打开API文档Hikvision 板卡网络开发包编程手册V4.7,在Doc目录下。
5. 代码分析和编写对应的C#代码
5.1 第二章编程说明中第六条我们可以看到API依次调用的顺序,可以根据函数名直接在代码中搜索调用顺序,不难发现,在HKVisionDlg.cpp的OnInitDialog方法能看到如下两行代码:
MP4_ClientSetNetPort( 5050 , 6050 ); MP4_ClientStartup(WM_MYCOMMAND, this -> m_hWnd); 很明显这是调用了API,其他代码就不用管了,那么我把这代码翻译到C# WinForm的Form1_Load事件里面,并且也这样调用API(封装好的SDK请看上篇文章):
PcHikClient.MP4_ClientSetNetPort( 5050 , 6050 ); PcHikClient.MP4_ClientStartup(PcHikClient.WM_USER + 1 , this .Handle); 5.2 根据界面上Start按钮事件能找到关键的连接上服务器,如下:
if (m_showmode == 0 ) { MP4_ClientSetShowMode(NORMALMODE, 0 ); } else { MP4_ClientSetShowMode(OVERLAYMODE,COLORREF( 0xff00ff )); } nn1 = nn2 = nn3 = nn4 = - 1 ; int itemp = m_shownum; char ips[ 256 ]; sprintf(ips, " %s " ,m_ipadd); hWnd5 = m_video5.GetSafeHwnd(); // aa5.m_bRemoteChannel = 0 ; switch (m_linktype) { case 0 : aa5.m_bSendMode = TCPMODE; break ; case 1 : aa5.m_bSendMode = UDPMODE; break ; case 2 : aa5.m_bSendMode = MULTIMODE; break ; case 3 : aa5.m_bSendMode = DIALING; break ; case 4 : aa5.m_bSendMode = AUDIODETACH; break ; default : aa5.m_bSendMode = TCPMODE; break ; } aa5.m_sIPAddress = ips; // 2003.12.2 // 如果想只录像,而不进行解码,可以将m_hShowVideo设置成NULL // If you just want to record without decode on client side, // please set m_hShowVideo as NULL #if defined RECORD_ONLY aa5.m_hShowVideo = NULL; #else aa5.m_hShowVideo = hWnd5; #endif // add 2003.12.2 // m_nImgFormat 指明想要获取的图像格式 // 依赖服务器端的设置。如果不设置,获取的是服务器的缺省格式 // m_nImgFormat indicates the picture format you get on the client side, // It depends on the setting of Server side. aa5.m_nImgFormat = 0 ; // request CIF format // aa5.m_nImgFormat = 1; // request QCIF format aa5.m_sUserName = " 123 " ; aa5.m_sUserPassword = " w " ; aa5.m_bUserCheck = TRUE; MP4_ClientSetTTL( 64 ); nn1 = MP4_ClientStart( & aa5,ReadDataCallBack); if (nn1 == - 1 ) { MessageBox( " error " ); return ; } // BOOL breturn; breturn = MP4_ClientRigisterDrawFun(nn1,DrawFun, 0 ); switch (m_delaytype) { case 0 : MP4_ClientSetBufferNum(nn1, 40 ); MP4_ClientSetPlayDelay(nn1, 580 ); break ; case 1 : MP4_ClientSetBufferNum(nn1, 15 ); MP4_ClientSetPlayDelay(nn1, 40 ); break ; case 2 : MP4_ClientSetBufferNum(nn1, 15 ); MP4_ClientSetPlayDelay(nn1, 0 ); break ; case 3 : MP4_ClientSetBufferNum(nn1, 0 ); MP4_ClientSetPlayDelay(nn1, 0 ); break ; } // MP4_ClientThrowBFrame(nn1,m_bframenum); MP4_ClientSetCapPicCallBack(nn1,CapPicFun); 有VC++代码可以看得出来接下来代码都和这差不多,应该就是初始化显示四个窗口的代码了,那我们就不需要把这个方法里面的代码全部翻译了,只需要达到连接一个视频窗口的目的就可以了,翻译的过程中可以自己先临时设置一些变量来让代码跑起来,翻译过程中每次都执行到MP4_ClientRigisterDrawFun方法的时候就报错了,但是画面确已经出来了,所有我就从这里截断了,先达到目的再说,请看翻译对象的C#代码:
int cs; private void button1_Click( object sender, EventArgs e) { CLIENT_VIDEOINFO cVideo = new CLIENT_VIDEOINFO(); // 对应服务端通道号 cVideo.m_bRemoteChannel = ( byte ) 0 ; // 网络连接模式 cVideo.m_bSendMode = ( byte )SEND_MODE.TCPMODE; // 服务端IP地址 cVideo.m_sIPAddress = " 192.168.0.188" ; // 显示区域 cVideo.m_hShowVideo = pVideo.Handle; // (IntPtr)null; // 图像格式 cVideo.m_nImgFormat = ( byte ) 0 ; // 用户名 cVideo.m_sUserName = " 123 " ; // 密码 cVideo.m_sUserPassword = " w " ; // 是否需要发生密码 cVideo.m_bUserCheck = true ; // 设置多播的TTL参数 PcHikClient.MP4_ClientSetTTL(( char ) 64 ); // 启动客户端 cs = PcHikClient.MP4_ClientStart( ref cVideo, new ReadDataCallBack(MyRealDataCallBack1)); } private void MyRealDataCallBack1( ulong port, [MarshalAs(UnmanagedType.LPArray)] byte [] pBuffer, ulong pSize) { MessageBox.Show(pBuffer.Length.ToString()); } 需要注意的是,VC++里面的指针类型,如HWND一般可以对应C#里面的IntPtr数据类型,ReadDataCallBack是回调函数,但是没有执行,不过至此画面已经能够显示出来!!
那么接下来做画面切割,右键事件什么的都只需要你WinForm的开发经验了,我是用的四个面板(Panel)切换隐藏显示的;pVideo是Panel控件;用户名和密码随便设置也能连得上。
5.3 关闭连接
同样找到VC++代码:
if (nn1 >= 0 ) { MP4_ClientStopCapture(nn1); MP4_ClientStop(nn1); } 对应C#代码:
private void Close() { PcHikClient.MP4_ClientStopCapture(cs); PcHikClient.MP4_ClientStop(cs); pVideo.Invalidate( true ); } 需要注意的是这个cs变量,在连接的时候MP4_ClientStart返回值,需要拿全局变量保存起来,以便这里关闭的时候需要,从API文章里面我们也能看到这样的说明。这段代码最好在窗体关闭的时候也加上!!
本文转自博客园农民伯伯的博客,原文链接:,如需转载请自行联系原博主。