WinForms C# 中的 SCROLLINFO PInvoke

SCROLLINFO PInvoke from WinForms C#

我正在编写一个带滚动条的控件,我希望它的行为(就滚动条而言)像 RichTextBox;即当条形图为 "Forced" 时,我希望它们在必要时被禁用。我有这个工作(有点),但在构建项目之前我没有在 Windows Forms Designer 中看到结果。

代码:

namespace WindowsFormsApplication1
{
    public class ScrollControl : Control
    {
        public const int WS_HSCROLL = 0x00100000;
        public const int WS_VSCROLL = 0x00200000;

        private RichTextBoxScrollBars sb;

        public RichTextBoxScrollBars ScrollBars
        {
            get
            {
                return this.sb;
            }

            set
            {
                this.sb = value;
                this.UpdateScrollBars();
            }
        }

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams result = base.CreateParams;
                result.Style |= WS_HSCROLL;
                result.Style |= WS_VSCROLL;
                return result;
            }
        }

        private void UpdateScrollBars()
        {
            ScrollOrientation dirH = ScrollOrientation.HorizontalScroll;
            ScrollInfoMask maskH = ScrollInfoMask.SIF_ALL;

            ScrollOrientation dirV = ScrollOrientation.VerticalScroll;
            ScrollInfoMask maskV = ScrollInfoMask.SIF_ALL;

            if (this.ScrollBars == RichTextBoxScrollBars.ForcedVertical || this.ScrollBars == RichTextBoxScrollBars.ForcedBoth)
            {
                maskV |= ScrollInfoMask.SIF_DISABLENOSCROLL;
            }

            if(this.ScrollBars == RichTextBoxScrollBars.ForcedHorizontal || this.ScrollBars == RichTextBoxScrollBars.ForcedBoth)
            {
                maskH |= ScrollInfoMask.SIF_DISABLENOSCROLL;
            }

            SCROLLINFO sV = new SCROLLINFO();
            SCROLLINFO sH = new SCROLLINFO();

            sV.cbSize = (uint)Marshal.SizeOf<SCROLLINFO>();
            sH.cbSize = (uint)Marshal.SizeOf<SCROLLINFO>();

            sV.fMask = (uint)maskV;
            sH.fMask = (uint)maskH;

            SetScrollInfo(this.Handle, (int)dirV, ref sV, true);
            SetScrollInfo(this.Handle, (int)dirH, ref sH, true);
        }

        [DllImport("user32.dll")]
        private static extern int SetScrollInfo(IntPtr hwnd, int fnBar, [In] ref SCROLLINFO lpsi, bool fRedraw);
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SCROLLINFO
    {
        public uint cbSize;
        public uint fMask;
        public int nMin;
        public int nMax;
        public uint nPage;
        public int nPos;
        public int nTrackPos;
    }

    public enum ScrollInfoMask
    {
        SIF_RANGE = 0x0001,
        SIF_PAGE = 0x0002,
        SIF_POS = 0x0004,
        SIF_DISABLENOSCROLL = 0x0008,
        SIF_TRACKPOS = 0x0010,
        SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS
    }
}

在这里,我已经构建了控件并将其加载到表单中(表单上的 16x 填充以清楚地显示控件的边界)

在这里,我已将 ScrollBars 属性 设置为 ForcedVertical,但是在构建解决方案之前不会显示

这里我选择了ForcedBoth,同样,这个只在构建

后显示

问题:

如何让 Designer 立即更新,以便我可以看到我的更改而无需不断构建?

注:

请原谅糟糕的代码质量(可变结构、可怕的名称等)- 这只是一个演示!

我也不想用ScrollableControl...太烂了!我需要 COMPLETE 控制 ScrollBars - Win32 预期的方式!

.Invalidate() .Update().Refresh() 不工作!

很可能,您需要强制重绘控件,即在 UpdateScrollBars 方法的末尾添加 Invalidate();.

编辑:以下对我有用(在 UpdateScrollBars 末尾):

Invalidate();
Update();

我认为您必须重新创建 window 才能做到这一点。试试这样:

public RichTextBoxScrollBars ScrollBars {
  get {
    return this.sb;
  }
  set {
    this.sb = value;
    this.RecreateHandle();
  }
}

protected override void OnHandleCreated(EventArgs e) {
  base.OnHandleCreated(e);
  UpdateScrollBars();
}