如何在 UserControl 中创建部分客户区? [英] How to create partially client area in UserControl?

查看:20
本文介绍了如何在 UserControl 中创建部分客户区?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我之前的问题中,我已经整理了如何创建容器依赖控件.现在,我在该控件中遇到了问题.控件的设计有点混乱.设计是这样的.

在此设计中,开发人员无法在页面控件之外添加控件.PageControl 将自动添加到客户区.我想阻止用户在 PageControl 之外添加控件.我不会再制造混乱了.所以,我的问题是我该怎么做?

您可以在我之前的.网上有很多教程,你应该搜索一下.

以下代码只是向您展示从哪里开始的示例,并且不是最终解决方案.为使其完美运行,您需要处理 Window redrawMouse events 等.

公共类 XWizardControl继承 DevExpress.XtraEditors.XtraUserControl<DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)>_私有共享函数 GetDCEx(ByVal hWnd As IntPtr, ByVal hrgnClip As IntPtr, ByVal flags As Integer) As IntPtr结束功能Private Sub WmNcCalcSize(ByRef m As Message)如果 (m.WParam.ToInt32() = 0) 那么将 ncRect 调暗为 RECT = DirectCast(m.GetLParam(GetType(RECT)), RECT)ncRect.top += 10ncRect.bottom -= 10Marshal.StructureToPtr(ncRect, m.LParam, False)m.Result = IntPtr.ZeroElseIf (m.WParam.ToInt32() = 1) 那么将 ncParams 调暗为 NCCALCSIZE_PARAMS = DirectCast(m.GetLParam(GetType(NCCALCSIZE_PARAMS)), NCCALCSIZE_PARAMS)ncParams.rectProposed.top += 10ncParams.rectProposed.bottom -= 10Marshal.StructureToPtr(ncParams, m.LParam, False)m.Result = IntPtr.Zero别的MyBase.WndProc(m)万一结束子Private Sub WmNcPaint(ByRef m As Message)将 hDC 调暗为 IntPtr = GetDCEx(m.HWnd, m.WParam, (DCX.WINDOW 或 DCX.INTERSECTRGN 或 DCX.CACHE 或 DCX.CLIPSIBLINGS))如果 (hDC.ToInt32() <> 0) 那么使用 g 作为图形 = Graphics.FromHdc(hDC)g.Clear(Color.Red)结束使用m.Result = IntPtr.Zero别的MyBase.WndProc(m)万一结束子Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)选择案例 m.Msg案例 WM_NCCALCSIZE : Me.WmNcCalcSize(m) : 退出选择案例 WM_NCPAINT : Me.WmNcPaint(m) : 退出选择其他情况:MyBase.WndProc(m):退出选择结束选择结束子公共常量 WM_NCCALCSIZE 作为整数 = 131公共常量 WM_NCPAINT 作为整数 = 133<StructLayout(LayoutKind.Sequential)>_私有结构 RECT公共左为整数公共顶部为整数公共权利为整数公底为整数末端结构<StructLayout(LayoutKind.Sequential)>_私有结构 NCCALCSIZE_PARAMS公开 rect 提议为 RECT公共 rectBeforeMove 作为 RECT公共 rectClientBeforeMove As RECT公共 lppos 作为 WINDOWPOS末端结构<StructLayout(LayoutKind.Sequential)>_私有结构 WINDOWPOS公共 hwnd 作为 IntPtr公共 hWndInsertAfter 作为 IntPtr公共 x 作为整数Public y As Integer公共 cx 作为整数Public cy As Integer公共标志为 UInteger末端结构私有枚举 DCX 作为整数缓存 = &H2剪辑儿童 = &H8CLIPSIBLINGS = &H10排除 = &H40排除更新 = &H100INTERSECTRGN = &H80INTERSECTUPDATE = &H200LOCKWINDOWUPDATE = &H400NORECOMPUTE = &H100000NORESETATTRS = &H4父剪辑 = &H20验证 = &H200000窗口 = &H1结束枚举结束类

In my previous question I have sorted out how to create container dependent control. Now, I am getting problem in that control. the design of control is little bit confusing. the design is looks like this.

In this design, developer could not add control outside the Page Control. The PageControl will be added automatically in the client area. I want to prevent user to add control outside the PageControl. I am not going to make confusion any more. So, my question is how do I do this?

You can see class declaration in my previous question

If you have any other idea to do this then please suggest me.

UPDATE:

Control should look like this.

but, After assigning non-client area the placed control goes inside the client area. I want to prevent user to add control in that portion.

解决方案

The easy way

The easiest way is to recalculate the bounds of the XWizardPage whenever the size of its parent changes.

