Extending RichTextBox - Help Required

M

Martin Horn

Hi,

I am trying to add extra functionality to the standard RichText control, but
I've fallen at the first hurdle,can someone take a look at the following
code and tell me why it fails to return true if the current selection is
bold.

Thanks,

Martin Horn.

Imports System.Runtime.InteropServices

Public Class RichTextEx
Inherits RichTextBox

<StructLayout(LayoutKind.Sequential)> _
Public Structure STRUCT_CHARFORMAT
Public cbSize As Integer
Public dwMask As UInt32
Public dwEffects As UInt32
Public yHeight As Int32
Public yOffset As Int32
Public crTextColor As Int32
Public bCharSet As Byte
Public bPitchAndFamily As Byte
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=32)> _
Public szFaceName As Char()
End Structure

<DllImport("user32.dll")> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, _
ByVal msg As Int32, _
ByVal wParam As Int32, _
ByVal lParam As IntPtr) As Int32
End Function

Public Const EM_GETCHARFORMAT As Int32 = &H43A&
Public Const SCF_SELECTION As Int32 = &H1&
Public Const CFM_BOLD As Int32 = &H1&
Public Const CFE_BOLD As Int32 = &H1&

' Just to test the SelectionBold Property
Public Sub New()
MyBase.New()
Me.Font = New Font("Times New Roman", 10, FontStyle.Bold)
End Sub

Public Property SelectionBold() As Boolean
Get
Dim fmt As New STRUCT_CHARFORMAT
fmt.cbSize = Marshal.SizeOf(fmt)
Dim lParam As IntPtr
lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmt))
Marshal.StructureToPtr(fmt, lParam, False)
SendMessage(Me.Handle, EM_GETCHARFORMAT, SCF_SELECTION, lParam)
If ((fmt.dwMask And CFM_BOLD) = 0) Then
Return False
End If
If ((fmt.dwEffects And CFE_BOLD) = 0) Then
Return False
Else
Return True
End If
End Get
Set(ByVal value As Boolean)
'// Not Implemented //
End Set
End Property

End Class
 
K

Ken Tucker [MVP]

Hi,

I changed your sendmessage api to pass lparam as
STRUCT_CHARFORMAT byref.

Public Class RichTextEx

Inherits RichTextBox

<StructLayout(LayoutKind.Sequential)> _

Public Structure STRUCT_CHARFORMAT

Public cbSize As Integer

Public dwMask As Int32

Public dwEffects As Int32

Public yHeight As Int32

Public yOffset As Int32

Public crTextColor As Int32

Public bCharSet As Byte

Public bPitchAndFamily As Byte

<MarshalAs(UnmanagedType.ByValArray, SizeConst:=32)> _

Public szFaceName As Char()

End Structure

<DllImport("user32.dll")> _

Private Shared Function SendMessage(ByVal hWnd As IntPtr, _

ByVal msg As Int32, _

ByVal wParam As Int32, _

ByRef lParam As STRUCT_CHARFORMAT) As Int32

End Function

Public Const EM_GETCHARFORMAT As Int32 = &H43A&

Public Const SCF_SELECTION As Int32 = &H1&

Public Const CFM_BOLD As Int32 = &H1&

Public Const CFE_BOLD As Int32 = &H1&

' Just to test the SelectionBold Property

Public Sub New()

MyBase.New()

Me.Font = New Font("Times New Roman", 10, FontStyle.Bold)

End Sub

Public Property SelectionBold() As Boolean

Get

Dim fmt As New STRUCT_CHARFORMAT

fmt.cbSize = Marshal.SizeOf(fmt)

SendMessage(Me.Handle, EM_GETCHARFORMAT, SCF_SELECTION, fmt)

If ((fmt.dwMask And CFM_BOLD) = 0) Then

Return False

End If

If ((fmt.dwEffects And CFE_BOLD) = 0) Then

Return False

Else

Return True

End If

End Get

Set(ByVal value As Boolean)

'// Not Implemented //

End Set

End Property

End Class





Ken

---------------------

Hi,

I am trying to add extra functionality to the standard RichText control, but
I've fallen at the first hurdle,can someone take a look at the following
code and tell me why it fails to return true if the current selection is
bold.

Thanks,

Martin Horn.

Imports System.Runtime.InteropServices

Public Class RichTextEx
Inherits RichTextBox

<StructLayout(LayoutKind.Sequential)> _
Public Structure STRUCT_CHARFORMAT
Public cbSize As Integer
Public dwMask As UInt32
Public dwEffects As UInt32
Public yHeight As Int32
Public yOffset As Int32
Public crTextColor As Int32
Public bCharSet As Byte
Public bPitchAndFamily As Byte
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=32)> _
Public szFaceName As Char()
End Structure

