取消

WPF / Windows Forms 检测窗口在哪个屏幕

使用 Windows Forms 自带的 System.Windows.Forms.Screen 类可以从一个窗口句柄获取到对应的屏幕。随后可以使用此 Screen 类获取各种屏幕信息。


System.Windows.Forms.Screen

通过句柄获取屏幕类:

1
System.Windows.Forms.Screen.FromHandle(hWnd)

这里我做了一个 DEMO 程序,画出了窗口的位置和大小,以及当前窗口所在的屏幕的位置和大小。

屏幕间移动的窗口

附代码

MainWindow.xaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<Window x:Class="Walterlv.Issues.Dpi.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Walterlv.Issues.Dpi"
        mc:Ignorable="d"
        Title="欢迎阅读吕毅的博客 blog.walterlv.com" Height="450" Width="800">
    <Grid x:Name="RootPanel">
        <Canvas SnapsToDevicePixels="True">
            <UIElement.RenderTransform>
                <ScaleTransform ScaleX="0.2" ScaleY="0.2" />
            </UIElement.RenderTransform>
            <Border x:Name="ScreenBorder" Background="#E4E4E6">
                <UIElement.RenderTransform>
                    <TranslateTransform x:Name="ScreenTranslateTransform" />
                </UIElement.RenderTransform>
                <TextBlock x:Name="ScreenTextBlock" FontSize="240" TextAlignment="Right" />
            </Border>
            <Border x:Name="WindowBorder" Background="#949499">
                <UIElement.RenderTransform>
                    <TranslateTransform x:Name="WindowTranslateTransform" />
                </UIElement.RenderTransform>
                <TextBlock x:Name="WindowTextBlock" FontSize="240" Margin="0 0 -1000 -1000" />
            </Border>
        </Canvas>
    </Grid>
</Window>

MainWindow.xaml.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;

namespace Walterlv.Issues.Dpi
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            LocationChanged += MainWindow_LocationChanged;
            SizeChanged += MainWindow_SizeChanged;
        }

        private void MainWindow_LocationChanged(object sender, EventArgs e)
        {
            UpdateScreenInfo(this);
        }

        private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            UpdateScreenInfo(this);
        }

        private void UpdateScreenInfo(Window window)
        {
            var hwndSource = (HwndSource)PresentationSource.FromVisual(window);
            if (hwndSource is null)
            {
                return;
            }
            var hWnd = hwndSource.Handle;
            var screen = System.Windows.Forms.Screen.FromHandle(hWnd).Bounds;

            if (User32.GetWindowRect(hWnd, out var rect))
            {
                ScreenTranslateTransform.X = screen.X;
                ScreenTranslateTransform.Y = screen.Y;
                ScreenBorder.Width = screen.Width;
                ScreenBorder.Height = screen.Height;
                ScreenTextBlock.Text = $@"{rect.left},{rect.top}
{screen.Width}×{screen.Height}";
                WindowTranslateTransform.X = rect.left;
                WindowTranslateTransform.Y = rect.top;
                WindowBorder.Width = rect.right - rect.left;
                WindowBorder.Height = rect.bottom - rect.top;
                WindowTextBlock.Text = $@"{rect.left},{rect.top}
{rect.right - rect.left}×{rect.bottom - rect.top}";
            }
        }
    }
}

本文会经常更新,请阅读原文: https://blog.walterlv.com/post/detect-screen-that-contains-the-wpf-window.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 ([email protected])

登录 GitHub 账号进行评论