代码如下:
using Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Tools;
using DisplayMode = Models.DisplayMode;
namespace TestItem
{
public partial class VideoTestManager : Form
{
private string originalDirectory = System.Environment.CurrentDirectory; // 保存当前目录
private string programName = string.Empty;//程式名称
public event Action<bool> CallExit = null;//回调函数
private bool isPass = false;
private string readValues = null; // 测试参数
private string testArgs = null;//测试参数
private List<string> testItem=null;//测试项目
private string playFileName = string.Empty;//播放文件名称
private List<DisplayEntity> displayEntity;//显示实体
private int random_number = 0;//随机数
private int input_number = 0;//输入数
#region 构造函数
//显示模式
public VideoTestManager()
{
InitializeComponent();
this.CallExit += (isPass) => { }; // 初始化事件
this.Load += VideoTestManager_Load;
this.FormClosing += VideoTestManager_FormClosing;
this.KeyDown += VideoTestManager_KeyDown;
this.KeyPreview = true; // Enable the form to receive key events
}
#endregion
#region 窗体加载
private const byte VK_LEFT = 0x25;
private const byte VK_RIGHT = 0x27;
private async void VideoTestManager_Load(object sender, EventArgs e)
{
if (await this.GetTestArgs())
{
this.SetHeaderStyle(); // 设置表头信息样式
this.displayEntity = new List<DisplayEntity>();//初始化显示实体
timer_Test.Enabled = true;
}
}
#endregion
#region 切屏显示
/// <summary>
/// 切屏显示
/// </summary>
/// <param name="mode"></param>
/// <exception cref="ArgumentOutOfRangeException"></exception>
private void SwitchDisplayMode(DisplayMode mode)
{
string argument;
switch (mode)
{
case DisplayMode.Internal:
argument = "/internal";
break;
case DisplayMode.Clone:
argument = "/clone";
break;
case DisplayMode.Extend:
argument = "/extend";
break;
case DisplayMode.External:
argument = "/external";
break;
default:
throw new ArgumentOutOfRangeException();
}
Process.Start("DisplaySwitch.exe", argument);
}
#endregion
#region 获取测试参数
private async Task<bool> GetTestArgs()
{
try
{
//获取程式名称
this.programName = AuxiliaryItemArray.GetProgramName(this.lbl_ShowResult) != null ? AuxiliaryItemArray.GetProgramName(this.lbl_ShowResult) + @".exe" : null;
if (this.programName == null)
return false;
// 获取测试参数
this.testArgs = AuxiliaryItemArray.GetTestParameter(this.originalDirectory, this.programName, this.lbl_ShowResult);
if (this.testArgs == null)
return false;
//解析参数
string[] args = this.testArgs.Split('|');
this.playFileName = args[1].Split('=')[1];
this.testItem = new List<string>();
this.testItem = args[0].Split(',').ToList();
this.lbl_TestArgs.BeginInvoke(new Action(() => {
this.lbl_TestArgs.Text= args[0];
}));
return this.testItem.Count>0;
}
catch (Exception ex)
{
this.Invoke(new Action(() =>
{
AuxiliaryItemArray.Loginfo($@"获取测试参数:{ex.Message}", false, lbl_ShowResult);
}));
return false;
}
}
#endregion
#region 播放视频
/// <summary>
/// 播放视频
/// </summary>
/// <param name="playFileName">播放文件</param>
/// <returns></returns>
private async Task<bool>Mp4Play(string playFileName)
{
try
{
//设置播放器URL
// 获取当前目录
string currentDirectory = AppDomain.CurrentDomain.BaseDirectory;
// 拼接视频文件路径
string videoPath = Path.Combine(currentDirectory, "Video", playFileName);
if (File.Exists(videoPath))
{
// 设置播放器URL
wmpPlayer.URL = videoPath;
// 设置循环播放模式
wmpPlayer.settings.setMode("loop", true);
return true;
}
else
{
this.Invoke(new Action(() =>
{
AuxiliaryItemArray.Loginfo("视频文件未找到: " + videoPath, false, lbl_ShowResult);
}));
return false;
}
}
catch(Exception ex)
{
this.Invoke(new Action(() =>
{
AuxiliaryItemArray.Loginfo($@"播放MP4错误:{ex.Message}", false, lbl_ShowResult);
}));
return false;
}
}
#endregion
#region 设置表头信息样式
private void SetHeaderStyle()
{
// 设置参数列宽度,使用百分比
this.tabPanel_Args.ColumnStyles[0].SizeType = SizeType.Percent;
this.tabPanel_Args.ColumnStyles[0].Width = 25;
this.tabPanel_Args.ColumnStyles[1].SizeType = SizeType.Percent;
this.tabPanel_Args.ColumnStyles[1].Width = 25;
this.tabPanel_Args.ColumnStyles[2].SizeType = SizeType.Percent;
this.tabPanel_Args.ColumnStyles[2].Width = 25;
this.tabPanel_Args.ColumnStyles[3].SizeType = SizeType.Percent;
this.tabPanel_Args.ColumnStyles[3].Width = 25;
}
#endregion
#region 关闭窗体
private void VideoTestManager_FormClosing(object sender, FormClosingEventArgs e)
{
this.readValues = JsonConvert.SerializeObject(this.displayEntity, Formatting.Indented);//将实体类转换成json文件
AuxiliaryItemArray.UpdateJsonInfo(this.programName, this.readValues, this.isPass, this.originalDirectory, this.lbl_ShowResult);
this.ProcessExit(this.isPass);
}
#endregion
#region 关闭进程
private void ProcessExit(bool isPass)
{
CallExit?.Invoke(isPass);
}
#endregion
#region 定时触发器
private async void timer_Test_Tick(object sender, EventArgs e)
{
timer_Test.Enabled = false;
bool testResult = true;
string[] testArgsValues = this.testArgs.Split(',');
foreach (var a in testArgsValues)
{
if (!this.displayEntity.Any(d => d.ProtName == a))
{
testResult = false;
break;
}
}
if (testResult)
{
this.readValues = JsonConvert.SerializeObject(this.displayEntity, Formatting.Indented);//将实体类转换成json文件
AuxiliaryItemArray.UpdateJsonInfo(this.programName, this.readValues, true, this.originalDirectory, this.lbl_ShowResult);
this.ProcessExit(this.isPass);
}
else
{
DisplayManager displayManager = new DisplayManager();
DisplayEntity tempdata = new DisplayEntity();
displayManager.DetectDisplays();
if (displayManager.displayEntity.Count > 0)
{
foreach (DisplayEntity ds in displayManager.displayEntity)
{
this.currentTestPort = new DisplayEntity();
if (!displayEntity.Any(d => d.ProtName == ds.ProtName) || displayEntity.Count == 0)
{
this.currentTestPort = ds;
tempdata = ds;
TestDisplayPort();//测试显示接口
if (ds.DeviceName.ToUpper().Contains("DISPLAY1"))
{
this.SwitchDisplayMode(DisplayMode.Internal);//仅第一个屏显示
this.currentTestPort.SwDisplayMode = DisplayMode.Internal;
break;
}
else
{
this.SwitchDisplayMode(DisplayMode.External);//仅第二个屏显示
this.currentTestPort.SwDisplayMode = DisplayMode.External;
break;
}
}
}
}
}
}
#endregion
#region 显示接口测试
/// <summary>
/// 测试显示接口
/// </summary>
/// <param name="protName">接口名称</param>
private async void TestDisplayPort()
{
this.input_number = 0;
Random random = new Random();
this.random_number = random.Next(1,9);
this.lbl_ShowResult.BeginInvoke(new Action(() => {
this.lbl_ShowResult.ForeColor = Color.SteelBlue;
this.lbl_ShowResult.Text = $@"{this.currentTestPort.ProtName}接口测试中..";
}));
this.lbl_Random.BeginInvoke(new Action(() => {
this.lbl_Random.Text = this.random_number.ToString();
}));
await this.Mp4Play(this.playFileName);//Mp4播放
waitTime = 20;
timer_random.Enabled = true;
}
#endregion
#region 随机数检测
private int waitTime = 0;//等待时间
private DisplayEntity currentTestPort;//当前测试接口
private async void timer_random_Tick(object sender, EventArgs e)
{
if(waitTime==0)
{
if(currentTestPort.ProtName=="VGA")
{
this.lbl_VGA_result.Text = "FAIL";
this.lbl_VGA_result.ForeColor = Color.Red;
}
else if(currentTestPort.ProtName == "DVI")
{
this.lbl_DVI_result.Text = "FAIL";
this.lbl_DVI_result.ForeColor = Color.Red;
}
else if (currentTestPort.ProtName == "DP")
{
this.lbl_DP_result.Text = "FAIL";
this.lbl_DP_result.ForeColor = Color.Red;
}
else if (currentTestPort.ProtName == "HDMI")
{
this.lbl_HDMI_result.Text = "FAIL";
this.lbl_HDMI_result.ForeColor = Color.Red;
}
this.lbl_ShowResult.BeginInvoke(new Action(() => {
this.lbl_ShowResult.Text = $@"{this.currentTestPort.ProtName}接口测试Fail";
this.lbl_ShowResult.ForeColor = Color.Red;
}));
this.SwitchDisplayMode(DisplayMode.Extend);//扩展屏显示
await this.Mp4Play(this.playFileName);//Mp4播放
timer_random.Enabled = false;
this.timer_Test.Enabled = true;
}
else
{
if(this.input_number==0)
waitTime--;
else
{
if (currentTestPort.ProtName == "VGA")
{
this.lbl_VGA_result.Text = this.input_number == this.random_number ? "PASS" : "FAIL";
this.lbl_VGA_result.ForeColor = this.input_number == this.random_number ? Color.Green : Color.Red;
}
else if (currentTestPort.ProtName == "DVI")
{
this.lbl_DVI_result.Text = this.input_number == this.random_number ? "PASS" : "FAIL";
this.lbl_DVI_result.ForeColor = this.input_number == this.random_number ? Color.Green : Color.Red;
}
else if (currentTestPort.ProtName == "DP")
{
this.lbl_DP_result.Text = this.input_number == this.random_number ? "PASS" : "FAIL";
this.lbl_DP_result.ForeColor = this.input_number == this.random_number ? Color.Green : Color.Red;
}
else if (currentTestPort.ProtName == "HDMI")
{
this.lbl_HDMI_result.Text = this.input_number == this.random_number ? "PASS" : "FAIL";
this.lbl_HDMI_result.ForeColor = this.input_number == this.random_number ? Color.Green : Color.Red;
}
this.timer_random.Enabled = false;
if (this.input_number == this.random_number)
{
this.currentTestPort.TestResult = "PASS";
this.displayEntity.Add(this.currentTestPort);
}
this.lbl_ShowResult.BeginInvoke(new Action(() => {
this.lbl_ShowResult.Text = $@"{this.currentTestPort.ProtName}接口测试PASS";
this.lbl_ShowResult.ForeColor = Color.Green;
}));
this.waitTime = 0;
this.SwitchDisplayMode(DisplayMode.Extend);//扩展屏显示
await this.Mp4Play(this.playFileName);//Mp4播放
this.timer_Test.Enabled = true;
}
}
}
#endregion
#region 键盘入事件
/// <summary>
/// 键盘键入事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void VideoTestManager_KeyDown(object sender, KeyEventArgs e)
{
// Check if the pressed key is a number key (both top row and numpad)
if ((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) || (e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9))
{
// Get the digit from the key code
int digit = (e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) ? e.KeyCode - Keys.D0 : e.KeyCode - Keys.NumPad0;
// Handle the digit input, for example:
this.input_number = digit;
}
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using Models;
namespace Tools
{
public class DisplayManager
{
public List<DisplayEntity> displayEntity; // 显示实体
[DllImport("user32.dll")]
private static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);
[StructLayout(LayoutKind.Sequential)]
private struct DISPLAY_DEVICE
{
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceString;
public int StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceKey;
}
/// <summary>
/// 检测接入的显示接口
/// </summary>
public void DetectDisplays()
{
displayEntity = new List<DisplayEntity>();
// 使用WMI查询显示器连接类型
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\wmi", "SELECT * FROM WmiMonitorConnectionParams");
foreach (ManagementObject queryObj in searcher.Get())
{
uint videoOutputTechnology = (uint)queryObj["VideoOutputTechnology"];
string connectionType = GetConnectionType(videoOutputTechnology);
displayEntity.Add(new DisplayEntity
{
DeviceIndex = displayEntity.Count,
DeviceName = queryObj["InstanceName"]?.ToString(),
//DeviceString = DeviceString = d.DeviceString,
ProtName = connectionType
});
}
DeviceString();
}
/// <summary>
/// 检测接入的显示接口
/// </summary>
public void DeviceString()
{
DISPLAY_DEVICE d = new DISPLAY_DEVICE();
d.cb = Marshal.SizeOf(d);
int deviceIndex = 0;
//this.displayEntity = new List<DisplayEntity>();
while (EnumDisplayDevices(null, (uint)deviceIndex, ref d, 0))
{
if (deviceIndex < displayEntity.Count)
{
displayEntity[deviceIndex].DeviceString = d.DeviceString;
displayEntity[deviceIndex].DeviceName = d.DeviceName;
}
//Console.WriteLine($"Device {deviceIndex}: {d.DeviceName} - {d.DeviceString}");
//this.displayEntity.Add(new DisplayEntity()
//{
// DeviceIndex = deviceIndex,
// DeviceName = d.DeviceName,
// DeviceString = d.DeviceString
//});
deviceIndex++;
}
}
/// <summary>
/// 获取连接的显示类型
/// </summary>
/// <param name="videoOutputTechnology"></param>
/// <returns></returns>
private string GetConnectionType(uint videoOutputTechnology)
{
// 根据WMI查询结果中的VideoOutputTechnology值返回连接类型
switch (videoOutputTechnology)
{
case 0x00000000: return "HD15 (VGA)";
case 0x00000001: return "S-Video";
case 0x00000002: return "Composite video";
case 0x00000003: return "Component video (YPbPr)";
case 0x00000004: return "DVI";
case 0x00000005: return "HDMI";
case 0x00000006: return "LVDS";
case 0x00000007: return "DJPN";
case 0x00000008: return "SDI";
case 0x00000009: return "DP";
//case 0x00000009: return "DisplayPort external";
//case 0x0000000A: return "DisplayPort embedded";
case 0x0000000A: return "VGA";
case 0x0000000B: return "UDI external";
case 0x0000000C: return "UDI embedded";
case 0x0000000D: return "SDTVDongle";
case 0x80000000: return "Miracast";
case 0x80000001: return "Indirect Display";
default: return "Unknown";
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace Models
{
public class DisplayEntity
{
/// <summary>
/// 硬件指针
/// </summary>
public int DeviceIndex { get; set; }
/// <summary>
/// 硬件名称
/// </summary>
public string DeviceName { get; set; }
/// <summary>
/// 硬件字符串
/// </summary>
public string DeviceString { get; set; }
/// <summary>
/// 接口名称
/// </summary>
public string ProtName { get; set; }
/// <summary>
/// 切换的显示模式
/// </summary>
public DisplayMode SwDisplayMode { get; set; } = DisplayMode.Internal;
/// <summary>
/// 测试结果
/// </summary>
public string TestResult { get; set; } = "Wait";
}
public enum DisplayMode
{
Internal,//仅电脑屏幕
Clone,//复制
Extend,//扩展
External//仅第二屏幕
}
}