<DllImport("user32.dll")> _
Private Shared Function SendMessage(ByVal hWnd As IntPtr, _
ByVal msg As Int32, _
ByVal wParam As Int32, _
ByVal lParam As IntPtr) As Int32
End Function

Public Const EM_GETCHARFORMAT As Int32 = &H43A&
Public Const SCF_SELECTION As Int32 = &H1&
Public Const CFM_BOLD As Int32 = &H1&
Public Const CFE_BOLD As Int32 = &H1&

' Just to test the SelectionBold Property
Public Sub New()
MyBase.New()
Me.Font = New Font("Times New Roman", 10, FontStyle.Bold)
End Sub

Public Property SelectionBold() As Boolean
Get
Dim fmt As New STRUCT_CHARFORMAT
fmt.cbSize = Marshal.SizeOf(fmt)
Dim lParam As IntPtr
lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(fmt))
Marshal.StructureToPtr(fmt, lParam, False)
SendMessage(Me.Handle, EM_GETCHARFORMAT, SCF_SELECTION, lParam)
If ((fmt.dwMask And CFM_BOLD) = 0) Then
Return False
End If
If ((fmt.dwEffects And CFE_BOLD) = 0) Then
Return False
Else
Return True
End If
End Get
Set(ByVal value As Boolean)
'// Not Implemented //
End Set
End Property

End Class
 
M

Martin Horn

Hi again,

I've encountered another problem with coding this property, this is how I
have it at the moment:

Public Enum BoldStateEnum As Integer
Mixed = 0
Regular = 1
Bold = 2
End Enum

Public Property SelectionBold() As BoldStateEnum
Get
Dim fmt As STRUCT_CHARFORMAT
fmt = GetCharFormat()
If ((fmt.dwMask And CFM_BOLD) = 0) Then
Return BoldStateEnum.Mixed
End If
If ((fmt.dwEffects And CFE_BOLD) = 0) Then
Return BoldStateEnum.Regular
Else
Return BoldStateEnum.Bold
End If
End Get
Set(ByVal value As BoldStateEnum)
Dim fmt As New STRUCT_CHARFORMAT
fmt = GetCharFormat()
If value = BoldStateEnum.Bold Then
fmt.dwMask = fmt.dwMask Or CFM_BOLD
fmt.dwEffects = (fmt.dwEffects Or CFE_BOLD)
Else
' Debug.Assert("SelectionBold = False - Not Implemeted")
End If
SetCharFormat(fmt)
End Set
End Property

Everything seems to work as it should, however when I try to view the form
designer for the form that contains my extended richtext control I get the
following error:
---------------------
One or more errors encountered while loading the designer.The errors are
listed below. Some errors can be fixed by rebuilding your project, while
others may require code changes. Clicking on each error will take you to the
line of code that caused it.

The name 'PC_Till_V2.RichTextBoxEx+BoldStateEnum' is not a valid type name.
---------------------

If I remove the line Me.rtf1.SelectionBold =
RichTextBoxEx.BoldStateEnum.Regular from the form's designer code it allows
the design view to show again.

So whilst I have a workaround for this I would still like to know what I am
doing wrong, as I can't initialise the property properly.

Any ideas?

Thanks,

Martin Horn.
 
K

Ken Tucker [MVP]

Hi,

I would make sure I build the control before I open the form
designer. If that doesnt work remove the control from the form and add the
control to the toolbox again. Then add it to the form. Maybe it is still
using the older version of the control.

Ken
-----------------
Hi again,

I've encountered another problem with coding this property, this is how I
have it at the moment:

Public Enum BoldStateEnum As Integer
Mixed = 0
Regular = 1
Bold = 2
End Enum

Public Property SelectionBold() As BoldStateEnum
Get
Dim fmt As STRUCT_CHARFORMAT
fmt = GetCharFormat()
If ((fmt.dwMask And CFM_BOLD) = 0) Then
Return BoldStateEnum.Mixed
End If
If ((fmt.dwEffects And CFE_BOLD) = 0) Then
Return BoldStateEnum.Regular
Else
Return BoldStateEnum.Bold
End If
End Get
Set(ByVal value As BoldStateEnum)
Dim fmt As New STRUCT_CHARFORMAT
fmt = GetCharFormat()
If value = BoldStateEnum.Bold Then
fmt.dwMask = fmt.dwMask Or CFM_BOLD
fmt.dwEffects = (fmt.dwEffects Or CFE_BOLD)
Else
' Debug.Assert("SelectionBold = False - Not Implemeted")
End If
SetCharFormat(fmt)
End Set
End Property

