Как изменить размер окна WPF с шагом? - PullRequest
4 голосов
/ 21 апреля 2011

Можно ли сделать Window таким, чтобы при изменении пользователем высоты по высоте он увеличивался и уменьшался на 10?Вроде как привязка изменения размера.

Ответы [ 6 ]

4 голосов
/ 21 апреля 2011

Вот пример того, как это можно сделать:

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

namespace DeleteMeWPF {
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow {
        public MainWindow() {
            InitializeComponent();
        }

        protected override void OnSourceInitialized(EventArgs e) {
            base.OnSourceInitialized(e);

            IntPtr handle = new WindowInteropHelper(this).Handle;
            HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(this.WindowProc));
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RECT {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        private const int WM_SIZING = 0x0214;

        private const int WMSZ_BOTTOM = 6;
        private const int WMSZ_BOTTOMLEFT = 7;
        private const int WMSZ_BOTTOMRIGHT = 8;
        private const int WMSZ_LEFT = 1;
        private const int WMSZ_RIGHT = 2;
        private const int WMSZ_TOP = 3;
        private const int WMSZ_TOPLEFT = 4;
        private const int WMSZ_TOPRIGHT = 5;

        private const int SnappingIncrement = 100;
        private const int SnappingThresholdWidth = 300;
        private const int SnappingThresholdHeight = 400;

        private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
            switch (msg) {
                case WM_SIZING:
                    RECT bounds = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT));

                    int width = bounds.right - bounds.left;
                    int height = bounds.bottom - bounds.top;

                    switch (wParam.ToInt32()) {
                        case WMSZ_BOTTOM:
                            if (height > SnappingThresholdHeight)
                                bounds.bottom = bounds.top + ((int)((double)height / (double)SnappingIncrement) * SnappingIncrement);
                            break;
                        case WMSZ_BOTTOMLEFT:
                            if (height > SnappingThresholdHeight)
                                bounds.bottom = bounds.top + ((int)((double)height / (double)SnappingIncrement) * SnappingIncrement);
                            if (width > SnappingThresholdWidth)
                                bounds.left = bounds.right - ((int)((double)width / (double)SnappingIncrement) * SnappingIncrement);
                            break;
                        case WMSZ_BOTTOMRIGHT:
                            if (height > SnappingThresholdHeight)
                                bounds.bottom = bounds.top + ((int)((double)height / (double)SnappingIncrement) * SnappingIncrement);
                            if (width > SnappingThresholdWidth)
                                bounds.right = bounds.left + ((int)((double)width / (double)SnappingIncrement) * SnappingIncrement);
                            break;
                        case WMSZ_LEFT:
                            if (width > SnappingThresholdWidth)
                                bounds.left = bounds.right - ((int)((double)width / (double)SnappingIncrement) * SnappingIncrement);
                            break;
                        case WMSZ_RIGHT:
                            if (width > SnappingThresholdWidth)
                                bounds.right = bounds.left + ((int)((double)width / (double)SnappingIncrement) * SnappingIncrement);
                            break;
                        case WMSZ_TOP:
                            if (height > SnappingThresholdHeight)
                                bounds.top = bounds.bottom - ((int)((double)height / (double)SnappingIncrement) * SnappingIncrement);
                            break;
                        case WMSZ_TOPLEFT:
                            if (width > SnappingThresholdWidth)
                                bounds.left = bounds.right - ((int)((double)width / (double)SnappingIncrement) * SnappingIncrement);
                            if (height > SnappingThresholdHeight)
                                bounds.top = bounds.bottom - ((int)((double)height / (double)SnappingIncrement) * SnappingIncrement);
                            break;
                        case WMSZ_TOPRIGHT:
                            if (width > SnappingThresholdWidth)
                                bounds.right = bounds.left + ((int)((double)width / (double)SnappingIncrement) * SnappingIncrement);
                            if (height > SnappingThresholdHeight)
                                bounds.top = bounds.bottom - ((int)((double)height / (double)SnappingIncrement) * SnappingIncrement);
                            break;

                    }
                    Marshal.StructureToPtr(bounds, lParam, false);
                    break;
            }

            return IntPtr.Zero;
        }
    }
}

Здесь используются приращения 100, чтобы действительно проиллюстрировать эффект «привязки».Кроме того, вы можете настроить пороговые значения привязки, чтобы гарантировать, что привязка вступает в силу только тогда, когда размер превышает заданную ширину / высоту.

3 голосов
/ 21 апреля 2011

Может быть, не очень хорошо, чтобы окно стало размером, которого пользователь не хотел ... что произойдет, если окно развернется до максимума, а оно не кратно 10?Смогли бы вы сохранить другие границы окна в том же месте, если бы они перетаскивали верхний край окна?

Я бы вместо этого сосредоточился на TreeView: создайте контейнер, который реализует MeasureOverride, и получите реализациювызовите base.MeasureOverride, и когда он получит этот результат, округляет значения вниз (всегда вниз) до значения, кратного 10. Остальное содержимое вашего окна получит различное количество пространства, в зависимости от размера окна, нопросто убедитесь, что в макете есть что-то, что растянется до 0-9 пикселей.

3 голосов
/ 21 апреля 2011

В старом Win32 Listbox была настройка, предотвращающая это.Обратите внимание, что это решало проблему с другого конца.

Но сначала взглянем на несколько установленных TreeView.Как Visual Studio, Параметры инструментов.

Я не думаю, что вы должны модифицировать поведение элементов управления стандартного интерфейса STD таким образом.Пользователи будут разочарованы, только если ваш телевизор будет работать по-другому.Они не будут называть это «лучше».

1 голос
/ 21 апреля 2011

Вы можете добавить SizeChangedEventHandler к событию SizeChanged. Затем в методе делегата измените размер вручную.

Хотя я думаю, что было бы трудно узнать, насколько это изменилось, если вы не сделаете запись где-то.

1 голос
/ 21 апреля 2011

Ну, обычно вам нужно обработать событие Resize / Resizing, а затем округлить размер в большую или меньшую величину до десяти или чего-то в этом роде.

Однако в WPF вам, видимо, приходится прибегать к хаку с использованием поведения.

См. эту статью , поскольку она описывает, что вы должны сделать, чтобы получить доступ к событию изменения размера.

0 голосов
/ 21 апреля 2011

Что ж, я собирался сказать: «В каком-то смысле, а не писать грязно-извилистый код позади? Не в моих силах».

... я буду придерживаться этого xD

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...