程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了WinForms 编辑器:覆盖 WndProc WM_NCHITEST 时无法选择表单控件大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决WinForms 编辑器:覆盖 WndProc WM_NCHITEST 时无法选择表单控件?

开发过程中遇到WinForms 编辑器:覆盖 WndProc WM_NCHITEST 时无法选择表单控件的问题如何解决?下面主要结合日常开发的经验,给出你关于WinForms 编辑器:覆盖 WndProc WM_NCHITEST 时无法选择表单控件的解决方法建议,希望对你解决WinForms 编辑器:覆盖 WndProc WM_NCHITEST 时无法选择表单控件有所启发或帮助; @H_944_2@我创建了一个表单类,我将其用作所有无边框窗口的基类。这个类允许我在没有窗口边框的情况下调整窗口大小。此类使用 WM_NCHITESTWndProc。问题是放置在表单中的所有控件都无法通过单击来选择。我可以通过选择容器内的一个区域来选择面板之类的容器,但是当我点击它们时,我再次选择了表单。这也意味着我不能通过拖动来放置控件。

@H_944_2@这是 borderlessResizeableForm 类:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.windows.Forms;

namespace CustomWinFormsControls {
    /// <sumMary>
    /// Form with a <see cref="Formborderstyle.None"/> which can be resized and moved if Drag control is set.
    /// </sumMary>
    public class borderlessResizableForm : Form {
        private FormDragControl dragControl;
        private Dictionary<Control,borderWndProcFilter> borderFilters;

        privatE int _resizeborderThickness = 5;

        /// <sumMary>
        /// The control which should be used to move the window around.
        /// </sumMary>
        [Editorbrowsable(EditorbrowsableState.Always)]
        [browsable(true)]
        [DefaultValue(null)]
        [category("BehavIoUr")]
        [Description("The control which should be used to move the window around.")]
        public Control DragTarget {
            get => this.dragControl?.Target;
            set {
                if (!(this.dragControl is null))
                    this.dragControl.Target = value;
            }
        }

        /// <sumMary>
        /// The thickness of the resize border on all sIDes of the window. The border is invisible. SetTing it will not result in a padding.
        /// </sumMary>
        [Editorbrowsable(EditorbrowsableState.Always)]
        [browsable(true)]
        [DefaultValue(null)]
        [category("BehavIoUr")]
        [Description("The thickness of the resize border on all sIDes of the window. The border is invisible. SetTing it will not result in a padding.")]
        public int ResizeborderThickness {
            get => this._resizeborderThickness;
            set {
                if (this._resizeborderThickness == value)
                    return;

                this._resizeborderThickness = value;

                foreach (borderWndProcFilter filter in this.borderFilters.Values)
                    filter.borderThinckness = value;
            }
        }

        /// <sumMary>
        /// Creates a new instance of the class <see cref="borderlessResizableForm"/>
        /// </sumMary>
        public borderlessResizableForm() {
            this.Formborderstyle = Formborderstyle.None;
            this.SetStyle(ControlStyles.ResizeRedraw,truE);

            this.dragControl = new FormDragControl();
            this.borderFilters = new Dictionary<Control,borderWndProcFilter>();
            this.ControlAdded += this.Control_ControlAdded;
            this.ControlRemoved += this.Control_ControlRemoved;
        }

        private voID Control_ControlAdded(object sender,ControlEventArgs E) {
            this.ApplyFiltersRecursive(this,e.Control);
        }

        private voID Control_ControlRemoved(object sender,ControlEventArgs E) {
            this.RemoveFiltersRecursive(e.Control);
        }

        private voID ApplyFiltersRecursive(Control parent,Control control) {
            if (control is null)
                return;

            this.borderFilters[control] = new borderWndProcFilter(parent,control,this.ResizeborderThickness);

            // remove them in case they were already added.
            control.ControlAdded -= this.Control_ControlAdded;
            control.ControlRemoved -= this.Control_ControlRemoved;

            control.ControlAdded += this.Control_ControlAdded;
            control.ControlRemoved += this.Control_ControlRemoved;

            foreach (Control c in control.Controls)
                if (!(c is null))
                    this.ApplyFiltersRecursive(parent,c);
        }