Everything seems to work as it should, however when I try to view the form
designer for the form that contains my extended richtext control I get the
following error:
---------------------
One or more errors encountered while loading the designer.The errors are
listed below. Some errors can be fixed by rebuilding your project, while
others may require code changes. Clicking on each error will take you to the
line of code that caused it.

The name 'PC_Till_V2.RichTextBoxEx+BoldStateEnum' is not a valid type name.
---------------------

If I remove the line Me.rtf1.SelectionBold =
RichTextBoxEx.BoldStateEnum.Regular from the form's designer code it allows
the design view to show again.

So whilst I have a workaround for this I would still like to know what I am
doing wrong, as I can't initialise the property properly.

Any ideas?

Thanks,

Martin Horn.
 
M

Martin Horn

Hi Ken,

that still didn't fix it. The problem seems to occur if I create an
inherited control class that has a property that reurns an enum value. See
below for an example that demonstrates the problem.

I created a new project with a single form. Then I added the follwing class:

Public Class TestClass
Inherits Button
Private fValue As TestClassEnum

Public Enum TestClassEnum
Value1 = 0
Value2 = 1
End Enum

Public Property ReturnEnum() As TestClassEnum
Get
Return fValue.Value1
End Get
Set(ByVal value As TestClassEnum)
fValue = value
End Set
End Property
End Class

If I close the form designer, save the project then try to re-open the form
designer I get the following error, but I can't see what I'm doing wrong.

-------------------------------------------
One or more errors encountered while loading the designer.The errors are
listed below. Some errors can be fixed by rebuilding your project, while
others may require code changes. Clicking on each error will take you to the
line of code that caused it.

The variable 'Value1' is either undeclared or was never assigned.
Hide
Edit

at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.Error(IDesignerSerializationManager
manager, String exceptionText, String helpLink)
at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeExpression(IDesignerSerializationManager
manager, String name, CodeExpression expression)
at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeAssignStatement(IDesignerSerializationManager
manager, CodeAssignStatement statement)
at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeStatement(IDesignerSerializationManager
manager, CodeStatement statement)
 
K

Ken Tucker [MVP]

Hi,

Sorry I cant reproduce the error. Make sure you have the latest
service pack for the dotnet framework installed. If you are still having
problems reinstall the dot net framework and as a last resort vb.net

http://msdn.microsoft.com/netframework/downloads/updates/default.aspx


Ken
------
Hi Ken,

that still didn't fix it. The problem seems to occur if I create an
inherited control class that has a property that reurns an enum value. See
below for an example that demonstrates the problem.

I created a new project with a single form. Then I added the follwing class:

Public Class TestClass
Inherits Button
Private fValue As TestClassEnum

Public Enum TestClassEnum
Value1 = 0
Value2 = 1
End Enum

Public Property ReturnEnum() As TestClassEnum
Get
Return fValue.Value1
End Get
Set(ByVal value As TestClassEnum)
fValue = value
End Set
End Property
End Class

If I close the form designer, save the project then try to re-open the form
designer I get the following error, but I can't see what I'm doing wrong.

-------------------------------------------
One or more errors encountered while loading the designer.The errors are
listed below. Some errors can be fixed by rebuilding your project, while
others may require code changes. Clicking on each error will take you to the
line of code that caused it.

The variable 'Value1' is either undeclared or was never assigned.
Hide
Edit

at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.Error(IDesignerSerializationManager
manager, String exceptionText, String helpLink)
at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeExpression(IDesignerSerializationManager
manager, String name, CodeExpression expression)
at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeAssignStatement(IDesignerSerializationManager
manager, CodeAssignStatement statement)
at
System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeStatement(IDesignerSerializationManager
manager, CodeStatement statement)
 
M

Martin Horn

Okay, so it looks like it's a problem peculiar to my setup, I'll do as you
suggest.

Thanks,

Martin.
 
M

Martin Horn

Just in case this may help anyone else, I have discovered that moving the
enum outside of the class fixes the problem, as follows:

Public Enum TestClassEnum
Value1 = 0
Value2 = 1
End Enum

Public Class TestClass
Inherits Button
Private fValue As TestClassEnum = TestClassEnum.Value1
Public Property ReturnEnum() As TestClassEnum
Get
Return fValue.Value1
End Get
Set(ByVal value As TestClassEnum)
fValue = value
End Set
End Property
End Class

I hope posting a late update to this topic isn't a problem.

Regards,

Martin Horn.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top