C# 将笔记本电脑与多台显示器对接时出现显示器编号问题
我开发了一个应用程序,可以将程序分配给特定的监视器,这样,当我对接笔记本电脑时,所有打开的窗口都会被推送到主监视器上,我可以按下全局热键Alt+d,所有分配给监视器的应用程序都会被推送到分配的监视器上。我还有另外3个热键,Alt+1、Alt+2和Alt+3,它们将焦点窗口移动到相应的监视器上。我注意到,当我回到我的办公桌,在笔记本电脑睡觉时对接,然后重新登录到Windows时,代码中返回的显示器工作区与显示设置中显示的不匹配 这是Windows显示的监视器布局。红色是我的代码显示的内容 如果我解开,然后把所有匹配的东西都装回去 以下是我将当前聚焦窗口移动到特定监视器的代码。C# 将笔记本电脑与多台显示器对接时出现显示器编号问题,c#,multiple-monitors,showwindow,setwindowpos,C#,Multiple Monitors,Showwindow,Setwindowpos,我开发了一个应用程序,可以将程序分配给特定的监视器,这样,当我对接笔记本电脑时,所有打开的窗口都会被推送到主监视器上,我可以按下全局热键Alt+d,所有分配给监视器的应用程序都会被推送到分配的监视器上。我还有另外3个热键,Alt+1、Alt+2和Alt+3,它们将焦点窗口移动到相应的监视器上。我注意到,当我回到我的办公桌,在笔记本电脑睡觉时对接,然后重新登录到Windows时,代码中返回的显示器工作区与显示设置中显示的不匹配 这是Windows显示的监视器布局。红色是我的代码显示的内容 如果我
Alt+1发送0,Alt+2发送1,Alt+3发送2:
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
[Flags]
public enum SpecialWindowHandles
{
/// <summary>
/// Places the window at the bottom of the Z order. If the hWnd parameter identifies a topmost window, the window loses its topmost status and is placed at the bottom of all other windows.
/// </summary>
HWND_BOTTOM = 1
}
[Flags]
public enum SetWindowPosFlags : uint
{
/// <summary>
/// Retains the current size (ignores the cx and cy parameters).
/// </summary>
SWP_NOSIZE = 0x0001,
/// <summary>
/// Retains the current Z order (ignores the hWndInsertAfter parameter).
/// </summary>
SWP_NOZORDER = 0x0004
}
private struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public System.Drawing.Point ptMinPosition;
public System.Drawing.Point ptMaxPosition;
public System.Drawing.Rectangle rcNormalPosition;
}
/// <summary>
/// Moves the user process retaining start to the provided monitor
/// </summary>
/// <param name="monitor"></param>
public void DockWindow(int monitor)
{
var screens = Screen.AllScreens.Count();
if (monitor == 1 && screens < 2 || monitor == 2 && screens < 3) // Prevent moving widnow to monitor that doesn't exist
return;
var hwnd = GetForegroundWindow(); // Gets the handle for the focused window
var screenLocation = Screen.AllScreens[monitor].WorkingArea; // Gets the working area of the windows associated monitor
var placement = new WINDOWPLACEMENT();
GetWindowPlacement(hwnd, ref placement); // Gest window placement info
switch (placement.showCmd)
{
case 3: // Maximized
ShowWindow(hwnd, 9); // Switch to regular window
SetWindowPos(hwnd, (IntPtr)SpecialWindowHandles.HWND_BOTTOM, screenLocation.X + 100, screenLocation.Y + 100, 0, 0, SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOSIZE); // Move window
ShowWindow(hwnd, 3); // Maximize window
break;
default: // Regular window
SetWindowPos(hwnd, (IntPtr)SpecialWindowHandles.HWND_BOTTOM, screenLocation.X + 100, screenLocation.Y + 100, 0 ,0, SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOSIZE); // Move window
break;
}
}
[DllImport(“user32.dll”)]
静态外部bool SetWindowPos(IntPtr hWnd、IntPtr hwninsertafter、intx、inty、intcx、intcy、SetWindowPosFlags uFlags);
[DllImport(“user32.dll”)]
静态外部布尔显示窗口(IntPtr hWnd、int nCmdShow);
[DllImport(“user32.dll”)]
私有静态外部IntPtr GetForegroundWindow();
[DllImport(“user32.dll”)]
静态外部布尔GetWindowPlacement(IntPtr hWnd,ref WINDOWPLACEMENT lpwndpl);
[旗帜]
公共枚举特殊indowHandles
{
///
///将窗口放置在Z顺序的底部。如果hWnd参数标识最顶部的窗口,则该窗口将失去其最顶部的状态,并放置在所有其他窗口的底部。
///
HWND_底部=1
}
[旗帜]
公共枚举SetWindowPosFlags:uint
{
///
///保留当前大小(忽略cx和cy参数)。
///
SWP_NOSIZE=0x0001,
///
///保留当前的Z顺序(忽略HwnInsertAfter参数)。
///
SWP_NOZORDER=0x0004
}
私有结构窗口放置
{
公共整数长度;
公共国旗;
公共int showCmd;
公共系统图点位置;
公共系统.Drawing.Point ptMaxPosition;
公共系统.Drawing.Rectangle位置;
}
///
///将用户进程保留启动移动到提供的监视器
///
///
公共空文档窗口(内部监视器)
{
var screens=Screen.AllScreens.Count();
如果(监视器==1&&screens<2 | |监视器==2&&screens<3)//防止将widnow移动到不存在的监视器
返回;
var hwnd=GetForegroundWindow();//获取聚焦窗口的句柄
var screenLocation=Screen.AllScreens[monitor].WorkingArea;//获取与windows关联的监视器的工作区域
var placement=新的WINDOWPLACEMENT();
GetWindowPlacement(hwnd,ref placement);//最大窗口位置信息
开关(placement.showCmd)
{
案例3://最大化
ShowWindow(hwnd,9);//切换到常规窗口
SetWindowPos(hwnd,(IntPtr)SpecialWindowWhandles.hwnd_底部,屏幕位置.X+100,屏幕位置.Y+100,0,0,SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOSIZE);//移动窗口
ShowWindow(hwnd,3);//最大化窗口
打破
默认值://常规窗口
SetWindowPos(hwnd,(IntPtr)SpecialWindowWhandles.hwnd_底部,屏幕位置.X+100,屏幕位置.Y+100,0,0,SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOSIZE);//移动窗口
打破
}
}
更新我又进行了一些调试,并显示了
屏幕。根据计算机对接时的状态,AllScreens
返回不同的数组:
你知道为什么会发生这种情况吗?我建议在你的问题中添加
c#
标记。因此AllScreens
数组中的三个屏幕具有相同的维度,但它们的排列顺序不同。也许没关系,因为。