Public Class XWizardPage
    Inherits DevExpress.XtraEditors.XtraPanel
    Implements IComparable(Of XWizardPage)

    Protected Overrides Sub OnResize(e As System.EventArgs)
        MyBase.OnResize(e)
        If (Not Me.positioningInternal) Then Me.Position()
    End Sub

    Protected Overrides Sub SetBoundsCore(x As Integer, y As Integer, width As Integer, height As Integer, specified As System.Windows.Forms.BoundsSpecified)
        MyBase.SetBoundsCore(x, y, width, height, specified)
        If (Not Me.positioningInternal) Then Me.Position()
    End Sub

    Protected Overrides Sub OnParentChanged(e As System.EventArgs)
        MyBase.OnParentChanged(e)
        If (Not Me.cachedParent Is Nothing) Then
            RemoveHandler Me.cachedParent.SizeChanged, AddressOf Me.OnParentSizeChanged
        End If
        Me.cachedParent = If(((Not Me.Parent Is Nothing) AndAlso (TypeOf Me.Parent Is XWizardControl)), Me.Parent, Nothing)
        If (Not Me.cachedParent Is Nothing) Then
            AddHandler Me.cachedParent.SizeChanged, AddressOf Me.OnParentSizeChanged
        End If
    End Sub

    Private Sub OnParentSizeChanged(sender As Object, e As EventArgs)
        Me.Position()
    End Sub

    Private Sub Position()
        If (Not Me.cachedParent Is Nothing) Then
            Dim r As Rectangle = Me.cachedParent.ClientRectangle
            r.Y += 10
            r.Height -= (10 * 2)
            If (Me.Bounds <> r) Then
                Me.positioningInternal = True
                Me.Bounds = r
                Me.positioningInternal = False
            End If
        End If
    End Sub

    Private cachedParent As Control
    Private positioningInternal As Boolean

End Class

The hard way

The hard way requires native calls. I cannot append a complete solution as this is pretty complex, though doable. The term you're looking for is nonclient area. There are many tutorials on the web, and you should do a search.

The following code is just an example to show you where to start and is not a final solution. For this to work perfect, you'll need to handle Window redraw, Mouse events etc.

Public Class XWizardControl
    Inherits DevExpress.XtraEditors.XtraUserControl

    <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> _
    Private Shared Function GetDCEx(ByVal hWnd As IntPtr, ByVal hrgnClip As IntPtr, ByVal flags As Integer) As IntPtr
    End Function

    Private Sub WmNcCalcSize(ByRef m As Message)
        If (m.WParam.ToInt32() = 0) Then
            Dim ncRect As RECT = DirectCast(m.GetLParam(GetType(RECT)), RECT)
            ncRect.top += 10
            ncRect.bottom -= 10
            Marshal.StructureToPtr(ncRect, m.LParam, False)
            m.Result = IntPtr.Zero
        ElseIf (m.WParam.ToInt32() = 1) Then
            Dim ncParams As NCCALCSIZE_PARAMS = DirectCast(m.GetLParam(GetType(NCCALCSIZE_PARAMS)), NCCALCSIZE_PARAMS)
            ncParams.rectProposed.top += 10
            ncParams.rectProposed.bottom -= 10
            Marshal.StructureToPtr(ncParams, m.LParam, False)
            m.Result = IntPtr.Zero
        Else
            MyBase.WndProc(m)
        End If
    End Sub

    Private Sub WmNcPaint(ByRef m As Message)
        Dim hDC As IntPtr = GetDCEx(m.HWnd, m.WParam, (DCX.WINDOW Or DCX.INTERSECTRGN Or DCX.CACHE Or DCX.CLIPSIBLINGS))
        If (hDC.ToInt32() <> 0) Then
            Using g As Graphics = Graphics.FromHdc(hDC)
                g.Clear(Color.Red)
            End Using
            m.Result = IntPtr.Zero
        Else
            MyBase.WndProc(m)
        End If
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Select Case m.Msg
            Case WM_NCCALCSIZE : Me.WmNcCalcSize(m) : Exit Select
            Case WM_NCPAINT : Me.WmNcPaint(m) : Exit Select
            Case Else : MyBase.WndProc(m) : Exit Select
        End Select
    End Sub

    Public Const WM_NCCALCSIZE As Integer = 131
    Public Const WM_NCPAINT As Integer = 133

    <StructLayout(LayoutKind.Sequential)> _
    Private Structure RECT
        Public left As Integer
        Public top As Integer
        Public right As Integer
        Public bottom As Integer
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Private Structure NCCALCSIZE_PARAMS
        Public rectProposed As RECT
        Public rectBeforeMove As RECT
        Public rectClientBeforeMove As RECT
        Public lppos As WINDOWPOS
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Private Structure WINDOWPOS
        Public hwnd As IntPtr
        Public hWndInsertAfter As IntPtr
        Public x As Integer
        Public y As Integer
        Public cx As Integer
        Public cy As Integer
        Public flags As UInteger
    End Structure

    Private Enum DCX As Integer
        CACHE = &H2
        CLIPCHILDREN = &H8
        CLIPSIBLINGS = &H10
        EXCLUDERGN = &H40
        EXCLUDEUPDATE = &H100
        INTERSECTRGN = &H80
        INTERSECTUPDATE = &H200
        LOCKWINDOWUPDATE = &H400
        NORECOMPUTE = &H100000
        NORESETATTRS = &H4
        PARENTCLIP = &H20
        VALIDATE = &H200000
        WINDOW = &H1
    End Enum

End Class

这篇关于如何在 UserControl 中创建部分客户区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