如何增量调整 WPF 窗口大小?

Joa*_*nge 5 .net c# wpf xaml

是否可以制作Window这样的一个,当用户调整高度时,它会增加和减少 10?有点像捕捉调整大小。

Cod*_*ked 5

以下是如何完成此操作的示例:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这里使用 100 的增量来真实地说明“捕捉”效果。此外,您可以调整捕捉阈值,以确保捕捉仅在尺寸高于给定宽度/高度时生效。

  • +1我刚刚写了一些类似的东西,但你抢先了我。一件事是您可能还应该考虑 [wParam](http://msdn.microsoft.com/en-us/library/ms632647(v=VS.85).aspx)。因为尺寸的来源(底部、左下、顶部、左上等)可能很重要。我仍然同意亨克·霍尔特曼的观点,即这可能并不理想,因为它违反了最小惊讶原则 (2认同)