|
Hello,
I think I understand your requirement ... and ... my code-snippet was much nearer to your requirement as I (or you) thought.
So ... let's start once again :
When I began with Controls-Development I startet like you - each and every customized Control was a UserControl. That is good for start but often not good for Behaviour.
So nowadays most of my controls derive from Control and normaly I try not to use other controls inside my Control.
The next part you should know is (that is also a part of your explaining) :
Nearly every action of a control which is possible during RunTime is also possible during DesignTime (this part can be realized with the ControlDesigner) - but it's not easy to find out how to realize that. So ... what I suggest to do for you is : I work-over my "Split-Control" to be a Stand-alone Control and post you the Code. But this will take a little time. After this you take a look at it, try to understand it and don't be angry with some german-named Variables. After this we can discuss it and/or I answer further questions.
Best regards to you
Ralf
|
|
|
|
|
... and here the code from my Control (it isn't complete anymore but it could show you how Splitting could be done) :
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Runtime.CompilerServices
Imports System.Windows.Forms.Design
Imports System.Windows.Forms.Design.Behavior
Imports System.Drawing.Drawing2D
<Description("Anzeige zur Darstellung eines Analogwertes mit zugehörigem Beschreibungs-Text und Einheit")>
<ToolboxItem(True)>
<Designer(GetType(RMValueDisplay.Designer))>
Public Class RMValueDisplay
Inherits Control
Implements ICustomTypeDescriptor
#Region "Konstruktor / Dispose"
Public Sub New()
Me.Size = New Size(300, 40)
Me.Invalidate()
End Sub
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
MyBase.Dispose(disposing)
End Sub
#End Region
#Region "Echte Transparenz herstellen"
Private Sub SetTransparenz()
Me.SetStyle(ControlStyles.Opaque, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, False)
Me.SetStyle(ControlStyles.ResizeRedraw, True)
End Sub
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim cp As CreateParams = MyBase.CreateParams
cp.ExStyle = cp.ExStyle Or &H20
Return cp
End Get
End Property
#End Region
#Region "ausgeblendete Properties"
Private myRemoveProperties As String() = {
"AllowDrop",
"Anchor",
"BackgroundImage",
"BackgroundImageLayout",
"CausesValidation",
"Cursor",
"Dock",
"Enabled",
"ImeMode",
"Margin",
"MaximumSize",
"MinimumSize",
"Padding",
"RightToLeft",
"TabIndex",
"TabStop",
"Text",
"UseWaitCursor"
}
#End Region
#Region "eigene Definitionen"
<TypeConverter(GetType(SpaltenTrennerDefinition.Converter))>
Public Class SpaltenTrennerDefinition
<Description("Position der 1. Spalte im Control")>
Property Pos1 As Int32
Get
Return my_Pos1
End Get
Set(ByVal value As Int32)
If my_Pos1 <> value Then
If value < 0 Then value = 0
If value > my_Pos2 Then value = my_Pos2
my_Pos1 = value
If Parent IsNot Nothing Then my_Pos1Proz = CSng(my_Pos1) / CSng(CType(Parent, Control).Width)
RaiseEvent Changed()
End If
End Set
End Property
Private my_Pos1Proz As Single = 0.6
Private my_Pos1 As Int32 = my_Pos1Proz * 300
<Description("Position der 2. Spalte im Control")>
Property Pos2 As Int32
Get
Return my_Pos2
End Get
Set(ByVal value As Int32)
If my_Pos2 <> value Then
my_Pos2 = value
If my_Pos2 < my_Pos1 Then my_Pos2 = my_Pos1
If Parent IsNot Nothing Then my_Pos2Proz = CSng(my_Pos2) / CSng(CType(Parent, Control).Width)
RaiseEvent Changed()
End If
End Set
End Property
Private my_Pos2Proz As Single = 0.85
Private my_Pos2 As Int32 = my_Pos2Proz * 300
Public Event Changed()
Property Parent As Object = Nothing
Public Sub New(xParent As Object, setPos1 As Int32, setPos2 As Int32)
Parent = CType(xParent, Control)
Dim my_Width As Integer = Parent.Width
If setPos1 < 0 Then setPos1 = 0
If setPos2 < 0 Then setPos2 = 0
If setPos1 > setPos2 Then setPos1 = setPos2
If setPos2 < setPos1 Then setPos2 = setPos1
If setPos1 > my_Width Then setPos1 = my_Width
If setPos2 > my_Width Then setPos2 = my_Width
my_Pos1 = setPos1
my_Pos1Proz = my_Pos1 / my_Width
my_Pos2 = setPos2
my_Pos2Proz = my_Pos2 / my_Width
RaiseEvent Changed()
End Sub
Public Sub New()
End Sub
Public Sub New(setPos1 As Int32, setPos2 As Int32)
If setPos1 < 0 Then setPos1 = 0
If setPos2 < 0 Then setPos2 = 0
If setPos1 > setPos2 Then setPos1 = setPos2
If setPos2 < setPos1 Then setPos2 = setPos1
my_Pos1 = setPos1
my_Pos2 = setPos2
RaiseEvent Changed()
End Sub
Public Sub ReCalculate(my_Width As Integer)
my_Pos1 = my_Pos1Proz * my_Width
my_Pos2 = my_Pos2Proz * my_Width
End Sub
Public Overrides Function ToString() As String
Return my_Pos1.ToString + "; " + my_Pos2.ToString
End Function
Public Class Converter
Inherits ExpandableObjectConverter
Public Overloads Overrides Function CanConvertFrom(ByVal context As ITypeDescriptorContext, ByVal sourceType As Type) As Boolean
If sourceType Is GetType(String) Then Return True
Return MyBase.CanConvertFrom(context, sourceType)
End Function
Public Overloads Overrides Function ConvertFrom(ByVal context As ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object
If value.GetType Is GetType(String) Then
Dim s As String = CType(value, String)
Dim sa As String() = Split(s, ";")
If sa.Length >= 2 Then
Dim p1, p2 As Integer
If Integer.TryParse(sa(0), p1) AndAlso Integer.TryParse(sa(1), p2) Then
Return New SpaltenTrennerDefinition(context.Instance, p1, p2)
End If
End If
Throw New FormatException()
End If
Return MyBase.ConvertFrom(context, culture, value)
End Function
Public Overloads Overrides Function CanConvertTo(context As System.ComponentModel.ITypeDescriptorContext, destinationType As System.Type) As Boolean
If destinationType Is GetType(System.ComponentModel.Design.Serialization.InstanceDescriptor) Then Return True
Return MyBase.CanConvertTo(context, destinationType)
End Function
Public Overloads Overrides Function ConvertTo(context As System.ComponentModel.ITypeDescriptorContext, culture As System.Globalization.CultureInfo, value As Object, destinationType As System.Type) As Object
If destinationType Is GetType(System.ComponentModel.Design.Serialization.InstanceDescriptor) Then
Dim ctor As Reflection.ConstructorInfo
Dim s As String = value.ToString
Dim sa As String() = Split(s, ";")
If sa.Length >= 2 Then
Dim p1, p2 As Integer
If Integer.TryParse(sa(0), p1) AndAlso Integer.TryParse(sa(1), p2) Then
ctor = GetType(SpaltenTrennerDefinition).GetConstructor(New Type() {GetType(Int32), GetType(Int32)})
Return New System.ComponentModel.Design.Serialization.InstanceDescriptor(ctor, New Object() {p1, p2}, True)
End If
End If
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
End Class
#End Region
#Region "Expandable Properties"
<Category("Layout"), Description("Definition der Spalten-Aufteilung im Control")>
<RefreshProperties(RefreshProperties.All)>
Property SpaltenTrenner As SpaltenTrennerDefinition
Get
Return my_SpaltenTrenner
End Get
Set(ByVal value As SpaltenTrennerDefinition)
my_SpaltenTrenner = value
Me.Invalidate()
End Set
End Property
Private WithEvents my_SpaltenTrenner As New SpaltenTrennerDefinition()
#End Region
#Region "Properties zur Darstellung"
<Category("Layout"), Description("Definition der Größe des Control")>
<RefreshProperties(RefreshProperties.All)>
Shadows Property Size As Size
Get
Return MyBase.Size
End Get
Set(ByVal value As Size)
If value.Width <> MyBase.Width Then
MyBase.Width = value.Width
my_SpaltenTrenner.ReCalculate(value.Width)
End If
MyBase.Height = value.Height
End Set
End Property
<Category("Darstellung"), Description("legt die Hintergrundfarbe im Control fest")>
<DefaultValue(GetType(Color), "LightGray")>
Shadows Property BackColor As Color
Get
Return my_BackColor
End Get
Set(ByVal value As Color)
MyBase.BackColor = value
my_BackColor = value
Me.Invalidate()
End Set
End Property
Private my_BackColor As Color = Color.LightGray
<Category("Darstellung"), Description("legt die Schriftfarbe im Control fest")>
<DefaultValue(GetType(Color), "Black")>
Shadows Property ForeColor As Color
Get
Return my_ForeColor
End Get
Set(ByVal value As Color)
MyBase.ForeColor = value
my_ForeColor = value
Me.Invalidate()
End Set
End Property
Private my_ForeColor As Color = Color.Black
<Category("Darstellung"), Description("legt die Rahmen-Farbe des Labels fest")>
<DefaultValue(GetType(System.Drawing.Color), "Gray")>
<DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)>
Property BorderColor As Color
Get
Return my_BorderColor
End Get
Set(ByVal value As Color)
my_BorderColor = value
Me.Invalidate()
End Set
End Property
Private my_BorderColor As Color = Color.Gray
<Category("Anzeige"), Description("legt die Schriftart im Control fest")>
Shadows Property Font As Font
Get
Return MyBase.Font
End Get
Set(ByVal value As Font)
MyBase.Font = value
End Set
End Property
#End Region
#Region "interne Aktionen"
Private Sub SpaltenTrenner_Changed() Handles my_SpaltenTrenner.Changed
Me.Invalidate()
End Sub
Protected Overrides Sub OnResize(e As EventArgs)
my_SpaltenTrenner.ReCalculate(Me.Width)
MyBase.OnResize(e)
Me.Invalidate()
End Sub
Protected Overrides Sub OnHandleCreated(e As System.EventArgs)
myParent = Parent
isInitialized = True
Me.Invalidate()
MyBase.OnHandleCreated(e)
End Sub
Private WithEvents myParent As Control
Private isInitialized As Boolean = False
#End Region
#Region "Implementierung der ISelectionService-Schnittstelle um festzustellen, dass das Control angewählt wurde"
<Browsable(False)>
ReadOnly Property Activated As Boolean
Get
If selectionService IsNot Nothing Then Return selectionService.GetComponentSelected(Me)
Return False
End Get
End Property
Private selectionService As ISelectionService
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never)>
Public Overrides Property Site() As ISite
Get
Return MyBase.Site
End Get
Set(ByVal Value As ISite)
MyBase.Site = Value
If MyBase.Site Is Nothing Then Return
selectionService = Me.Site.GetService(GetType(ISelectionService))
End Set
End Property
#End Region
#Region "Properties bedingt ein-/ausblenden"
Private Function FilterProperties(ByVal origProperties As PropertyDescriptorCollection) As PropertyDescriptorCollection
Dim myPD As PropertyDescriptor
Dim myListe As New List(Of PropertyDescriptor)
Dim setHidden As Boolean
For i As Integer = 0 To origProperties.Count - 1
myPD = origProperties.Item(i)
setHidden = False
If setHidden Then
myPD = TypeDescriptor.CreateProperty(myPD.ComponentType, myPD, New Attribute() {New BrowsableAttribute(False), New EditorBrowsableAttribute(EditorBrowsableState.Never)})
End If
If Not myRemoveProperties.Contains(myPD.Name) Then myListe.Add(myPD)
Next
Dim myPDListe(myListe.Count - 1) As PropertyDescriptor
myListe.CopyTo(myPDListe)
Return New PropertyDescriptorCollection(myPDListe)
End Function
#End Region
#Region "ICustomTypeDescriptor - Properties ein-/ausblenden"
<Description("Simply delegates to the TypeDescriptor method.")> _
Public Function GetAttributes() As System.ComponentModel.AttributeCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetAttributes
Return TypeDescriptor.GetAttributes(Me, True)
End Function
<Description("Simply delegates to the TypeDescriptor method.")> _
Public Function GetClassName() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetClassName
Return TypeDescriptor.GetClassName(Me, True)
End Function
<Description("Simply delegates to the TypeDescriptor method.")> _
Public Function GetComponentNaMe() As String Implements System.ComponentModel.ICustomTypeDescriptor.GetComponentName
Return TypeDescriptor.GetComponentName(Me, True)
End Function
<Description("Simply delegates to the TypeDescriptor method.")> _
Public Function GetConverter() As System.ComponentModel.TypeConverter _
Implements System.ComponentModel.ICustomTypeDescriptor.GetConverter
Return TypeDescriptor.GetConverter(Me, True)
End Function
<Description("Simply delegates to the TypeDescriptor method.")> _
Public Function GetDefaultEvent() As System.ComponentModel.EventDescriptor _
Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent
Return TypeDescriptor.GetDefaultEvent(Me, True)
End Function
<Description("Simply delegates to the TypeDescriptor method.")> _
Public Function GetDefaultProperty() As System.ComponentModel.PropertyDescriptor _
Implements System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty
Return TypeDescriptor.GetDefaultProperty(Me, True)
End Function
<Description("Simply delegates to the TypeDescriptor method.")> _
Public Function GetEditor(ByVal editorBaseType As System.Type) As Object _
Implements System.ComponentModel.ICustomTypeDescriptor.GetEditor
Return TypeDescriptor.GetEditor(Me, editorBaseType, True)
End Function
<Description("Simply delegates to the TypeDescriptor method.")> _
Public Overloads Function GetEvents() As System.ComponentModel.EventDescriptorCollection _
Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
Return TypeDescriptor.GetEvents(Me, True)
End Function
<Description("Simply delegates to the TypeDescriptor method.")> _
Public Overloads Function GetEvents(ByVal attributes() As System.Attribute) As System.ComponentModel.EventDescriptorCollection _
Implements System.ComponentModel.ICustomTypeDescriptor.GetEvents
Return TypeDescriptor.GetEvents(Me, attributes, True)
End Function
<Description("Returns the wrapped object.")> _
Public Function GetPropertyOwner(ByVal pd As System.ComponentModel.PropertyDescriptor) As Object _
Implements System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner
Return Me
End Function
<Description("Returns the list of properties as defined in the constructor")> _
Public Overloads Function GetProperties() As System.ComponentModel.PropertyDescriptorCollection _
Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
Dim pd As PropertyDescriptorCollection = TypeDescriptor.GetProperties(Me, True)
Return FilterProperties(pd)
End Function
<Description("Returns the list of properties as defined in the constructor")> _
Public Overloads Function GetProperties(ByVal attributes() As System.Attribute) As System.ComponentModel.PropertyDescriptorCollection _
Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
Dim pd As PropertyDescriptorCollection = TypeDescriptor.GetProperties(Me, attributes, True)
Return FilterProperties(pd)
End Function
#End Region
#Region "Designer"
Public Class Designer
Inherits System.Windows.Forms.Design.ControlDesigner
Private HostControl As RMValueDisplay = Nothing
Public Overrides Sub Initialize(ByVal component As System.ComponentModel.IComponent)
MyBase.Initialize(component)
HostControl = DirectCast(component, RMValueDisplay)
End Sub
Protected Overrides Sub PreFilterProperties(ByVal properties As System.Collections.IDictionary)
MyBase.PreFilterProperties(properties)
properties.Remove("AccessibleDescription")
properties.Remove("AccessibleName")
properties.Remove("AccessibleRole")
properties.Remove("ApplicationSettings")
properties.Remove("DataBindings")
properties.Remove("ContextMenuStrip")
properties.Remove("GenerateMember")
properties.Remove("Locked")
End Sub
Public Overrides ReadOnly Property SnapLines As System.Collections.IList
Get
Dim snaps As ArrayList = New ArrayList(MyBase.SnapLines)
snaps.Add(New SnapLine(SnapLineType.Horizontal, Me.Control.Height \ 2))
snaps.Add(New SnapLine(SnapLineType.Vertical, Me.Control.Width \ 2))
Return snaps
End Get
End Property
Protected Overrides Sub OnSetCursor()
Dim myPoint As Point = HostControl.PointToClient(Cursor.Position)
If inShiftPosition(myPoint) > 0 Then
If Dragging_Aktiv Then
Cursor.Current = Cursors.Arrow
Else
Cursor.Current = Cursors.SizeWE
End If
Else
MyBase.OnSetCursor()
End If
End Sub
Private Function inShiftPosition(ByVal p As Point) As Integer
If HostControl IsNot Nothing AndAlso HostControl.Activated Then
If (p.X >= HostControl.SpaltenTrenner.Pos1 - Dragging_ShiftHysterese) AndAlso (p.X <= HostControl.SpaltenTrenner.Pos1 + Dragging_ShiftHysterese) Then
Return 1
ElseIf (p.X >= HostControl.SpaltenTrenner.Pos2 - Dragging_ShiftHysterese) AndAlso (p.X <= HostControl.SpaltenTrenner.Pos2 + Dragging_ShiftHysterese) Then
Return 2
Else
Return 0
End If
Else
Return 0
End If
End Function
Private Dragging_ShiftHysterese As Integer = 3
Private Dragging_Aktiv As Boolean = False
Private Dragging_ShiftPoint As Integer = 0
Private Dragging_Offset As Integer = 0
Protected Overrides Sub OnMouseDragBegin(ByVal x As Integer, ByVal y As Integer)
If HostControl Is Nothing Then Exit Sub
Dim myPoint As Point = HostControl.PointToClient(New Point(x, y))
Dragging_ShiftPoint = inShiftPosition(myPoint)
If Dragging_ShiftPoint = 1 Then
Dragging_Offset = HostControl.SpaltenTrenner.Pos1 - myPoint.X
Dragging_Aktiv = True
ElseIf Dragging_ShiftPoint = 2 Then
Dragging_Offset = HostControl.SpaltenTrenner.Pos2 - myPoint.X
Dragging_Aktiv = True
Else
MyBase.OnMouseDragBegin(x, y)
End If
End Sub
Protected Overrides Sub OnMouseDragMove(ByVal x As Integer, ByVal y As Integer)
If HostControl Is Nothing Then Exit Sub
Dim myPoint As Point = HostControl.PointToClient(New Point(x, y))
If Dragging_Aktiv Then
If Dragging_ShiftPoint = 1 Then
HostControl.SpaltenTrenner.Pos1 = myPoint.X + Dragging_Offset
ElseIf Dragging_ShiftPoint = 2 Then
HostControl.SpaltenTrenner.Pos2 = myPoint.X + Dragging_Offset
End If
Else
MyBase.OnMouseDragMove(x, y)
End If
End Sub
Protected Overrides Sub OnMouseDragEnd(ByVal cancel As Boolean)
Dragging_Aktiv = False
MyBase.OnMouseDragEnd(cancel)
End Sub
Protected Overrides Sub OnPaintAdornments(ByVal pe As System.Windows.Forms.PaintEventArgs)
If HostControl Is Nothing Then Exit Sub
If HostControl.Activated Then
Dim borderPen As New Pen(HostControl.ForeColor)
If HostControl.BackColor = Color.Transparent Then borderPen = New Pen(HostControl.Parent.ForeColor)
borderPen.DashStyle = Drawing2D.DashStyle.Dash
pe.Graphics.DrawRectangle(borderPen, 0, 0, HostControl.SpaltenTrenner.Pos1 - 1, HostControl.Height - 1)
pe.Graphics.DrawRectangle(borderPen, HostControl.SpaltenTrenner.Pos1 + 1, 0, HostControl.SpaltenTrenner.Pos2 - HostControl.SpaltenTrenner.Pos1 - 2, HostControl.Height - 1)
pe.Graphics.DrawRectangle(borderPen, HostControl.SpaltenTrenner.Pos2 + 1, 0, HostControl.Width - HostControl.SpaltenTrenner.Pos2 - 2, HostControl.Height - 1)
borderPen.Dispose()
Else
If (HostControl.BackColor = Color.Transparent) Then
Dim borderPen As New Pen(HostControl.ForeColor)
If HostControl.BackColor = Color.Transparent Then borderPen = New Pen(HostControl.Parent.ForeColor)
borderPen.DashStyle = Drawing2D.DashStyle.Dash
pe.Graphics.DrawRectangle(borderPen, 0, 0, HostControl.Width - 1, HostControl.Height - 1)
borderPen.Dispose()
End If
End If
MyBase.OnPaintAdornments(pe)
End Sub
End Class
#End Region
End Class
|
|
|
|
|
Hello,
Thank you for this sample code. It is very interesting to me. Some of this implementation
is new to me and I will have to study to see how I can apply to my control. It may take
a couple of days for me to understand your sample and apply to my control. I will let you
know when I have figured it out.
Thanks again for your continued efforts.
Best regards
|
|
|
|
|
Hello Ralf,
The sample code that you supplied is excellent.
It is so much simpler than the sample code I started with from the MSDN library.
I have gained more understanding of the ControlDesigner from your sample.
I have recreated my control using your sample as a guide and everything is working
good now. I can select my child panels, resize them, and drag and drop controls within
the panels now.
I really appreciate your patience and desire to help me with this problem.
Many thanks
|
|
|
|
|
You are welcome ... and I'm very glad about your response.
And you know : if you have further questions ... feel free to ask ...
Additional :
I don't know your goal ... but I suppose that you don't need Panels for the Rest. But that is your turn to decide.
|
|
|
|
|
I'm sorry ... the solution I gave to you with your last question was incomplete.
You must enhance your ControlDesigner with this code (Property-Names are the same as before) :
Protected Overrides Sub OnPaintAdornments(ByVal pe As System.Windows.Forms.PaintEventArgs)
If HostControl Is Nothing Then Exit Sub
Dim borderPen As New Pen(HostControl.ForeColor)
borderPen.DashStyle = Drawing2D.DashStyle.Dash
pe.Graphics.DrawRectangle(borderPen, 0, 0, HostControl.SpaltenTrenner.Pos1 - 1, HostControl.Height - 1)
pe.Graphics.DrawRectangle(borderPen, HostControl.SpaltenTrenner.Pos1 + 1, 0, HostControl.SpaltenTrenner.Pos2 - HostControl.SpaltenTrenner.Pos1 - 2, HostControl.Height - 1)
pe.Graphics.DrawRectangle(borderPen, HostControl.SpaltenTrenner.Pos2 + 1, 0, HostControl.Width - HostControl.SpaltenTrenner.Pos2 - 2, HostControl.Height - 1)
borderPen.Dispose()
MyBase.OnPaintAdornments(pe)
End Sub
But Attention :
I don't have several Controls - I have only one Control with the required Behaviour ...
|
|
|
|
|
Hello, I am new to this site so if I am on the wrong board, I am sorry; please help me.
I have created a control similar to the SplitContainer.
I am new to using the ParentControlDesigner but with the help of other articles have
implemented my control using it.
I have created a main control using a custom ParentControlDesigner.
I have created a splitter bar control also using a custom ParentControlDesigner.
During run time the main control passes an event object to the splitter bar which
will raise the event when MouseUp occurs. The main control will resize the left and
right panels when the event occurs.
Everything works at run time.
Problem: The event mentioned above does not work in design mode so the main control
cannot adjust the panels.
Question: In design mode, is there a way that I can program the main control so it
can detected when the splitter bar has moved, or a way to program the splitter bar
to inform the main control when splitter bar is moved?
Thank you
|
|
|
|
|
Each ControlDesigner has several methods to pass the Mouse-Functionality to the Control in DesignTime the same way like in RunTime-mode.
For your requirement I would suggest you use/override the Methods OnMouseDragBegin, OnMouseDragMove and OnMouseDragEnd from the Designer.
With this methods you could modify properties from the HostControl.
Public Class myControlDesigner
Inherits System.Windows.Forms.Design.ControlDesigner
Private HostControl As RMWertAnzeigeValue2 = Nothing
Public Overrides Sub Initialize(ByVal component As System.ComponentModel.IComponent)
MyBase.Initialize(component)
HostControl = DirectCast(component, RMWertAnzeigeValue2)
End Sub
Protected Overrides Sub OnSetCursor()
Dim myPoint As Point = HostControl.PointToClient(Cursor.Position)
If inShiftPosition(myPoint) > 0 Then
If Dragging_Aktiv Then
Cursor.Current = Cursors.Arrow
Else
Cursor.Current = Cursors.SizeWE
End If
Else
MyBase.OnSetCursor()
End If
End Sub
Private Function inShiftPosition(ByVal p As Point) As Integer
If HostControl IsNot Nothing AndAlso HostControl.Activated Then
If (p.X >= HostControl.SpaltenTrenner.Pos1 - Dragging_ShiftHysterese) AndAlso (p.X <= HostControl.SpaltenTrenner.Pos1 + Dragging_ShiftHysterese) Then
Return 1
ElseIf (p.X >= HostControl.SpaltenTrenner.Pos2 - Dragging_ShiftHysterese) AndAlso (p.X <= HostControl.SpaltenTrenner.Pos2 + Dragging_ShiftHysterese) Then
Return 2
Else
Return 0
End If
Else
Return 0
End If
End Function
Private Dragging_ShiftHysterese As Integer = 3
Private Dragging_Aktiv As Boolean = False
Private Dragging_ShiftPoint As Integer = 0
Private Dragging_Offset As Integer = 0
Protected Overrides Sub OnMouseDragBegin(ByVal x As Integer, ByVal y As Integer)
If HostControl Is Nothing Then Exit Sub
Dim myPoint As Point = HostControl.PointToClient(New Point(x, y))
Dragging_ShiftPoint = inShiftPosition(myPoint)
If Dragging_ShiftPoint = 1 Then
Dragging_Offset = HostControl.SpaltenTrenner.Pos1 - myPoint.X
Dragging_Aktiv = True
ElseIf Dragging_ShiftPoint = 2 Then
Dragging_Offset = HostControl.SpaltenTrenner.Pos2 - myPoint.X
Dragging_Aktiv = True
Else
MyBase.OnMouseDragBegin(x, y)
End If
End Sub
Protected Overrides Sub OnMouseDragMove(ByVal x As Integer, ByVal y As Integer)
If HostControl Is Nothing Then Exit Sub
Dim myPoint As Point = HostControl.PointToClient(New Point(x, y))
If Dragging_Aktiv Then
If Dragging_ShiftPoint = 1 Then
HostControl.SpaltenTrenner.Pos1 = myPoint.X + Dragging_Offset
ElseIf Dragging_ShiftPoint = 2 Then
HostControl.SpaltenTrenner.Pos2 = myPoint.X + Dragging_Offset
End If
Else
MyBase.OnMouseDragMove(x, y)
End If
End Sub
Protected Overrides Sub OnMouseDragEnd(ByVal cancel As Boolean)
Dragging_Aktiv = False
MyBase.OnMouseDragEnd(cancel)
End Sub
End Class
In this code SpaltenTrenner is a class-property which is equal to your requirement - sorry that some comments are in german.
I think, it could help you to see what should be done.
RMWertAnzeigeValue2 is the type a my Control which consists of 3 sections.
|
|
|
|
|
Thank you for the example code. This has been very helpful to my problem.
|
|
|
|
|
You are welcome ...
If you have further questions the feel free to ask ...
|
|
|
|
|
Good day,
in advance I appreciate the help. I have the following problem ...
I developed an application where I capture some data from a web page using vb.net and the object of the SHDocVw.WebBrowser interface, what it does is that if it finds a certain page, it saves it as body.innerHTML in a string variable. Until a few days ago it worked perfectly. the page where I capture the data changed the structure of it (Links, Field names, labels) and it does not let me take the values. When I go through the debug process in vb.net, it shows me the variable loaded with the innerHTML but as if there were no data ready, so this is seeing them on the page.
also try to save the page (complete, HTML) from the IE to validate that it keeps the data entered on the page and does not save it, that is, as if it had not written anything. I do not know what to do to be able to save those fields correctly. Any suggestions always welcome. Thank you.
These are the tools with which I develop:
Visual Studio 2013
SO: 8.1 pro
IE: 11
--Process--
Dim ShellOnWindows As New ShellWindowsClass
Dim ObjectOfPoliedro As SHDocVw.WebBrowser
Try
'--runs all instances of internet explorer--'
For Each ObjectOfPoliedro In ShellOnWindows
Dim NameOfBrowser As String = ObjectOfPoliedro.Name.ToLower.ToString
'--check if name of browser contains internet explorer--'
If NameOfBrowser.ToString.Contains("internet explorer") Or NameOfBrowser.ToString.Contains("internet") Or NameOfBrowser.ToString.Contains("explorer") Then
Dim LocationOfBrowser As String = ObjectOfPoliedro.LocationURL.ToLower.ToString
Dim TitleOfBrowser As String = ObjectOfPoliedro.LocationName.ToLower.ToString
Dim DocumentOfPoliedro As mshtml.HTMLDocument = TryCast(ObjectOfPoliedro.Document, mshtml.HTMLDocument)
Dim StrinOfPage As String = DocumentOfPoliedro.body.innerHTML
|
|
|
|
|
Your problem is most likely the source web site, so you need to talk to the owners. It may well be that they have changed things in order to protect their intellectual property.
|
|
|
|
|
Hi..where can i learn to play MIDI sounds through an USB MIDI controller?!
I have a MIDI instruments example where i can play sounds with the PC´s keyboard...but i would like to play them from my MIDI controller..although i am totally blind on that part!
I googled but i did not found something realy clear about it..specialy for VB!
Thanks for any Support!
Duarte
modified 7-Jan-19 21:02pm.
|
|
|
|
|
|
Hi....i found this simple plugin called Jazz Plugin that seems to have a very simple code..although i am not figuring out why it is returning me these errors!
this is the thing:
<pre>Public Class Form1
Dim chan As Integer = 0
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim list As String() = Jazz.MidiOutList()
For Each s In list
Out.Items.Add(s)
Next s
Out.SelectedIndex = 0
tone.SelectedIndex = 0
Channel.SelectedIndex = 0
End Sub
Private Sub Out_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Out.SelectedIndexChanged
Jazz.MidiOutOpen(Out.SelectedItem)
End Sub
Private Sub Channel_SelectedIndexChanged(sender As Object, e As EventArgs) Handles Channel.SelectedIndexChanged
chan = Channel.SelectedIndex
End Sub
Private Function Note(ByVal obj As System.Object)
If ReferenceEquals(obj, Button1) Then
Return 53
ElseIf ReferenceEquals(obj, Button2) Then
Return 55
End If
Return 0
End Function
Private Sub ToneChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tone.SelectedIndexChanged
Jazz.MidiOut(&HC0 + chan, tone.SelectedIndex, 0)
End Sub
Private Sub Down(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseDown, Button2.MouseDown
Jazz.MidiOut(&H90 + chan, Note(sender), 100)
End Sub
Private Sub Up(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseUp, Button2.MouseUp
Jazz.MidiOut(&H80 + chan, Note(sender), 0)
End Sub
End Class
and its returnning the errors on these lines:
<pre> Private Sub ToneChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tone.SelectedIndexChanged
Jazz.MidiOut(&HC0 + chan, tone.SelectedIndex, 0)
End Sub
Private Sub Down(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseDown, Button2.MouseDown
Jazz.MidiOut(&H90 + chan, Note(sender), 100)
End Sub
Private Sub Up(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseUp, Button2.MouseUp
Jazz.MidiOut(&H80 + chan, Note(sender), 0)
End Sub
Any help...?!
modified 7-Jan-19 21:02pm.
|
|
|
|
|
Alienoiz wrote: and its returnning the errors on these lines:
Which errors?
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
the code underlined is being treated as an error!
modified 7-Jan-19 21:02pm.
|
|
|
|
|
Yes.. but what's the description of the error
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
Severity Code Description Project File Line Suppression State
Error BC30311 Value of type 'Integer' cannot be converted to 'Object()'. WindowsApplication1 C:\Users\beata\Documents\Visual Studio 2015\Projects\WindowsApplication1\WindowsApplication1\Form1.vb 35 Active
Error BC30057 Too many arguments to 'Public Overridable Overloads Sub MidiOut([in] As Object())'. WindowsApplication1 C:\Users\beata\Documents\Visual Studio 2015\Projects\WindowsApplication1\WindowsApplication1\Form1.vb 35 Active
modified 7-Jan-19 21:02pm.
|
|
|
|
|
The method Jazz.MidiOut that's intended to being called there isn't part of the project you downloaded. I assume it's in that "Jazz-Plugin" which is advertised on the website and it doesn't look like the source code of that is being offered. You should ask for help on that website.
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
OK..i will try..Thank You!
modified 7-Jan-19 21:02pm.
|
|
|
|
|
Well... i did not had an answer..even because my registration in their forums was a mess..and i could not even register there!
I searched for more help and i came accross with some examples..i kinda mixed 2 codes and i am now able to open my midi devices an play the sounds through my MIDI controller. I am only having 2 issues that i am not being able to solve!
1 - the sound is playing twice..one for "note on" another for "note off"...when i press my MIDI controller key it plays..and when i release it ..it plays again!!!!
2 - the notes seem to be infinite..i do not know where to put the
STOPAllMIDINotes() function!
I have all this code:
<pre> Public Declare Function midiInGetNumDevs Lib "winmm.dll" () As Integer
Public Declare Function midiInGetDevCaps Lib "winmm.dll" Alias "midiInGetDevCapsA" (ByVal uDeviceID As Integer, ByRef lpCaps As MIDIINCAPS, ByVal uSize As Integer) As Integer
Public Declare Function midiInOpen Lib "winmm.dll" (ByRef hMidiIn As Integer, ByVal uDeviceID As Integer, ByVal dwCallback As MidiInCallback, ByVal dwInstance As Integer, ByVal dwFlags As Integer) As Integer
Public Declare Function midiInStart Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
Public Declare Function midiInStop Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
Public Declare Function midiInReset Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
Public Declare Function midiInClose Lib "winmm.dll" (ByVal hMidiIn As Integer) As Integer
Public Delegate Function MidiInCallback(ByVal hMidiIn As Integer, ByVal wMsg As UInteger, ByVal dwInstance As Integer, ByVal dwParam1 As Integer, ByVal dwParam2 As Integer) As Integer
Public ptrCallback As New MidiInCallback(AddressOf MidiInProc)
Public Const CALLBACK_FUNCTION As Integer = &H30000
Public Const MIDI_IO_STATUS = &H20
Public Delegate Sub DisplayDataDelegate(dwParam1)
Public Structure MIDIINCAPS
Dim wMid As Int16
Dim wPid As Int16
Dim vDriverVersion As Integer
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> Dim szPname As String
Dim dwSupport As Integer
End Structure
Dim hMidiIn As Integer
Dim DataByte1 As Byte
Dim m As New clsMIDI
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
FillInstrumentCombo()
If midiInGetNumDevs() = 0 Then
MsgBox("No MIDI devices connected")
Application.Exit()
End If
Dim InCaps As New MIDIINCAPS
Dim DevCnt As Integer
For DevCnt = 0 To (midiInGetNumDevs - 1)
midiInGetDevCaps(DevCnt, InCaps, Len(InCaps))
ComboBox1.Items.Add(InCaps.szPname)
Next DevCnt
midiInStart(hMidiIn)
End Sub
Function MidiInProc(ByVal hMidiIn As Integer, ByVal wMsg As UInteger, ByVal dwInstance As Integer, ByVal dwParam1 As Integer, ByVal dwParam2 As Integer) As Integer
DataByte1 = (dwParam1 And &HFF00) >> 8
m.PlayMIDINote(DataByte1, 127)
m.STOPAllMIDINotes()
End Function
Private Sub ComboBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim DeviceID As Integer = ComboBox1.SelectedIndex
midiInOpen(hMidiIn, DeviceID, ptrCallback, 0, CALLBACK_FUNCTION Or MIDI_IO_STATUS)
midiInStart(hMidiIn)
End Sub
Private Sub Form1_Closed(sender As Object, e As EventArgs) Handles Me.Closed
midiInStop(hMidiIn)
midiInReset(hMidiIn)
midiInClose(hMidiIn)
Application.Exit()
End Sub
I do not know where "to go" now...!!!
modified 7-Jan-19 21:02pm.
|
|
|
|
|
HI..some help please..
I have changed my code and i am now able to select a MIDI Device and play notes from it!
I am now facing a problem that is - note duration
When i insert the code for note duration it returns me an error that says something like this:
"the code is using a thread for what was not created"
Heres the code i am using...and i am also using a module called clsMIDI
<pre>Public Class Form1
Dim m As New clsMIDI
Dim hMidiIn As Integer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
FillInstrumentCombo()
If midiInGetNumDevs() = 0 Then
MsgBox("No MIDI devices connected")
End If
Dim InCaps As New MIDIINCAPS
Dim DevCnt As Integer
For DevCnt = 0 To (midiInGetNumDevs - 1)
midiInGetDevCaps(DevCnt, InCaps, Len(InCaps))
ComboBox1.Items.Add(InCaps.szPname)
Next DevCnt
midiInStart(hMidiIn)
End Sub
Private Sub Form1_Closed(sender As Object, e As EventArgs) Handles Me.Closed
midiInStop(hMidiIn)
midiInReset(hMidiIn)
midiInClose(hMidiIn)
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim DeviceID As Integer = ComboBox1.SelectedIndex
midiInOpen(hMidiIn, DeviceID, AddressOf MidiInProc, 0, CALLBACK_FUNCTION)
midiInStart(hMidiIn)
End Sub
Private Sub FillInstrumentCombo()
For i = 0 To 128
cboInstruments.Items.Add(Instrument.GMInstrumentNames(i))
Next
cboInstruments.SelectedIndex = 0
End Sub
Private Sub cboInstruments_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboInstruments.SelectedIndexChanged
m.CurrentInstrument = cboInstruments.Text
End Sub
Private Sub hsbVolume_ValueChanged(sender As Object, e As EventArgs) Handles hsbVolume.ValueChanged
m.Volume = hsbVolume.Value
End Sub
Function MidiInProc(ByVal hMidiIn As Integer, ByVal wMsg As UInteger, ByVal dwInstance As Integer, ByVal dwParam1 As Integer, ByVal dwParam2 As Integer) As Integer
Dim DataByte1 = (dwParam1) >> 8
m.PlayMIDINote(DataByte1, 127)
m.NoteDuration = CInt(cboduration.Text)
m.Pan = 50
End Function
End Class
TIA
modified 7-Jan-19 21:02pm.
|
|
|
|
|
Controls (a Form, ComboBox, TextBox..) can only be accessed by the UI-thread. That's the thread that created them and the thread that executes all your code unless you either explicitly create additional threads or use some kind of event/callback mechanism - the latter you apparently do here:
midiInOpen(hMidiIn, DeviceID, AddressOf MidiInProc, 0, CALLBACK_FUNCTION) So that midi-library you're using seems to call your function MidiInProc(..) on a different thread than your UI-thread and then tries to access cboduration.Text which is one of your controls which may only be accessed by your UI thread. That's the problem.
The easiest solution for you here is this: Read the value of cboduration.Text into a class variable (let's call it duration ) the moment that it is changed by the user. Also initialize that variable with the same value as the control. Then replace this:
m.NoteDuration = CInt(cboduration.Text)
..by this:
m.NoteDuration = duration
Now the UI thread does the reading from the control and the thread that executes MidiInProc doesn't "touch" any controls any more.
If the brain were so simple we could understand it, we would be so simple we couldn't. — Lyall Watson
|
|
|
|
|
"The easiest solution for you here is this: Read the value of cboduration.Text into a class variable (let's call it duration) the moment that it is changed by the user. Also initialize that variable with the same value as the control."
May you show me the code for this...???
Thank you!
modified 7-Jan-19 21:02pm.
|
|
|
|
|