Rowdyone52
asked on
DataGridView - Adding Label Controls
Good Morning.
I have a DataGridView control on a form and need to do the following...
I have a dataset that I would like to add to the DataGridView, but need to display it with some color coding and boxing.
I would like to add each line of text to a cell as a lable, that way I can set the text color and put a border around the text if I need to.
I basically need this
24
GREG - Out of Office (color=red)
BOB - In Meeting (color=Green)
FRED - PAL Day(Color=blue)(border=1)
Can anyone tell me how to add label controls to a cell in a DataGridView or how to accomplish this another way?
ASKER
I would love to see your sample code when you get a chance.
DataGridViewRichTextCell:
Imports System.Runtime.InteropServ ices
Imports System.Drawing.Printing
Imports VB6 = Microsoft.VisualBasic.Comp atibility. VB6
Public Class DataGridViewRichTextCell
Inherits DataGridViewTextBoxCell
Private m_rtfTemplate As New RichTextBox
Protected Overrides Sub Paint(ByVal graphics As Graphics, _
ByVal clipBounds As Rectangle, ByVal cellBounds As Rectangle, _
ByVal rowIndex As Integer, ByVal cellState As DataGridViewElementStates, _
ByVal value As Object, ByVal formattedValue As Object, _
ByVal errorText As String, ByVal cellStyle As DataGridViewCellStyle, _
ByVal advancedBorderStyle As DataGridViewAdvancedBorder Style, _
ByVal paintParts As DataGridViewPaintParts)
Dim brush As New SolidBrush(cellStyle.BackC olor)
graphics.FillRectangle(bru sh, cellBounds)
brush.Dispose()
' Convert the text to Rtf, and then transfer to the Graphics object.
Me.PaintRtf(formattedValue , graphics, cellBounds, cellStyle.Font, cellStyle.BackColor)
' Paint the cell border after everything is done, or it will get
' overridden.
MyBase.PaintBorder(graphic s, clipBounds, cellBounds, cellStyle, advancedBorderStyle)
End Sub
Private Function GetSelectionLink(ByVal charIndex As Integer) As Boolean
Const SCF_SELECTION As Int32 = &H1
Const CFE_LINK As Int32 = &H20
Dim cf As CHARFORMAT2_STRUCT = New CHARFORMAT2_STRUCT
cf.cbSize = CType(Marshal.SizeOf(cf), UInt32)
cf.szFaceName = New Char(32) {}
Dim wParam As IntPtr = New IntPtr(SCF_SELECTION)
Dim lParam As IntPtr = Marshal.AllocCoTaskMem(Mar shal.SizeO f(cf))
Marshal.StructureToPtr(cf, lParam, False)
Dim res As IntPtr = SendMessage(m_rtfTemplate. Handle, EM_GETCHARFORMAT, wParam, lParam)
cf = CType(Marshal.PtrToStructu re(lParam, GetType(CHARFORMAT2_STRUCT )), CHARFORMAT2_STRUCT)
Marshal.FreeCoTaskMem(lPar am)
Return (cf.dwEffects And CFE_LINK)
End Function
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
' Use the current date and time as the default value.
Return String.Empty
End Get
End Property
#Region "PaintRtf"
<StructLayout(LayoutKind.S equential) > _
Private Structure CHARFORMAT2_STRUCT
Public cbSize As UInt32
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.B yValArray, SizeConst:=32)> _
Public szFaceName As Char()
Public wWeight As UInt16
Public sSpacing As UInt16
Public crBackColor As Integer
Public lcid As Integer
Public dwReserved As Integer
Public sStyle As Int16
Public wKerning As Int16
Public bUnderlineType As Byte
Public bAnimation As Byte
Public bRevAuthor As Byte
Public bReserved1 As Byte
End Structure
<StructLayout(LayoutKind.S equential) > _
Private Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
<StructLayout(LayoutKind.S equential) > _
Private Structure CHARRANGE
Public cpMin As Integer ' First character of range (0 for start of doc)
Public cpMax As Integer ' Last character of range (-1 for end of doc)
End Structure
<StructLayout(LayoutKind.S equential) > _
Private Structure FORMATRANGE
Public hdc As IntPtr ' Actual DC to draw on
Public hdcTarget As IntPtr ' Target DC for determining text formatting
Public rc As RECT ' Region of the DC to draw to (in twips)
Public rcPage As RECT ' Region of the whole DC (page size) (in twips)
Public chrg As CHARRANGE ' Range of text to draw (see above declaration)
End Structure
Private Const WM_USER As Int32 = &H400
Private Const EM_FORMATRANGE As Int32 = WM_USER + 57
Private Const EM_GETCHARFORMAT As Int32 = (WM_USER + 58)
Private Declare Function SendMessage Lib "USER32" Alias "SendMessageA" _
(ByVal hWnd As IntPtr, ByVal msg As Int32, ByVal wparam As IntPtr, _
ByVal lparam As IntPtr) As IntPtr
' Render the contents of the RichTextBox for printing
' Return the last character printed + 1 (printing start from this point for next page)
Private Sub PaintRtf(ByVal value As String, ByVal gr As Graphics, ByVal bounds As Rectangle, ByVal font As Font, ByVal backColor As Color)
If value Is Nothing Then
Exit Sub
End If
' Use an internal RichTextBox to format the text according to the
' business rules.
m_rtfTemplate.Font = font
m_rtfTemplate.WordWrap = False
m_rtfTemplate.Text = value
m_rtfTemplate.BackColor = backColor
m_rtfTemplate.DetectUrls = True
' Mark starting and ending character.
Dim cRange As CHARRANGE
cRange.cpMin = 0
cRange.cpMax = value.Length
' Calculate the area to render and print. The bounds need to
' be converted from pixels to twips (1/1440 of an inch).
Dim rectCell As New RECT
rectCell.Left = VB6.PixelsToTwipsX(bounds. Left) + 30
rectCell.Top = VB6.PixelsToTwipsY(bounds. Top) + 30
rectCell.Right = VB6.PixelsToTwipsX(bounds. Right)
rectCell.Bottom = VB6.PixelsToTwipsY(bounds. Bottom)
Dim rectPrint As RECT = rectCell
' Get the DC for the graphics object.
Dim hdc As IntPtr = gr.GetHdc()
' Initialize the FORMATRANGE structure for the EM_FORMATRANGE message.
Dim fmtRange As FORMATRANGE
fmtRange.chrg = cRange ' Indicate character from to character to
fmtRange.hdc = hdc ' Use the same DC for measuring and rendering
fmtRange.hdcTarget = hdc ' Point at printer hDC
fmtRange.rc = rectPrint ' Indicate the area on page to print
fmtRange.rcPage = rectCell ' Indicate whole size of page
Dim wParam As IntPtr = New IntPtr(1)
' Pass the FORMATRANGE structure to the lParam handle for the
' EM_FORMATRANGE message sent to the internal RichTextBox.
Dim lParam As IntPtr = Marshal.AllocCoTaskMem(Mar shal.SizeO f(fmtRange ))
Marshal.StructureToPtr(fmt Range, lParam, False)
' Tell the RichTextBox to paint on the DC.
Dim res As IntPtr = SendMessage(m_rtfTemplate. Handle, EM_FORMATRANGE, wParam, lParam)
' Free the block of memory allocated.
Marshal.FreeCoTaskMem(lPar am)
' Release the device context handle obtained by a previous call.
gr.ReleaseHdc(hdc)
End Sub
#End Region
End Class
Imports System.Runtime.InteropServ
Imports System.Drawing.Printing
Imports VB6 = Microsoft.VisualBasic.Comp
Public Class DataGridViewRichTextCell
Inherits DataGridViewTextBoxCell
Private m_rtfTemplate As New RichTextBox
Protected Overrides Sub Paint(ByVal graphics As Graphics, _
ByVal clipBounds As Rectangle, ByVal cellBounds As Rectangle, _
ByVal rowIndex As Integer, ByVal cellState As DataGridViewElementStates,
ByVal value As Object, ByVal formattedValue As Object, _
ByVal errorText As String, ByVal cellStyle As DataGridViewCellStyle, _
ByVal advancedBorderStyle As DataGridViewAdvancedBorder
ByVal paintParts As DataGridViewPaintParts)
Dim brush As New SolidBrush(cellStyle.BackC
graphics.FillRectangle(bru
brush.Dispose()
' Convert the text to Rtf, and then transfer to the Graphics object.
Me.PaintRtf(formattedValue
' Paint the cell border after everything is done, or it will get
' overridden.
MyBase.PaintBorder(graphic
End Sub
Private Function GetSelectionLink(ByVal charIndex As Integer) As Boolean
Const SCF_SELECTION As Int32 = &H1
Const CFE_LINK As Int32 = &H20
Dim cf As CHARFORMAT2_STRUCT = New CHARFORMAT2_STRUCT
cf.cbSize = CType(Marshal.SizeOf(cf), UInt32)
cf.szFaceName = New Char(32) {}
Dim wParam As IntPtr = New IntPtr(SCF_SELECTION)
Dim lParam As IntPtr = Marshal.AllocCoTaskMem(Mar
Marshal.StructureToPtr(cf,
Dim res As IntPtr = SendMessage(m_rtfTemplate.
cf = CType(Marshal.PtrToStructu
Marshal.FreeCoTaskMem(lPar
Return (cf.dwEffects And CFE_LINK)
End Function
Public Overrides ReadOnly Property DefaultNewRowValue() As Object
Get
' Use the current date and time as the default value.
Return String.Empty
End Get
End Property
#Region "PaintRtf"
<StructLayout(LayoutKind.S
Private Structure CHARFORMAT2_STRUCT
Public cbSize As UInt32
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.B
Public szFaceName As Char()
Public wWeight As UInt16
Public sSpacing As UInt16
Public crBackColor As Integer
Public lcid As Integer
Public dwReserved As Integer
Public sStyle As Int16
Public wKerning As Int16
Public bUnderlineType As Byte
Public bAnimation As Byte
Public bRevAuthor As Byte
Public bReserved1 As Byte
End Structure
<StructLayout(LayoutKind.S
Private Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
<StructLayout(LayoutKind.S
Private Structure CHARRANGE
Public cpMin As Integer ' First character of range (0 for start of doc)
Public cpMax As Integer ' Last character of range (-1 for end of doc)
End Structure
<StructLayout(LayoutKind.S
Private Structure FORMATRANGE
Public hdc As IntPtr ' Actual DC to draw on
Public hdcTarget As IntPtr ' Target DC for determining text formatting
Public rc As RECT ' Region of the DC to draw to (in twips)
Public rcPage As RECT ' Region of the whole DC (page size) (in twips)
Public chrg As CHARRANGE ' Range of text to draw (see above declaration)
End Structure
Private Const WM_USER As Int32 = &H400
Private Const EM_FORMATRANGE As Int32 = WM_USER + 57
Private Const EM_GETCHARFORMAT As Int32 = (WM_USER + 58)
Private Declare Function SendMessage Lib "USER32" Alias "SendMessageA" _
(ByVal hWnd As IntPtr, ByVal msg As Int32, ByVal wparam As IntPtr, _
ByVal lparam As IntPtr) As IntPtr
' Render the contents of the RichTextBox for printing
' Return the last character printed + 1 (printing start from this point for next page)
Private Sub PaintRtf(ByVal value As String, ByVal gr As Graphics, ByVal bounds As Rectangle, ByVal font As Font, ByVal backColor As Color)
If value Is Nothing Then
Exit Sub
End If
' Use an internal RichTextBox to format the text according to the
' business rules.
m_rtfTemplate.Font = font
m_rtfTemplate.WordWrap = False
m_rtfTemplate.Text = value
m_rtfTemplate.BackColor = backColor
m_rtfTemplate.DetectUrls = True
' Mark starting and ending character.
Dim cRange As CHARRANGE
cRange.cpMin = 0
cRange.cpMax = value.Length
' Calculate the area to render and print. The bounds need to
' be converted from pixels to twips (1/1440 of an inch).
Dim rectCell As New RECT
rectCell.Left = VB6.PixelsToTwipsX(bounds.
rectCell.Top = VB6.PixelsToTwipsY(bounds.
rectCell.Right = VB6.PixelsToTwipsX(bounds.
rectCell.Bottom = VB6.PixelsToTwipsY(bounds.
Dim rectPrint As RECT = rectCell
' Get the DC for the graphics object.
Dim hdc As IntPtr = gr.GetHdc()
' Initialize the FORMATRANGE structure for the EM_FORMATRANGE message.
Dim fmtRange As FORMATRANGE
fmtRange.chrg = cRange ' Indicate character from to character to
fmtRange.hdc = hdc ' Use the same DC for measuring and rendering
fmtRange.hdcTarget = hdc ' Point at printer hDC
fmtRange.rc = rectPrint ' Indicate the area on page to print
fmtRange.rcPage = rectCell ' Indicate whole size of page
Dim wParam As IntPtr = New IntPtr(1)
' Pass the FORMATRANGE structure to the lParam handle for the
' EM_FORMATRANGE message sent to the internal RichTextBox.
Dim lParam As IntPtr = Marshal.AllocCoTaskMem(Mar
Marshal.StructureToPtr(fmt
' Tell the RichTextBox to paint on the DC.
Dim res As IntPtr = SendMessage(m_rtfTemplate.
' Free the block of memory allocated.
Marshal.FreeCoTaskMem(lPar
' Release the device context handle obtained by a previous call.
gr.ReleaseHdc(hdc)
End Sub
#End Region
End Class
DataGridViewRichTextColumn :
Public Class DataGridViewRichTextColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New DataGridViewRichTextCell)
End Sub
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
' Ensure that the cell used for the template is a CalendarCell.
If Not (value Is Nothing) AndAlso _
Not value.GetType().IsAssignab leFrom(Get Type(DataG ridViewRic hTextCell) ) _
Then
Throw New InvalidCastException("Must be a DataGridViewRichTextCell")
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
Bob
Public Class DataGridViewRichTextColumn
Inherits DataGridViewColumn
Public Sub New()
MyBase.New(New DataGridViewRichTextCell)
End Sub
Public Overrides Property CellTemplate() As DataGridViewCell
Get
Return MyBase.CellTemplate
End Get
Set(ByVal value As DataGridViewCell)
' Ensure that the cell used for the template is a CalendarCell.
If Not (value Is Nothing) AndAlso _
Not value.GetType().IsAssignab
Then
Throw New InvalidCastException("Must
End If
MyBase.CellTemplate = value
End Set
End Property
End Class
Bob
Sample usage:
Private Sub ConfigureGrid()
Me.gridQuestion.AutoGenera teColumns = False
Me.gridQuestion.Columns.Cl ear()
Dim column As New DataGridViewRichTextColumn ()
column.ReadOnly = True
column.Width = Me.gridQuestion.ClientSize .Width
Me.gridQuestion.Columns.Ad d(column)
End Sub
Bob
Private Sub ConfigureGrid()
Me.gridQuestion.AutoGenera
Me.gridQuestion.Columns.Cl
Dim column As New DataGridViewRichTextColumn
column.ReadOnly = True
column.Width = Me.gridQuestion.ClientSize
Me.gridQuestion.Columns.Ad
End Sub
Bob
ASKER
What dll should I reference in order to be able to import - Imports VB6 = Microsoft.VisualBasic.Comp atibility. VB6
ASKER
Nevermind, I got it :)
ASKER
OK I have your code working. I cannot figure out how to change a line of text color, or how to add a border around a line of text. I have tried several methods.
The text, in this case, needs to be rich text. You can use a RichTextBox control to get the right Rtf text, and then set the cell value to that. To get borders, you can specify a cell border.
Bob
Bob
ASKER
I tried to set the value and it didnt work correctly. Could you paste a sample code to achieve...
<GREEN>GREG R</GREEN>NEWLINE
<RED>BOB SMITH</RED>
<GREEN>GREG R</GREEN>NEWLINE
<RED>BOB SMITH</RED>
ASKER
"{\\rtf1\\ansi\\ansicpg125 2\\deff0\\ deflang103 3{\\fonttb l{\\f0\\fn il\\fchars et0 Microsoft Sans Serif;}}\r\n{\\colortbl ;\\red0\\green0\\blue255;\ \red255\\g reen255\\b lue0;}\r\n \\viewkind 4\\uc1\\pa rd\\f0\\fs 17 dude we \\cf1 are\\cf0 \\cf2 working\\cf0\\par\r\n}\r\n "
shows as multicolored in a richtextbox, but doesnt format in the datagridview
shows as multicolored in a richtextbox, but doesnt format in the datagridview
I am going to have to review my code tonight when I get home.
Bob
Bob
ASKER
Thanks Bob. From my digging it appears that I need to inherit the RichTextBox control in a way to access the .rtf member, so that I may enter RTF code as above. Ive tried to do that to no avail, but I'm still working on it. Any information would be most helpful and I appreciate your time thus far.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That is exactly what I needed. BOB you are the MAN!
I owe you big time.
Thanks for all of your help and patience
I owe you big time.
Thanks for all of your help and patience
Bob