        private voID RemoveFiltersRecursive(Control control) {
            if (control is null)
                return;

            this.borderFilters.Remove(control);
            control.ControlAdded -= this.Control_ControlAdded;
            control.ControlRemoved -= this.Control_ControlRemoved;

            foreach (Control c in control.Controls)
                if (!(c is null))
                    this.RemoveFiltersRecursive(c);
        }

        protected overrIDe voID WndProc(ref message m) {
            if (m.Msg != borderWndProcFilter.WM_NCHITTEST) {
                base.WndProc(ref m);
                return;
            }

            Point pos = this.PointToClIEnt(new Point(m.LParam.ToInt32()));

            // if in top left corner
            if (pos.X <= this.ResizeborderThickness && pos.Y <= this.ResizeborderThickness) {
                m.Result = new IntPtr(borderWndProcFilter.HTtopleft);
                return;
            }

            // if in top right corner
            if (pos.X >= this.CLIENtSize.WIDth - this.ResizeborderThickness && pos.Y <= this.ResizeborderThickness) {
                m.Result = new IntPtr(borderWndProcFilter.HTtopRIGHT);
                return;
            }

            // if in bottom left corner
            if (pos.X <= this.ResizeborderThickness && pos.Y >= this.CLIENtSize.Height - this.ResizeborderThickness) {
                m.Result = new IntPtr(borderWndProcFilter.HTBottOMleft);
                return;
            }

            // if in bottom right corner
            if (pos.X >= this.CLIENtSize.WIDth - this.ResizeborderThickness && pos.Y >= this.CLIENtSize.Height - this.ResizeborderThickness) {
                m.Result = new IntPtr(borderWndProcFilter.HTBottomrIGHT);
                return;
            }

            // if on the left
            if (pos.X <= this.ResizeborderThickness) {
                m.Result = new IntPtr(borderWndProcFilter.HTleft);
                return;
            }

            // if on top
            if (pos.Y <= this.ResizeborderThickness) {
                m.Result = new IntPtr(borderWndProcFilter.HTtop);
                return;
            }

            // if on the right
            if (pos.X >= this.CLIENtSize.WIDth - this.ResizeborderThickness) {
                m.Result = new IntPtr(borderWndProcFilter.HtrigHT);
                return;
            }

            // if on the bottom
            if (pos.Y >= this.CLIENtSize.Height - this.ResizeborderThickness) {
                m.Result = new IntPtr(borderWndProcFilter.HTBottOM);
                return;
            }

            base.WndProc(ref m);
        }
    }

    /// <sumMary>
    /// A filter for the WM_NCHITTEST message to ignore it when the mouse hovers the resize border.
    /// </sumMary>
    public class borderWndProcFilter : NativeWindow {
        public const int WM_NCHITTEST = 0x0084;

        public const int HTCAPTION = 0x00000002;
        public const int HTtop = 0x0000000c;
        public const int HTBottOM = 0x0000000F;
        public const int HTleft = 0x0000000A;
        public const int HtrigHT = 0x0000000B;
        public const int HTtopleft = 0x0000000D;
        public const int HTtopRIGHT = 0x0000000E;
        public const int HTBottOMleft = 0x00000010;
        public const int HTBottomrIGHT = 0x00000011;
        public const int HTtransparent = -1;

        public static List<Type> TypeBlackList { get; set; } = new List<Type>();

        private Control parent;
        private Control child;

        public int borderThinckness { get; set; }
        public bool Resizeborderleft { get; set; }
        public bool ResizeborderRight { get; set; }
        public bool Resizebordertop { get; set; }
        public bool ResizeborderBottom { get; set; }

