Willem D'Haeseleer
Willem D'Haeseleer

Reputation: 20200

GetWindowRect differs from Window.Left

I created a small sample application to illustrate a problem i encountered when using GetWindowRect. When i click the Foo button it shows that the Left value returned by GetWindowRect differs from Window.Left.

It appears that the returned value from Window.Left is relative, but i'm not sure to what. It's also strange that i can't reproduce this on every machine, on my home laptop with or without extra monitor i can reproduce this issue, on my work pc the issue doesn't occur. Both systems run Windows 7

Why are these values different and how can i fix this ?

MainWindow.xaml.cs

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

namespace PositionTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private IntPtr thisHandle;
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            thisHandle = new WindowInteropHelper(this).Handle;
        }

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }

        private void ReportLocation(object sender, RoutedEventArgs e)
        {
            var rct = new RECT();
            GetWindowRect(thisHandle, ref rct);

            MessageBox.Show(Left.ToString() + " " + rct.Left);
        }
    }
}

MainWindow.xaml

<Window x:Class="PositionTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Loaded="Window_Loaded" WindowStartupLocation="Manual" Height="150" Width="150" WindowStyle="SingleBorderWindow" ResizeMode="NoResize" BorderThickness="0,1,0,0" >
    <Grid>
        <Button Content="Foo" HorizontalAlignment="Left" Margin="35,50,0,0" VerticalAlignment="Top" Width="75" Click="ReportLocation"/>
    </Grid>
</Window>

Upvotes: 1

Views: 1645

Answers (1)

Hans Passant
Hans Passant

Reputation: 942538

You didn't quantify the difference, there are several explanations, but there's one obvious mismatch. Windows and WPF use different units. GetWindowRect() returns the window position in pixels, Window.Left returns the position in 1/96 inches. They will not match when the video adapter isn't running at 96 dots-per-inch. 96 dpi is the legacy setting, it is very easy to change on later versions of Windows. WPF makes it a bit difficult to obtain the dpi setting, check this blog post for code.

Upvotes: 5

Related Questions