.NET ChangeDisplaySettingsEX 封装






2.86/5 (3投票s)
ChangeDisplaySettingsEx

引言
在编写一个程序,以便快速更改我的显示设置时,我发现 .NET 环境中没有很多可用的示例,而且没有一个示例展示了更改分辨率和主显示器以及连接和断开监视器的完整画面。
UpdateSettings
函数能够设置主显示器、连接和断开监视器,以及设置显示属性 Size
、BitsPerPixel
、Frequency
。
背景
我经常根据正在进行的操作更改双显示器电脑的显示设置。例如,当我使用 Visual Studio 时,我喜欢将两个监视器都设置为 1280x1024,但当我浏览网页时,我会将它们设置为 1024x768。然后还有那些使用屏幕边缘来滚动世界的模拟/冒险游戏。如果您连接了第二个监视器,这些游戏将无法正常运行。因此,需要更改另一个显示设置以断开第二个监视器。
Using the Code
Display_Settings
可以添加到任何窗体。它包含允许您为其提供组合框、面板和滑块以填充和控制的属性。这意味着您只需要在“应用”按钮上调用 UpdateSettings
。所有控件属性均经过处理,以确保不应用任何不正确的设置。Display_Settings
还提供允许您控制自己的控件的事件。
Private Sub btnApply_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnApply.Click
Me.Display_Settings1.UpdateSettings()
End Sub
UpdateSettings
函数还允许您通过传递 Display_Settings.Display
类的数组来更新存储的设置。Display_Settings.Display
类是可序列化的,并继承自 Kim Major 的 ContractBase(of T) 类。这使得序列化变得容易。非常感谢 Kim Major 提供的这个类。
UpdateSettings
函数首先通过将当前主显示器从位置 0,0 移开并将新的主显示器移动到位置 0,0 来设置主显示器。
然后它循环遍历每个显示设备。如果显示器要断开,它会将它移动到位置 0,0 并将其大小设置为 0,0。如果显示器连接,它将将其设置为其新设置。这也有连接先前未连接的任何显示器的效果。
最后,我们再次循环遍历所有显示设备并应用设置。
UpdateSettings 函数
Public Function UpdateSettings(ByVal Displays As Display()) _
As WinAPI.DisplaySetting_Results
If Not Me.PrimaryDisplayID = Me.PrimaryDisplayRegistryID Then
SetPrimaryDisplay(Me.m_Displays(Me.PrimaryDisplayRegistryID).DeviceName, _
Me.m_Displays(Me.PrimaryDisplayID).DeviceName)
End If
For Each disp As Display In Displays
If Not disp.Attached Then
Dim dm As New WinAPI.DEVMODE
dm.dmDeviceName = New [String](New Char(31) {})
dm.dmFormName = New [String](New Char(31) {})
dm.dmSize = CShort(Marshal.SizeOf(dm))
dm.dmFields = WinAPI.DEVMODE_Flags.DM_POSITION Or _
WinAPI.DEVMODE_Flags.DM_PELSWIDTH Or WinAPI.DEVMODE_Flags.DM_PELSHEIGHT
dm.dmPelsWidth = 0
dm.dmPelsHeight = 0
dm.dmPosition.x = 0
dm.dmPosition.y = 0
Dim Result As WinAPI.DisplaySetting_Results = _
WinAPI.ChangeDisplaySettingsEx_
(disp.DeviceName, dm, Nothing, WinAPI.DeviceFlags.CDS_UPDATEREGISTRY _
Or WinAPI.DeviceFlags.CDS_NORESET, 0)
Else
Dim dm As New WinAPI.DEVMODE
dm.dmDeviceName = New [String](New Char(31) {})
dm.dmFormName = New [String](New Char(31) {})
dm.dmSize = CShort(Marshal.SizeOf(dm))
dm.dmFields = WinAPI.DEVMODE_Flags.DM_POSITION Or _
WinAPI.DEVMODE_Flags.DM_PELSWIDTH Or _
WinAPI.DEVMODE_Flags.DM_PELSHEIGHT _
Or WinAPI.DEVMODE_Flags.DM_DISPLAYFLAGS _
Or WinAPI.DEVMODE_Flags.DM_BITSPERPEL _
Or WinAPI.DEVMODE_Flags.DM_DISPLAYFREQUENCY
dm.dmPelsWidth = disp.Size.Width
dm.dmPelsHeight = disp.Size.Height
dm.dmPosition.x = disp.Location.X
dm.dmPosition.y = disp.Location.Y
dm.dmBitsPerPel = disp.BitsPerPixel
dm.dmDisplayFrequency = disp.Frequency
Dim Result As WinAPI.DisplaySetting_Results = _
WinAPI.ChangeDisplaySettingsEx(disp.DeviceName, dm, _
Nothing, WinAPI.DeviceFlags.CDS_SET_PRIMARY _
Or WinAPI.DeviceFlags.CDS_UPDATEREGISTRY _
Or WinAPI.DeviceFlags.CDS_NORESET, 0)
End If
Next
For i As Integer = Displays.Length - 1 To 0 Step -1
Dim dm1 As New WinAPI.DEVMODE
dm1.dmDeviceName = New [String](New Char(31) {})
dm1.dmFormName = New [String](New Char(31) {})
dm1.dmSize = CShort(Marshal.SizeOf(dm1))
Dim lStatus As WinAPI.DisplaySetting_Results = _
WinAPI.ChangeDisplaySettingsEx(Me.m_Displays(i).DeviceName, _
dm1, Nothing, WinAPI.DeviceFlags.CDS_UPDATEREGISTRY, Nothing)
WinAPI.OutputDebugString(lStatus.ToString & vbCrLf)
Next
Me.InitializeDisplays()
End Function
SetPrimaryDisplay 函数
Public Sub SetPrimaryDisplay_
(ByVal OldPrimary As String, ByVal NewPrimary As String)
Dim Result As WinAPI.DisplaySetting_Results = 0
Dim dm1 As WinAPI.DEVMODE = NewDevMode()
WinAPI.EnumDisplaySettings(NewPrimary, _
WinAPI.DEVMODE_SETTINGS.ENUM_REGISTRY_SETTINGS, dm1)
Dim dm3 As WinAPI.DEVMODE = NewDevMode()
dm3.dmFields = WinAPI.DEVMODE_Flags.DM_POSITION
dm3.dmPosition.x = dm1.dmPelsWidth
dm3.dmPosition.y = 0
Result = WinAPI.ChangeDisplaySettingsEx(OldPrimary, dm3, _
Nothing, WinAPI.DeviceFlags.CDS_UPDATEREGISTRY _
Or WinAPI.DeviceFlags.CDS_NORESET, 0)
Console.WriteLine(Result.ToString)
Dim dm2 As WinAPI.DEVMODE = NewDevMode()
WinAPI.EnumDisplaySettings(NewPrimary, _
WinAPI.DEVMODE_SETTINGS.ENUM_REGISTRY_SETTINGS, dm2)
Dim dm4 As WinAPI.DEVMODE = NewDevMode()
dm4.dmFields = WinAPI.DEVMODE_Flags.DM_POSITION
dm4.dmPosition.x = 0
dm4.dmPosition.y = 0
Result = WinAPI.ChangeDisplaySettingsEx(NewPrimary, dm4, Nothing, _
WinAPI.DeviceFlags.CDS_SET_PRIMARY Or WinAPI.DeviceFlags.CDS_UPDATEREGISTRY _
Or WinAPI.DeviceFlags.CDS_NORESET, 0)
Console.WriteLine(Result.ToString)
Dim dm5 As WinAPI.DEVMODE = NewDevMode()
Result = WinAPI.ChangeDisplaySettingsEx(OldPrimary, dm5, _
Nothing, WinAPI.DeviceFlags.CDS_UPDATEREGISTRY, Nothing)
Console.WriteLine(Result.ToString)
Dim dm6 As WinAPI.DEVMODE = NewDevMode()
Result = WinAPI.ChangeDisplaySettingsEx(NewPrimary, dm6, Nothing, _
WinAPI.DeviceFlags.CDS_SET_PRIMARY Or WinAPI.DeviceFlags.CDS_UPDATEREGISTRY, 0)
Console.WriteLine(Result.ToString)
Console.WriteLine(Result.ToString)
End Sub
关注点
务必确保您的显示器具有共同的边缘。如果屏幕重叠或存在间隙,您可能会遇到一些奇怪的效果,例如鼠标指针没有指向鼠标位置。我不得不使用键盘几次来重置我的显示设置。
ChangeDisplaySettingsEX
建议要应用设置,您应该使用 ChangeDisplaySettingsEX(nothing, nothing, nothing, 0, nothing)
。这对我不起作用。我必须为每个设备名称调用 ChangeDisplaySettingsEX
,并使用一个空的 DEVMODE
结构和标志 CDS_UPDATEREGISTRY
。
历史
- 2009 年 7 月 6 日:第一个版本