        /// <sumMary>
        /// Creates a new instance of the class <see cref="borderWndProcFilter"/>. Sets all borders to true.
        /// </sumMary>
        /// <param name="parent">The resizable control which should have a non blocked resize border.</param>
        /// <param name="child">The child control the filter should be applIEd to for not blocking the resize border of the parent control.</param>
        /// <param name="borderThinckness">The resize border thickness of the parent.</param>
        public borderWndProcFilter(Control parent,Control child,int borderThinckness) {
            this.parent = parent;
            this.child = child;

            try {
                if (!borderWndProcFilter.TypeBlackList.Contains(child.GetType()))
                    this.AssignHandle(child.HandlE);
            } catch (Exception) { }

            this.borderThinckness = borderThinckness;

            this.Resizeborderleft = true;
            this.ResizeborderRight = true;
            this.Resizebordertop = true;
            this.ResizeborderBottom = true;
        }

        /// <sumMary>
        /// Creates a new instance of the class <see cref="borderWndProcFilter"/>. Sets all borders to true.
        /// </sumMary>
        /// <param name="parent">The resizable control which should have a non blocked resize border.</param>
        /// <param name="child">The child control the filter should be applIEd to for not blocking the resize border of the parent control.</param>
        /// <param name="borderThinckness">The resize border thickness of the parent.</param>
        /// <param name="left">If true the parent has a left-sIDe resize border which should not be blocked.</param>
        /// <param name="right">If true the parent has a right-sIDe resize border which should not be blocked.</param>
        /// <param name="top">If true the parent has a top-sIDe resize border which should not be blocked.</param>
        /// <param name="bottom">If true the parent has a bottom-sIDe resize border which should not be blocked.</param>
        public borderWndProcFilter(Control parent,int borderThinckness,bool left,bool right,bool top,bool bottom) {
            this.parent = parent;
            this.child = child;
            this.AssignHandle(child.HandlE);
            this.borderThinckness = borderThinckness;

            this.Resizeborderleft = left;
            this.ResizeborderRight = right;
            this.Resizebordertop = top;
            this.ResizeborderBottom = bottom;
        }

        protected overrIDe voID WndProc(ref message m) {
            if (m.Msg != WM_NCHITTEST) {
                base.WndProc(ref m);
                return;
            }

            if (this.parent is null) {
                base.WndProc(ref m);
                return;
            }

            Point pos = new Point(m.LParam.ToInt32());
            Point parentGlobalPos = this.parent is Form ? this.parent.LOCATIOn : this.parent.PointToScreen(this.parent.LOCATIOn);

            // if on the left
            if (pos.X <= parentGlobalPos.X + this.borderThinckness && this.Resizeborderleft) {
                m.Result = new IntPtr(HTtransparent);
                return;
            }

            // if on top
            if (pos.Y <= parentGlobalPos.Y + this.borderThinckness && this.Resizebordertop) {
                m.Result = new IntPtr(HTtransparent);
                return;
            }

            // if on the right
            if (pos.X >= parentGlobalPos.X + this.parent.WIDth - this.borderThinckness && this.ResizeborderRight) {
                m.Result = new IntPtr(HTtransparent);
                return;
            }

            // if on the bottom
            if (pos.Y >= parentGlobalPos.Y + this.parent.Height - this.borderThinckness && this.ResizeborderBottom) {
                m.Result = new IntPtr(HTtransparent);
                return;
            }

            base.WndProc(ref m);
        }
    }
}
@H_944_2@编辑: 我还尝试在设计时忽略 WndProc,但这也不起作用:

if (licenseManager.UsageMode == licenseUsageMode.DesigntimE) {
    base.WndProc(ref m);
    return;
}

解决方法

@H_944_2@暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

@H_944_2@如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

@H_944_2@小编邮箱:dio#foxmail.com (将#修改为@)

大佬总结

以上是大佬教程为你收集整理的WinForms 编辑器:覆盖 WndProc WM_NCHITEST 时无法选择表单控件全部内容,希望文章能够帮你解决WinForms 编辑器:覆盖 WndProc WM_NCHITEST 时无法选择表单控件所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。