如何在UserControl中创建部分客户区? [英] How to create partially client area in UserControl?
问题描述
在上一个问题中,我已经整理出如何创建依赖于容器的控件.现在,我在该控件中遇到问题.控件的设计有点令人困惑.设计看起来像这样.
在此设计中,开发人员无法在页面控件之外添加控件.PageControl将自动添加到工作区中.我想防止用户在PageControl之外添加控件.我不会再感到困惑了.所以,我的问题是我该怎么做?
您可以在我之前的.网络上有很多教程,您应该进行搜索.
以下代码仅是向您展示从哪里开始的示例,并非最终解决方案.为此,您需要处理 Window redraw
, Mouse events
等.
公共类XWizardControl继承DevExpress.XtraEditors.XtraUserControl< DllImport("user32.dll",CharSet:= CharSet.Auto,ExactSpelling:= True)>_私有共享函数GetDCEx(ByVal hWnd为IntPtr,ByVal hrgnClip为IntPtr,ByVal标志为Integer)为IntPtr结束功能私人子WmNcCalcSize(ByRef m作为消息)如果(m.WParam.ToInt32()= 0)昏暗ncRect为RECT = DirectCast(m.GetLParam(GetType(RECT)),RECT)ncRect.top + = 10ncRect.bottom-= 10元帅.StructureToPtr(ncRect,m.LParam,False)m.结果=整数零ElseIf(m.WParam.ToInt32()= 1)然后昏暗ncParams为NCCALCSIZE_PARAMS = DirectCast(m.GetLParam(GetType(NCCALCSIZE_PARAMS)),NCCALCSIZE_PARAMS)ncParams.rectProposed.top + = 10ncParams.rectProposed.bottom-= 10元帅StructureToPtr(ncParams,m.LParam,False)m.结果=整数零别的MyBase.WndProc(m)万一结束子私人子WmNcPaint(由消息引用)Dim hDC As IntPtr = GetDCEx(m.HWnd,m.WParam,(DCX.WINDOW或DCX.INTERSECTRGN或DCX.CACHE或DCX.CLIPSIBLINGS))如果(hDC.ToInt32()<> 0)然后使用g作为Graphics = Graphics.FromHdc(hDC)g.清除(颜色:红色)最终使用m.结果=整数零别的MyBase.WndProc(m)万一结束子受保护的重写子WndProc(由System.Windows.Forms.Message继承)选择案例m.gsg案例WM_NCCALCSIZE:Me.WmNcCalcSize(m):退出选择案例WM_NCPAINT:Me.WmNcPaint(m):退出选择其他情况:MyBase.WndProc(m):退出选择结束选择结束子公共常量WM_NCCALCSIZE作为整数= 131公共常量WM_NCPAINT作为整数= 133< StructLayout(LayoutKind.Sequential)>_私人结构RECT公开左为整数公共顶级As Integer作为整数的公共权利公共底部为Integer末端结构< StructLayout(LayoutKind.Sequential)>_私有结构NCCALCSIZE_PARAMS公开建议为RECT公共rectBeforeMove作为RECT公开rectClientBeforeMove作为RECT作为WINDOWPOS的公开lppos末端结构< StructLayout(LayoutKind.Sequential)>_私人结构WINDOWPOS作为IntPtr公开拥有作为IntPtr的公共hWndInsertAfterPublic x As Integer以整数形式公开Public cx As Integer作为整数的公共循环作为UInteger的公共标志末端结构私有枚举DCX作为整数缓存=& H2CLIPCHILDREN =& H8CLIPSIBLINGS =& H10EXCLUDERGN =& H40EXCLUDEUPDATE =& 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屋!