Мне нужно сохранить соотношение сторон моего окна WPF, когда оно будет изменено.Единственное решение, которое я нашел для решения соотношения сторон, - это использовать следующий код WINAPI и зарегистрировать Window в классе WindowAspectRatio в обработчике событий Window_SourceInitialized.
Обработчик событий Window_SourceInitialized.
private void Window_SourceInitialized(object sender, EventArgs e)
{
ratio = WindowAspectRatio.Register((Window)sender);
double scaleOfScreen = 0.5;
double w = (double)WpfScreen.GetScreenFrom(this).WorkingArea.Width;
double h = (double)WpfScreen.GetScreenFrom(this).WorkingArea.Height;
if (w < h)
{
Application.Current.MainWindow.Width = w * scaleOfScreen;
Application.Current.MainWindow.Height = w * scaleOfScreen / ratio;
}
else
{
Application.Current.MainWindow.Height = h * scaleOfScreen;
Application.Current.MainWindow.Width = h * ratio * scaleOfScreen;
}
this.InvalidateVisual();
}
Класс WindowAspectRatio
internal class WindowAspectRatio
{
private double ratio_;
private Window windowToTrack_;
private WindowAspectRatio(Window window)
{
ratio_ = window.Width / window.Height;
windowToTrack_ = window;
((HwndSource)HwndSource.FromVisual(window)).AddHook(DragHook);
}
public static double Register(Window window)
{
return new WindowAspectRatio(window).ratio_;
}
internal enum WM
{
WINDOWPOSCHANGING = 0x0046,
}
[Flags()]
public enum SWP
{
NoMove = 0x2,
}
[StructLayout(LayoutKind.Sequential)]
internal struct WINDOWPOS
{
public IntPtr hwnd;
public IntPtr hwndInsertAfter;
public int x;
public int y;
public int cx;
public int cy;
public int flags;
}
private IntPtr DragHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled)
{
if ((WM)msg == WM.WINDOWPOSCHANGING)
{
WINDOWPOS position = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
if ((position.flags & (int)SWP.NoMove) != 0 ||
HwndSource.FromHwnd(hwnd).RootVisual == null) return IntPtr.Zero;
double screenW = (double)WpfScreen.GetScreenFrom(windowToTrack_).WorkingArea.Width;
double screenH = (double)WpfScreen.GetScreenFrom(windowToTrack_).WorkingArea.Height;
if (position.cy >= screenH)
position.cy = (int)screenH;
position.cx = (int)(position.cy * ratio_);
if (position.cx >= screenW)
{
position.cx = (int)screenW;
position.cy = (int)(position.cx / ratio_);
}
Marshal.StructureToPtr(position, lParam, true);
handeled = true;
}
return IntPtr.Zero;
}
Это хорошо работает.При изменении размера окна путем перетаскивания в углу окна оно работает просто идеально, а соотношение сторон сохраняется.
Если я переместлю указатель мыши к нижнему краю окна, где можно изменить размер окна, онтоже отлично работает, чтобы перетащить этот край.Размер окна изменяется, а соотношение сторон по-прежнему сохраняется.
Проблема заключается в том, что при перемещении указателя мыши к левому краю окна появляется значок изменения размера указателя мыши, но при попытке изменить размер окна теперь вместо окна простоперемещается горизонтально.
Также при перемещении указателя мыши к правому краю окна я получаю значок указателя мыши с измененным размером, но при попытке изменить размер ничего не происходит вообще.
Для меня это было бы непроблема, связанная с тем, что изменение размера только по углу сработало бы, если бы можно было просто предотвратить отображение значка указателя мыши при изменении размера по горизонтали (по левому или правому краю) или только по вертикали (по нижнему краю), позволяя толькоизменить размер, схватив угол окна.Таким образом, вопрос, возможно ли как-то предотвратить горизонтальное и вертикальное изменение размеров значков указателя мыши, но при этом разрешить изменение размера (по вертикали и по горизонтали) одновременно, захватывая угол?
В качестве альтернативы, если у кого-то есть идеякак можно решить проблему горизонтального изменения размера, не работающую должным образом, используя приведенный выше код, который также решил бы проблему.