项目场景:
公司展厅使用时,需要在多个屏幕开启一些指定的网页,免去每次人工操作。
- 控制台应用
- .NET Framework 4.8
- 引用 System.Drawing
开机自启的话, 键盘按下win+R,输入命令"shell:startup",把exe扔进去。
思路:
- 从注册表中获取默认浏览器可执行文件路径。
- 获取系统上所有显示器的数组。
- 开启浏览器到各个显示器并全屏显示。(理论上,浏览器应该能全屏打开网页才对。没试出来,所以采用F11方法干。)
实现
user32.dll
/// <summary>
/// 检索前台窗口的句柄, (用户当前正在使用的窗口) 。 系统向创建前台窗口的线程分配略高于其他线程的优先级。
/// </summary>
/// <returns></returns>
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
/// <summary>
/// 更改子窗口、弹出窗口或顶级窗口的大小、位置和 Z 顺序。 这些窗口根据屏幕上的外观进行排序。 最上面的窗口接收最高排名,是 Z 顺序中的第一个窗口。
/// </summary>
/// <param name="hWnd">窗口的句柄。</param>
/// <param name="hWndInsertAfter">1:将窗口置于 Z 顺序的底部。-2:将窗口置于所有非顶部窗口上方 (,即位于最顶部窗口) 后面。0:将窗口置于 Z 顺序的顶部。-1:将窗口置于所有非最顶部窗口的上面。</param>
/// <param name="X">窗口左侧的新位置,以客户端坐标表示。</param>
/// <param name="Y">窗口顶部的新位置,以客户端坐标表示。</param>
/// <param name="cx">窗口的新宽度(以像素为单位)。</param>
/// <param name="cy">窗口的新高度(以像素为单位)。</param>
/// <param name="uFlags"></param>
/// <returns></returns>
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
/// <summary>
/// 阻止键盘和鼠标输入事件到达应用程序。
/// </summary>
/// <param name="Block">函数的用途。 如果此参数为 TRUE,则阻止键盘和鼠标输入事件。 如果此参数为 FALSE,则取消阻止键盘和鼠标事件。 请注意,只有阻止输入的线程才能成功取消阻止输入。</param>
[DllImport("user32.dll")]
static extern void BlockInput(bool Block);
Main
private static Dictionary<string, string> dic = new Dictionary<string, string>
{
{@"\\.\DISPLAY1","https://www.baidu.com/"},
{@"\\.\DISPLAY2","https://cn.bing.com/"},
{@"\\.\DISPLAY5","http://www.google.cn/"},//分屏器会跳过某些屏
};
static void Main(string[] args)
{
try
{
//锁定鼠标及键盘
BlockInput(true);
//
var browserPath = GetDefaultWebBrowserFilePath();
//
Screen[] screens = Screen.AllScreens;
/*
\\.\DISPLAY1
\\.\DISPLAY2
*/
for (int i = 0; i < screens.Length; i++)
{
if (dic.TryGetValue(screens[i].DeviceName, out string url))
{
OpenBrowser(screens[i], browserPath, url);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
//解除键盘鼠标锁定
BlockInput(false);
//Console.ReadLine();
}
}
一些方法
/// <summary>
/// 从注册表中获取默认浏览器可执行文件路径
/// </summary>
/// <returns></returns>
public static string GetDefaultWebBrowserFilePath()
{
//计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice
RegistryKey CURRENT_USER = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice\");
string ProgId = CURRENT_USER.GetValue("ProgId").ToString();
//计算机\HKEY_CLASSES_ROOT\MSEdgeHTM\shell\open\command
RegistryKey CLASSES_ROOT = Registry.ClassesRoot.OpenSubKey($@"{ProgId}\shell\open\command\");
string browser = CLASSES_ROOT.GetValue("").ToString();
//browser就是你的默认浏览器,不过后面带了参数,把它截去,不过需要注意的是:不同的浏览器后面的参数不一样!
//"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --single-argument %1
browser = browser.Substring(1, browser.IndexOf('\"', 1) - 1);
//C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
return browser;
}
/// <summary>
///
/// </summary>
/// <param name="screen"></param>
/// <param name="browserPath"></param>
/// <param name="url"></param>
public static async void OpenBrowser(Screen screen, string browserPath, string url)
{
//
Process proc = Process.Start(browserPath, $"{url} --new-window");
//确保启动成功
proc.WaitForExit();
do
{
Thread.Sleep(500);
} while (!proc.HasExited);
//
var wnd = GetForegroundWindow();
SetWindowPos(wnd, 0, screen.Bounds.X, screen.Bounds.Y, 0, 0, 0x0001);
//
Thread.Sleep(200);
//
SendKeys.SendWait("{F11}");
}