using AForge.Imaging;
using AForge.Video.FFMPEG;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Shapes;
using static AForge.Imaging.Filters.HitAndMiss;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace videoGather
{
public partial class video : Form
{
public video()
{
InitializeComponent();
}
#region 属性
///
/// 设备源
/// 用来操作摄像头
///
private AForge.Video.DirectShow.VideoCaptureDevice videoCapture;
///
/// 摄像头设备集合
///
private AForge.Video.DirectShow.FilterInfoCollection infoCollection;
///
/// 图片
///
private System.Drawing.Bitmap imgMap;
///
/// 文件保存路径
///
private readonly string filePath = Application.StartupPath + @"\";
///
/// 文件名称
///
private readonly string fileName = $"{DateTime.Now.ToString("yyyyMMddhhmmssffff")}";
///
/// 用与把每一帧图像写入到视频文件
///
private AForge.Video.FFMPEG.VideoFileWriter videoWriter;
///
/// 是否开始录像
///
private bool IsStartVideo = false;
///
/// 写入次数
///
private int tick_num = 0;
///
/// 录制多少小时,只是为了定时间计算录制时间使用
///
private int Hour = 0;
///
/// 计时器
///
private System.Timers.Timer timer_count;
///
/// 视频保存名称
///
private string videoName = string.Empty;
///
/// 路径地址
///
private string _url = string.Empty;
private string _path = string.Empty;
///
/// 当前类型
///
private string _type = string.Empty;
///
/// 病理截图临时存放位置
///
private string _blpath = string.Empty;
///
/// 病理访问前缀
///
private string _blprefix = string.Empty;
///
/// 病理截图热键
///
private string strkey = string.Empty;
///
/// 区域截图设置
///
private string _xywh = string.Empty;
///
/// 文件上传模式
///
private string _model = string.Empty;
//超声存放文件访问地址
ArrayList imagearray = new ArrayList();
///
/// 存放双击选择的患者数据
///
private HisInfo rowhisinfo;
///
/// 存放自己新增的数据源
///
List hisInfos = new List();
#endregion
#region 窗口加载与关闭
///
/// 讲题加载事件
///
///
///
private void Form1_Load(object sender, EventArgs e)
{
dGVPatient.AutoGenerateColumns = false;
InitCamera();
InitCameraSelect();
//读取配置信息
_url = ConfigurationManager.AppSettings["URL"];
_path = ConfigurationManager.AppSettings["path"];
_type = ConfigurationManager.AppSettings["type"];
_blpath = ConfigurationManager.AppSettings["blpath"];
strkey = ConfigurationManager.AppSettings["strkey"];
_blprefix = ConfigurationManager.AppSettings["blprefix"];
_xywh = ConfigurationManager.AppSettings["xywh"];
_model = ConfigurationManager.AppSettings["model"];
if (_type == "1")
{
gb_ButtonBox.Visible = true;
groupBox2.Visible = false;
}
else if (_type == "2")
{
gb_ButtonBox.Visible = false;
groupBox2.Visible = true;
txt_x.Enabled = false;
txt_y.Enabled = false;
txt_w.Enabled = false;
txt_h.Enabled = false;
txt_x.Text = _xywh.Split(',')[0];
txt_y.Text = _xywh.Split(',')[1];
txt_w.Text = _xywh.Split(',')[2];
txt_h.Text = _xywh.Split(',')[3];
}
this.btn_Capture.Enabled = false;
//秒表
timer_count = new System.Timers.Timer(); //实例化Timer类,设置间隔时间为1000毫秒;
timer_count.Elapsed += new System.Timers.ElapsedEventHandler(tick_count); //到达时间的时候执行事件;
timer_count.AutoReset = true; //设置是执行一次(false)还是一直执行(true);
timer_count.Interval = 1000;
HookStart();
btn_Connect_Click(null, null);
GetHisInfo();
label4.Focus();
}
///
/// 窗口关闭时
///
///
///
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
EndCamera();
}
#endregion
#region 实例化
///
/// 实例化摄像头
///
public void InitCamera()
{
try
{
//检测电脑上的摄像头设备
infoCollection = new AForge.Video.DirectShow.FilterInfoCollection(AForge.Video.DirectShow.FilterCategory.VideoInputDevice);
}
catch (Exception ex)
{
MessageBox.Show($"没有找到设备:{ex.Message}", "Error");
}
}
//加载摄像头选择
public void InitCameraSelect()
{
this.cb_CameraSelect.DropDownStyle = ComboBoxStyle.DropDownList;
//根据读取到的摄像头加载选择项
foreach (AForge.Video.DirectShow.FilterInfo item in infoCollection)
{
this.cb_CameraSelect.Items.Add(item.Name);
}
//for (int i = 1; i <= infoCollection.Count; i++)
//{
// this.cb_CameraSelect.Items.Add("摄像头" + i);
//}
if (cb_CameraSelect.Items.Count > 0)
{
cb_CameraSelect.SelectedIndex = 0;
}
}
#endregion
#region 连接读取与关闭
///
/// 连接按钮
///
///
///
private void btn_Connect_Click(object sender, EventArgs e)
{
var CameraSelect = this.cb_CameraSelect.Text;
var selectIndex = this.cb_CameraSelect.SelectedIndex;
if (string.IsNullOrEmpty(CameraSelect))
{
MessageBox.Show("请先选择视频源");
return;
}
//已有连接的摄像头时先关闭
if (videoCapture != null)
{
EndCamera();
}
videoCapture = new AForge.Video.DirectShow.VideoCaptureDevice(infoCollection[selectIndex].MonikerString);
//启动摄像头
this.vsp_Panel.VideoSource = videoCapture;
this.vsp_Panel.Start();
this.btn_Capture.Enabled = true;
}
///
/// 关闭按钮
///
///
///
private void btn_Close_Click(object sender, EventArgs e)
{
HookStop();
EndCamera();
}
///
/// 关闭摄像头
///
public void EndCamera()
{
if (this.vsp_Panel.VideoSource != null)
{
//也可以用 Stop() 方法关闭
//指示灯停止且等待
this.vsp_Panel.SignalToStop();
//停止且等待
this.vsp_Panel.WaitForStop();
this.vsp_Panel.VideoSource = null;
}
}
#endregion
#region 拍照与保存
///
/// 拍照
///
///
///
private void btn_Capture_Click(object sender, EventArgs e)
{
if (videoCapture == null)
{
MessageBox.Show("设备未连接");
return;
}
imgMap = this.vsp_Panel.GetCurrentVideoFrame();
if (imgMap == null)
{
return;
}
var saveName = $"{filePath}{$"{DateTime.Now.ToString("yyyyMMddhhmmssffff")}"}.jpg";
imgMap.Save(saveName);
imagearray.Add(saveName);
label1.Text = imagearray.Count.ToString();
}
///
/// 保存事件
///
///
///
private void btn_Save_Click(object sender, EventArgs e)
{
}
#endregion
#region 录像
///
/// 开始录像
///
///
///
private void btn_StartVideo_Click(object sender, EventArgs e)
{
if (videoCapture == null)
{
MessageBox.Show("设备未连接");
return;
}
if (rowhisinfo == null)
{
MessageBox.Show("请选择患者");
return;
}
btn_StartVideo.Enabled = false;
videoName = $"{filePath}{fileName}.mp4";
IsStartVideo = true;
//开始计时
timer_count.Enabled = true;
//配置录像参数(宽,高,帧率,比特率等参数)VideoCapabilities这个属性会返回摄像头支持哪些配置,从这里面选一个赋值接即可
videoCapture.VideoResolution = videoCapture.VideoCapabilities[0];
//设置回调,aforge会不断从这个回调推出图像数据
videoCapture.NewFrame += Camera_NewFrame;
videoWriter = new AForge.Video.FFMPEG.VideoFileWriter();
//打开摄像头
//videoCapture.Start();
int videoBitrate = 5000000; // 1000 Kbps
//打开录像文件(如果没有则创建,如果有也会清空),这里还有关于视频宽高、帧率、格式、比特率
videoWriter.Open(
videoName,
videoCapture.VideoResolution.FrameSize.Width,
videoCapture.VideoResolution.FrameSize.Height,
videoCapture.VideoResolution.AverageFrameRate,
AForge.Video.FFMPEG.VideoCodec.MPEG4,
videoBitrate
);
}
//this.lab_Time
//摄像头输出回调
private void Camera_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
{
imgMap = eventArgs.Frame;
lock (imgMap)
{
if (eventArgs != null && eventArgs.Frame != null)
{
try
{
//写到文件
videoWriter.WriteVideoFrame(eventArgs.Frame);
}
catch (Exception ex)
{
//MessageBox.Show("写入文件错误"+ex.Message);
}
}
}
}
///
/// 暂停录像
///
///
///
private void btn_PauseVideo_Click(object sender, EventArgs e)
{
if (videoCapture == null)
{
MessageBox.Show("设备未连接");
return;
}
var stopBtnName = this.btn_PauseVideo.Text;
if (stopBtnName == "暂停录像")
{
this.btn_PauseVideo.Text = "恢复录像";
//暂停计时
timer_count.Enabled = false;
IsStartVideo = false;
}
if (stopBtnName == "恢复录像")
{
this.btn_PauseVideo.Text = "暂停录像";
//恢复计时
timer_count.Enabled = true;
IsStartVideo = true;
}
}
///
/// 停止录像
///
///
///
private void btn_EndVideo_Click(object sender, EventArgs e)
{
if (videoCapture == null)
{
MessageBox.Show("设备未连接");
return;
}
btn_StartVideo.Enabled = true;
IsStartVideo = false;
timer_count.Enabled = false;
if (videoWriter != null)
{
videoWriter.Close();
}
tick_num = 0;
}
#endregion
#region 计时器响应函数
///
/// 计时器
///
///
///
public void tick_count(object source, System.Timers.ElapsedEventArgs e)
{
tick_num++;
int Temp = tick_num;
int Second = Temp % 60;
int Minute = Temp / 60;
if (Minute % 60 == 0)
{
Hour = Minute / 60;
Minute = 0;
}
else
{
Minute = Minute - Hour * 60;
}
string HourStr = Hour < 10 ? $"0{Hour}" : Hour.ToString();
string MinuteStr = Minute < 10 ? $"0{Minute}" : Minute.ToString();
string SecondStr = Second < 10 ? $"0{Second}" : Second.ToString();
String tick = $"{HourStr}:{MinuteStr}:{SecondStr}";
this.Invoke((EventHandler)(delegate
{
this.lab_Time.Text = tick;
}));
}
#endregion
///
/// 视频上传
///
///
///
private void button1_Click(object sender, EventArgs e)
{
}
#region 请求接口
private void UploadFileUrl(string filename, string filetype)
{
if (!string.IsNullOrEmpty(filename) && !string.IsNullOrEmpty(filetype))
{
string imgType = "1";//1图片2 视频
string ID = string.Empty;
string imagebase = string.Empty;
string imgDescription = "超声图像";
string orgId = string.Empty;
if (filetype == ".mp4")
{
imgType = "2";
imgDescription = "超声视频";
}
imagebase = _path + @"/" + rowhisinfo.jianchaid + "/" + filename;
ID = rowhisinfo.jianchaid;
orgId = rowhisinfo.yiyuancode;
insimagescreenshotVO vO = new insimagescreenshotVO();
vO.id = ID;
vO.imagebase = imagebase;
vO.imgDescription = imgDescription;
vO.imgType = imgType;
vO.orgId = orgId;
var json = JsonConvert.SerializeObject(vO);
string msg = Post(_url + "/admin-api/ultrasoniccom/ultrasonic/insimagescreenshot", json);
}
}
///
/// 指定Post地址使用Get 方式获取全部字符串
///
/// 请求后台地址
/// Post提交数据内容(utf-8编码的)
///
public static string Post(string url, string content)
{
string result = "";
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/json";
#region 添加Post 参数
byte[] data = Encoding.UTF8.GetBytes(content);
req.ContentLength = data.Length;
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(data, 0, data.Length);
reqStream.Close();
}
#endregion
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();
//获取响应内容
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
result = reader.ReadToEnd();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return result;
}
///
/// 指定Post地址使用Get 方式获取全部字符串
///
/// 请求后台地址
/// Post提交数据内容(utf-8编码的)
///
public static string Post(string url, string content, string headerKey, string headerValue)
{
string result = "";
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "application/json";
req.Headers[headerKey] = headerValue;
#region 添加Post 参数
byte[] data = Encoding.UTF8.GetBytes(content);
req.ContentLength = data.Length;
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(data, 0, data.Length);
reqStream.Close();
}
#endregion
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Stream stream = resp.GetResponseStream();
//获取响应内容
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
result = reader.ReadToEnd();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return result;
}
///
/// Get请求
///
/// 请求url
///
public static string Get(string url)
{
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "GET";
req.Timeout = 30000;
if (req == null || req.GetResponse() == null)
{
MessageBox.Show("请求对象为空");
return string.Empty;
}
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
if (resp == null)
{
MessageBox.Show("响应对象为空");
return string.Empty;
}
using (var stream = resp.GetResponseStream())
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
var content = new StringBuilder();
char[] buffer = new char[1024];
int read;
while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
{
content.Append(new string(buffer, 0, read));
}
return content.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show("发生错误: " + ex.Message);
return string.Empty;
}
}
///
/// Get请求
///
///
///
///
///
public static string Get(string url, string headerKey, string headerValue)
{
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "GET";
req.Timeout = 30000;
req.Headers[headerKey] = headerValue;
if (req == null || req.GetResponse() == null)
{
MessageBox.Show("请求对象为空");
return string.Empty;
}
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
if (resp == null)
{
MessageBox.Show("响应对象为空");
return string.Empty;
}
using (var stream = resp.GetResponseStream())
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
var content = new StringBuilder();
char[] buffer = new char[1024];
int read;
while ((read = reader.Read(buffer, 0, buffer.Length)) > 0)
{
content.Append(new string(buffer, 0, read));
}
return content.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show("发生错误: " + ex.Message);
return string.Empty;
}
}
///
/// 获取HIS患者信息
///
public void GetHisInfo()
{
//存放绑定界面的患者数据 一个患者有多个检查 按照检查拆分 一个检查一条数据
List hisInfos = new List();
//获取福乐云HIS接口的token
string hisToken = getHisToken(ConfigurationManager.AppSettings["hisGetTokenUrl"], ConfigurationManager.AppSettings["hisAppkey"], ConfigurationManager.AppSettings["appsecret"]);
//获取当天的患者信息
FlyHisEcgDataModel FHEDM = GetHisEcgData(ConfigurationManager.AppSettings["hisGetDataUrl"], ConfigurationManager.AppSettings["inHisCode"], DateTime.Now.ToString("yyyy-MM-dd"), hisToken);//
if (FHEDM != null)
{
foreach (patientInfo item in FHEDM.rows)
{
foreach (projectsInfo projectsInfo in item.projects)
{
if (projectsInfo.category == "US")
{
HisInfo info = new HisInfo();
info.jianchaid = item.jianchaid;
info.name = item.name;
info.jianchabh = item.jianchabh;
info.sfz = item.sfz;
info.birthdate = item.birthdate;
info.age = item.age;
info.sex = item.sex;
info.yiyuanname = item.yiyuanname;
info.yiyuanid = item.yiyuanid;
info.yiyuancode = item.yiyuancode;
info.kaifangsj = item.kaifangsj;
info.departmentCode = item.departmentCode;
info.departmentName = item.departmentName;
info.resDoctorName = item.resDoctorName;
info.resDoctorCode = item.resDoctorCode;
info.nation = item.nation;
info.patientCode = item.patientCode;
info.visitType = item.visitType;
info.jianchamingcheng = projectsInfo.jianchamingcheng;
info.nhbm = projectsInfo.nhbm;
info.category = projectsInfo.category;
hisInfos.Add(info);
}
}
}
dGVPatient.DataSource = hisInfos;
rowhisinfo = null;
}
}
///
/// 获取福乐云HIS系统的token
///
///
///
///
public string getHisToken(string url1, string appkey, string appsecret)
{
Dictionary dic = new Dictionary();
dic.Add("appkey", appkey);
dic.Add("appsecret", appsecret);
string resultV = PostFile3(url1, dic);
FlyHisTokenMsgModel tm = JsonConvert.DeserializeObject(resultV);
return tm.data.access_token;
}
///
/// 获取福乐云HIS系统的患者基本信息
///
///
///
///
public FlyHisEcgDataModel GetHisEcgData(string url1, string Yiyuanid, string kaifangsj, string token)
{
Dictionary dic = new Dictionary();
dic.Add("Yiyuanid", Yiyuanid);
dic.Add("dateStart", kaifangsj);
dic.Add("dateEnd", kaifangsj);
dic.Add("token", token);
string resultV = PostFile3(url1, dic);
FlyHisEcgDataModel tm = JsonConvert.DeserializeObject(resultV);
return tm;
}
///
/// post form-data 参数
///
///
///
///
public string PostFile3(string url, Dictionary items)
{
string boundary = DateTime.Now.Ticks.ToString("x");
HttpWebRequest request = null;
//如果是发送HTTPS请求
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
{
//处理HttpWebRequest访问https有安全证书的问题( 请求被中止: 未能创建 SSL/TLS 安全通道。)
ServicePointManager.ServerCertificateValidationCallback += (s, cert, chain, sslPolicyErrors) => true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
//ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
request = WebRequest.Create(url) as HttpWebRequest;
request.ProtocolVersion = HttpVersion.Version10;
}
else
{
request = WebRequest.Create(url) as HttpWebRequest;
}
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Method = "POST";
// request.Headers.Add("Authorization", "Bearer " + token);
// 最后的结束符
var endBoundary = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
//文件数据
string fileFormdataTemplate =
"--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" +
"\r\nContent-Type: application/octet-stream" +
"\r\n\r\n";
//文本数据
string dataFormdataTemplate =
"\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"" +
"\r\n\r\n{1}";
//FileInfo fi = new FileInfo(filePath);
//string fileHeader = string.Format(fileFormdataTemplate, "file", fi.Name);
//var fileBytes = Encoding.UTF8.GetBytes(fileHeader);
using (var postStream = new MemoryStream())
{
////写入文件格式串
//postStream.Write(fileBytes, 0, fileBytes.Length);
//#region 写入文件流
//using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
//{
// byte[] buffer = new byte[1024];
// int bytesRead = 0;
// while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0)
// {
// postStream.Write(buffer, 0, bytesRead);
// }
//}
//#endregion
#region 写入其他表单参数
foreach (KeyValuePair key in items)
{
var p = string.Format(dataFormdataTemplate, key.Key, key.Value);
var bp = Encoding.UTF8.GetBytes(p);
postStream.Write(bp, 0, bp.Length);
}
#endregion
//写入结束边界
postStream.Write(endBoundary, 0, endBoundary.Length);
#region 写入流
request.ContentLength = postStream.Length;
postStream.Position = 0;
using (Stream ds = request.GetRequestStream())
{
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0)
{
ds.Write(buffer, 0, bytesRead);
}
}
#endregion
#region 获取返回值
string result = string.Empty;
using (HttpWebResponse rep = (HttpWebResponse)request.GetResponse())
{
using (Stream ds = rep.GetResponseStream())
{
using (StreamReader sr = new StreamReader(ds))
{
result = sr.ReadToEnd();
}
}
}
return result;
#endregion
}
}
#endregion
#region 视频转换
///
/// 转换文件
///
///
/// 转换后文件
private string ConvertVideo(string filename)
{
Process p = new Process();
p.StartInfo.FileName = Application.StartupPath + @"\ffmpeg\" + "ffmpeg";
//p.StartInfo.FileName = path + "ffmpeg.exe";
p.StartInfo.UseShellExecute = false;
string srcFileName = "";
srcFileName = "\"" + filename + "\"";
string destFileName = Application.StartupPath + "\\" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".mp4";
//-preset:指定编码的配置。x264编码算法有很多可供配置的参数,
//不同的参数值会导致编码的速度大相径庭,甚至可能影响质量。
//为了免去用户了解算法,然后手工配置参数的麻烦。x264提供了一些预设值,
//而这些预设值可以通过preset指定。这些预设值有包括:
//ultrafast,superfast,veryfast,faster,fast,medium,slow,slower,veryslow和placebo。
//ultrafast编码速度最快,但压缩率低,生成的文件更大,placebo则正好相反。x264所取的默认值为medium。
//需要说明的是,preset主要是影响编码的速度,并不会很大的影响编码出来的结果的质量。
//-crf:这是最重要的一个选项,用于指定输出视频的质量,取值范围是0-51,默认值为23,数字越小输出视频的质量越高。
//这个选项会直接影响到输出视频的码率。一般来说,压制480p我会用20左右,压制720p我会用16-18,1080p我没尝试过。
//个人觉得,一般情况下没有必要低于16。最好的办法是大家可以多尝试几个值,每个都压几分钟,看看最后的输出质量和文件大小,自己再按需选择。
p.StartInfo.Arguments = "-i " + srcFileName + " -y -vcodec h264 -threads " + 1 + " -crf " + 25 + " " + "\"" + destFileName + "\""; //执行参数
p.StartInfo.UseShellExecute = false; ////不使用系统外壳程序启动进程
p.StartInfo.CreateNoWindow = true; //不显示dos程序窗口
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中
p.ErrorDataReceived += new DataReceivedEventHandler(p_ErrorDataReceived);
p.OutputDataReceived += new DataReceivedEventHandler(p_OutputDataReceived);
p.StartInfo.UseShellExecute = false;
p.Start();
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.BeginErrorReadLine();//开始异步读取
p.WaitForExit();//阻塞等待进程结束
p.Close();//关闭进程
p.Dispose();//释放资源
return destFileName.TrimStart('\\');
}
private static void p_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
//WriteLog(e.Data);
}
private static void p_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
//WriteLog(e.Data);
}
#endregion
#region 病理相关
///
/// 开启或关闭全局监测
///
///
///
private void button2_Click(object sender, EventArgs e)
{
var CameraSelect = this.cb_CameraSelect.Text;
if (string.IsNullOrEmpty(CameraSelect))
{
MessageBox.Show("请先选择视频源");
return;
}
if (button2.Text == "开启截图")
{
HookStart();
button2.Text = "关闭截图";
}
else if (button2.Text == "关闭截图")
{
HookStop();
button2.Text = "开启截图";
}
}
///
/// 保存病理截图并且转换成dcm
///
private void SaveImageDcm()
{
Bitmap currentFrame = this.vsp_Panel.GetCurrentVideoFrame();
if (currentFrame != null)
{
//开启区域截图
if (checkBox1.Checked)
{
int x = int.Parse(txt_x.Text.Trim());
int y = int.Parse(txt_y.Text.Trim());
int w = int.Parse(txt_w.Text.Trim());
int h = int.Parse(txt_h.Text.Trim());
// 定义你想要裁剪的区域 imgMap
System.Drawing.Rectangle region = new System.Drawing.Rectangle(x, y, w, h); // 例如,从(10,10)开始,宽100,高100的区域
// 裁剪图像区域
imgMap = currentFrame.Clone(region, currentFrame.PixelFormat);
}
else
{
imgMap = currentFrame;
}
bool bol = Imaganddcm.ImportImage("123456", "2", "3", "测试", imgMap, _blpath);
if (bol)
{
label5.Text = Imaganddcm.Array.Count.ToString();
imgMap.Dispose();
currentFrame.Dispose();
}
}
}
///
/// 上传病理dcm并且传递数据
///
///
///
private void button3_Click(object sender, EventArgs e)
{
//给当前患者创建FTP路径
FtpHelper.MakeDir("123456");
//读取当前患者截图文件上传FTP
string[] filePaths = Directory.GetFiles(_blpath);
if (!filePaths.Any())
{
MessageBox.Show("文件为空");
return;
}
//存放文件访问地址
ArrayList arrayList = new ArrayList();
foreach (string filePath in filePaths)
{
string fileName = System.IO.Path.GetFileName(filePath);
string returnStr = FtpHelper.FileUpLoad(filePath, "123456", fileName);//上传文件
arrayList.Add("123456" + "/" + fileName);
File.Delete(filePath);
}
//调用患者信息接口
//先获取token
string msg = Get(_url + "/admin-api/system/jwtToken/getToken?key_public=c4c7dde887706361d8480909043bfdbd");
if (!string.IsNullOrEmpty(msg))
{
MsgInfo person = JsonConvert.DeserializeObject(msg);
if (person != null)
{
InsPatientInfo(person.data);
InsImageInfo(person.data, arrayList);
MessageBox.Show("上传成功");
Imaganddcm.Array.Clear();
label5.Text = "0";
}
}
}
///
/// 插入患者信息
///
///
private void InsPatientInfo(string token)
{
string strjson = @"[
{
""examId"": ""1234567"",
""pname"": ""病理测试插入患者"",
""gender"": ""男"",
""birthday"": ""1727075391000"",
""deviceType"": ""CSH1"",
""deviceName"": ""设备测试12"",
""seDc"": """",
""examDate"": ""1727075391000"",
""examItemCode"": ""Z0000000210"",
""examItemName"": ""病理"",
""reportstatus"": ""待分析"",
""applicationDate"": ""1727075391000"",
""orgId"": ""9f65555c-ce59-4f4c-8f1c-af245ebe5ce6"",
""orgName"": ""科右前旗康立寿医院"",
""regId"": ""123456""
}
]";
string msg = Post(_url + "/admin-api/tblist/patientexamlist/addPatientExamInfo", strjson, "AuthToken", token);
}
///
/// 插入影像数据
///
///
///
private void InsImageInfo(string token, ArrayList arrayList)
{
if (arrayList != null)
{
int count = 0;
List images = new List();
foreach (string str in arrayList)
{
count++;
image imageInfo = new image();
imageInfo.ImageNumber = count.ToString();
imageInfo.ObjectFile = str;
imageInfo.UrlPrefix = _blprefix;
images.Add(imageInfo);
}
Series series = new Series
{
SeriesNumb = "1",
SeriesDesc = "病理",
Modality = "CSH1",
image = images
};
//检查项目信息
Study study = new Study
{
StudyDescr = "病理",
StudyID = "Z0000000033",
StudyModal = "CSH1",
Series = new List { series }
};
//患者信息
Patient patient = new Patient
{
PatientID = "123456",
PatientNam = "病理测试插入患者",
PatientBir = "511200000000",
PatientSex = "F",
OrgId = "9f65555c-ce59-4f4c-8f1c-af245ebe5ce6",
OrgName = "测试插入1",
StudyDate = "2024-9-20 13:03:30",
Studies = new List { study }
};
List patientList = new List();
patientList.Add(patient);
// 将对象转换为JSON字符串
string json = JsonConvert.SerializeObject(patientList);
string msg = Post(_url + "/admin-api/ultrasoniccom/ultrasonic/InsImageInfo", json, "AuthToken", token);
}
}
#endregion
#region 钩子相关
//定义变量
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
static int hKeyboardHook = 0;
HookProc KeyboardHookProcedure;
/*************************
* 声明API函数
* ***********************/
// 安装钩子 (using System.Runtime.InteropServices;)
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
// 卸载钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
// 继续下一个钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
// 取得当前线程编号(线程钩子需要用到)
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
//钩子子程:就是钩子所要做的事情
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
{
if (nCode >= 0)
{
/****************
//线程键盘钩子判断是否按下键
Keys keyData = (Keys)wParam;
if(lParam.ToInt32() > 0)
{
// 键盘按下
}
if(lParam.ToInt32() < 0)
{
// 键盘抬起
}
****************/
/****************
//全局键盘钩子判断是否按下键
wParam = = 0x100 // 键盘按下
wParam = = 0x101 // 键盘抬起
****************/
KeyMSG m = (KeyMSG)Marshal.PtrToStructure(lParam, typeof(KeyMSG));//键盘
Keys key = (Keys)m.vkCode;
if (wParam == 0x100) // WM_KEYDOWN
{
string keyString = key.ToString();
// MessageBox.Show(keyString);
if (keyString == strkey)
{
SaveImageDcm();
}
switch (keyString)
{
case "F6":
if (!IsStartVideo)
{
btn_StartVideo_Click(null, null);
}
break;
case "F7":
btn_PauseVideo_Click(null, null);
break;
case "F8":
if (IsStartVideo)
{
btn_EndVideo_Click(null, null);
}
break;
case "F9":
btn_Capture_Click(null, null);
break;
}
// MessageBox.Show("Key down: " + key.ToString());
}
else if (wParam == 0x101) // WM_KEYUP
{
// MessageBox.Show("Key up: " + key.ToString());
}
// return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
return 0;//如果返回1,则结束消息,这个消息到此为止,不再传递。如果返回0或调用CallNextHookEx函数则消息出了这个钩子继续往下传递,也就是传给消息真正的接受者
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
//键盘结构
public struct KeyMSG
{
public int vkCode; //键值
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
// 安装钩子
public void HookStart()
{
if (hKeyboardHook == 0)
{
// 创建HookProc实例
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
// 设置线程钩子
hKeyboardHook = SetWindowsHookEx(13, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
//************************************
//键盘线程钩子
//SetWindowsHookEx( 2,KeyboardHookProcedure, IntPtr.Zero, GetCurrentThreadId());
//键盘全局钩子,需要引用空间(using System.Reflection;)
//SetWindowsHookEx( 13,KeyboardHookProcedure,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0);
//
//关于SetWindowsHookEx (int idHook, HookProc lpfn, IntPtr hInstance, int threadId)函数将钩子加入到钩子链表中,说明一下四个参数:
//idHook 钩子类型,即确定钩子监听何种消息,上面的代码中设为2,即监听键盘消息并且是线程钩子,如果是全局钩子监听键盘消息应设为13,
//线程钩子监听鼠标消息设为7,全局钩子监听鼠标消息设为14。
//
//lpfn 钩子子程的地址指针。如果dwThreadId参数为0 或是一个由别的进程创建的线程的标识,lpfn必须指向DLL中的钩子子程。 除此以外,lpfn可
//以指向当前进程的一段钩子子程代码。钩子函数的入口地址,当钩子钩到任何消息后便调用这个函数。
//
//hInstance应用程序实例的句柄。标识包含lpfn所指的子程的DLL。如果threadId 标识当前进程创建的一个线程,而且子程代码位于当前
//进程,hInstance必须为NULL。可以很简单的设定其为本应用程序的实例句柄。
//
//threadedId 与安装的钩子子程相关联的线程的标识符。如果为0,钩子子程与所有的线程关联,即为全局钩子。
//************************************
// 如果设置钩子失败
if (hKeyboardHook == 0)
{
HookStop();
throw new Exception("SetWindowsHookEx failed.");
}
}
}
// 卸载钩子
public void HookStop()
{
bool retKeyboard = true;
if (hKeyboardHook != 0)
{
retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
hKeyboardHook = 0;
}
if (!(retKeyboard))
throw new Exception("UnhookWindowsHookEx failed.");
}
#endregion
///
/// 是否开启区域截图
///
///
///
private void checkBox1_Click(object sender, EventArgs e)
{
if (!checkBox1.Checked)
{
txt_x.Enabled = false;
txt_y.Enabled = false;
txt_w.Enabled = false;
txt_h.Enabled = false;
}
else
{
txt_x.Enabled = true;
txt_y.Enabled = true;
txt_w.Enabled = true;
txt_h.Enabled = true;
}
}
///
/// 双击患者列 选中患者
///
///
///
private void dGVPatient_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
// 检查是否双击了整行
if (e.RowIndex >= 0) // 确保是行内的单元格被双击
{
// 获取当前行的所有单元格
DataGridViewRow row = dGVPatient.Rows[e.RowIndex];
rowhisinfo = (HisInfo)row.DataBoundItem;
label3.Text = "双击选择患者" + " 当前患者:" + rowhisinfo.name;
}
}
///
/// 患者数据上传
///
///
///
private void button4_Click(object sender, EventArgs e)
{
if (rowhisinfo == null)
{
MessageBox.Show("请选择患者");
return;
}
if (imagearray.Count <= 0 && string.IsNullOrEmpty(videoName))
{
MessageBox.Show("暂无需要上传的患者和文件");
return;
}
this.backgroundWorker1.RunWorkerAsync(); // 运行 backgroundWorker 组件
ProcessForm form = new ProcessForm(this.backgroundWorker1);// 显示进度条窗体
form.ShowDialog(this);
form.Close();
MessageBox.Show("上传成功");
}
#region 线程执行
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
}
else
{
}
}
//你可以在这个方法内,实现你的调用,方法等。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
//上传图片
#region 上传图片
string returnStr = string.Empty;
foreach (var item in imagearray)
{
string fileName = System.IO.Path.GetFileName(item.ToString());
if (_model == "0")
{
returnStr = SaveFile(item.ToString(), ConfigurationManager.AppSettings["filepath"] + "\\" + rowhisinfo.jianchaid, fileName.Split('.')[0], "jpg");
}
else
{
returnStr = FtpHelper.FileUpLoad(item.ToString(), ConfigurationManager.AppSettings["path1"], fileName);//上传文件
}
if (!string.IsNullOrEmpty(returnStr) && returnStr == "上传成功")
{
//上传成功 清除文件
try
{
UploadFileUrl(fileName, ".jpg");
// 删除文件
File.Delete(item.ToString());
worker.ReportProgress(10);
}
catch (IOException ex)
{
MessageBox.Show("删除文件时出错: " + ex.Message);
return;
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show("没有权限删除文件: " + ex.Message);
return;
}
}
}
#endregion
#region 上传视频
if (!string.IsNullOrEmpty(videoName))
{
bool fileExists = File.Exists(videoName);
if (fileExists)
{
string newfilename = ConvertVideo(videoName);
if (_model == "0")
{
returnStr = SaveFile(newfilename, ConfigurationManager.AppSettings["filepath"] + "\\" + rowhisinfo.jianchaid, fileName, "mp4");
}
else
{
returnStr = FtpHelper.FileUpLoad(newfilename, ConfigurationManager.AppSettings["path1"], fileName + ".mp4");//上传文件
}
if (!string.IsNullOrEmpty(returnStr) && returnStr == "上传成功")
{
//上传成功 清除文件
try
{
UploadFileUrl(fileName + ".mp4", ".mp4");
// 删除文件
File.Delete(videoName);
// 删除文件
File.Delete(newfilename);
worker.ReportProgress(10);
}
catch (IOException ex)
{
MessageBox.Show("删除文件时出错: " + ex.Message);
return;
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show("没有权限删除文件: " + ex.Message);
return;
}
this.Invoke(new Action(() =>
{
tick_num = 0;
lab_Time.Text = "00:00:00";
}));
}
}
}
#endregion
#region 插入患者
worker.ReportProgress(70);
string token = Get(_url + "/admin-api/system/jwtToken/getToken?key_public=c4c7dde887706361d8480909043bfdbd");
if (!string.IsNullOrEmpty(token))
{
MsgInfo person = JsonConvert.DeserializeObject(token);
List Record = new List();
ExamRecord examRecord = new ExamRecord();
examRecord.examId = rowhisinfo.jianchabh + "_" + GetRandomNumber(1, 100);
examRecord.pname = rowhisinfo.name;
examRecord.gender = rowhisinfo.sex;
examRecord.birthday = GetTimestampFromBirthdate(rowhisinfo.birthdate).ToString();
examRecord.deviceType = "US";//rowhisinfo.category
examRecord.deviceName = "彩超";
examRecord.seDc = "1/1";
examRecord.examDate = GetTimestampFromdate(rowhisinfo.kaifangsj).ToString();
examRecord.examItemName = rowhisinfo.jianchamingcheng;
examRecord.examItemCode = rowhisinfo.nhbm;
examRecord.reportstatus = "待分析";
examRecord.applicationDate = GetTimestampFromdate(rowhisinfo.kaifangsj).ToString();
examRecord.orgId = rowhisinfo.yiyuancode;//9f65555c-ce59-4f4c-8f1c-af245ebe5ce6 rowhisinfo.yiyuanid
examRecord.orgName = rowhisinfo.yiyuanname;
examRecord.regId = rowhisinfo.jianchaid;
Record.Add(examRecord);
var json = JsonConvert.SerializeObject(Record);
string msg = Post(_url + "/admin-api/tblist/patientexamlist/addPatientExamInfo", json, "AuthToken", person.data);
worker.ReportProgress(100);
this.Invoke(new Action(() =>
{
//截图数量置为0
label1.Text = "0";
//选择患者置为空
rowhisinfo = null;
imagearray.Clear();
videoName = string.Empty;
label3.Text = "双击选择患者";
}));
}
#endregion
}
#endregion
private void gb_ButtonBox_Enter(object sender, EventArgs e)
{
}
public static int GetRandomNumber(int minValue, int maxValue)
{
Random random = new Random(); // 实例化Random类
return random.Next(minValue, maxValue); // 返回一个随机整数
}
// 获取当前时间的Unix时间戳(毫秒)
public static string GetCurrentTimestamp()
{
// DateTime.UtcNow 获取当前UTC时间
// Subtract 方法减去1970年1月1日的时间
// TotalMilliseconds 获取总毫秒数
return DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalMilliseconds.ToString();
}
// 将指定的出生日期转换为Unix时间戳(毫秒)
public static long GetTimestampFromBirthdate(string birthdate)
{
// 尝试解析日期字符串
DateTime birthDateTime;
if (DateTime.TryParseExact(birthdate, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out birthDateTime))
{
// 将本地时间转换为UTC时间
DateTime birthDateTimeUtc = birthDateTime.ToUniversalTime();
// 计算时间戳
TimeSpan elapsedTime = birthDateTimeUtc - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return (long)elapsedTime.TotalMilliseconds;
}
else
{
// 如果日期格式不正确,抛出异常
throw new ArgumentException("无效的日期格式。正确的格式应该是yyyy-MM-dd。");
}
}
public static long GetTimestampFromdate(string birthdate)
{
// 尝试解析日期字符串
DateTime birthDateTime;
if (DateTime.TryParseExact(birthdate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out birthDateTime))
{
// 将本地时间转换为UTC时间
DateTime birthDateTimeUtc = birthDateTime.ToUniversalTime();
// 计算时间戳
return (long)birthDateTimeUtc.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
}
else
{
// 如果日期格式不正确,抛出异常或返回0
throw new ArgumentException("无效的日期格式。正确的格式应该是yyyy-MM-dd。");
// 或者返回0,取决于你希望如何处理错误
// return 0;
}
}
///
/// 刷新患者
///
///
///
private void button1_Click_1(object sender, EventArgs e)
{
GetHisInfo();
}
private void button5_Click(object sender, EventArgs e)
{
// 创建一个OpenFileDialog实例
OpenFileDialog openFileDialog = new OpenFileDialog();
try
{
// 设置OpenFileDialog的属性
openFileDialog.InitialDirectory = "C:\\"; // 初始目录
openFileDialog.Title = "请选择一个图像文件"; // 对话框标题
openFileDialog.Filter = "图像文件 (*.jpg;*.jpeg;*.png;*.bmp)|*.jpg;*.jpeg;*.png;*.bmp"; // 文件过滤器
// 显示OpenFileDialog
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
// 获取选中的文件路径
string selectedFilePath = openFileDialog.FileName;
using (FileStream fs = new FileStream(selectedFilePath, FileMode.Open, FileAccess.Read))
{
using (Bitmap bitmap = new Bitmap(fs))
{
bool bol = Imaganddcm.ImportImage("M20241025", "202410253", "202410253", "树艳", bitmap, _blpath);
}
}
}
}
catch (Exception ex)
{
// 异常处理
Console.WriteLine("发生异常:" + ex.Message);
}
}
#region 调用接口上传文件
///
/// 调用接口上传文件
///
/// 文件所在的路径
/// 文件保存的文件夹路径
/// 文件名(不包含扩展名)
/// 文件扩展名(例如 "png", "jpg", "txt")
///
private string SaveFile(string imageBase, string folderPath, string fileName, string extension)
{
string base64String = ConvertFileToBase64(imageBase);
if (string.IsNullOrEmpty(base64String))
{
return "文件为空";
}
SaveFile saveFile = new SaveFile();
saveFile.imagebase = base64String;
saveFile.folderPath = folderPath;
saveFile.fileName = fileName;
saveFile.extension = extension;
var json = JsonConvert.SerializeObject(saveFile);
string msg = Post(_url + "/admin-api/ultrasoniccom/ultrasonic/SaveFileBase64", json);
return msg;
}
///
/// 文件转换成base64
///
///
///
///
private string ConvertFileToBase64(string filePath)
{
string base64String = string.Empty;
// 确保文件存在
if (File.Exists(filePath))
{
// 读取文件内容到字节数组中
byte[] fileBytes = File.ReadAllBytes(filePath);
// 将字节数组转换为Base64字符串
base64String = Convert.ToBase64String(fileBytes);
}
return base64String;
}
#endregion
///
/// 添加患者
///
///
///
private void button6_Click(object sender, EventArgs e)
{
InfoForm infoForm = new InfoForm();
if (infoForm.ShowDialog() == DialogResult.OK)
{
//先赋空再绑定
dGVPatient.DataSource=null;
hisInfos.Add(infoForm.info);
dGVPatient.DataSource = hisInfos;
rowhisinfo = null;
}
}
}
}