ComboBox DrawItem event handling for Font Combo Box - WinForms, VB.NET - vb.net

I am creating a combobox which shows fonts in the list, with every font item displayed in its own font style. The combobox loads without errors but the list that shows is all in just one font. I have set DrawMode = OwnerDrawVariable and IntegralHeight = false, but still no result. The DrawItem code that you can see here is from the MSDN website, with a few changes as per my requirement. Here is my code:
BindCOmboboxes() is called when the form loads.
Private Sub w_BindComboBoxes() (StyleControl is a User Control containing the combobox)
'Set Properties
Dim tFont As Font = Nothing
StyleControl.TS1Font.DrawMode = DrawMode.OwnerDrawVariable
For Each fntfam As FontFamily In FontFamily.Families
If fntfam.IsStyleAvailable(FontStyle.Regular) Then
tFont = New Font(fntfam, 12, FontStyle.Regular)
StyleControl.TS1Font.Items.Add(tFont.Name & ",Regular")
End If
If fntfam.IsStyleAvailable(FontStyle.Italic) Then
tFont = New Font(fntfam, 12, FontStyle.Italic)
StyleControl.TS1Font.Items.Add(tFont.Name & ",Italic")
End If
If fntfam.IsStyleAvailable(FontStyle.Bold) Then
tFont = New Font(fntfam, 12, FontStyle.Bold)
StyleControl.TS1Font.Items.Add(tFont.Name & ",Bold")
End If
Next
End Sub
DrawItem function for TS1Font combobox
Private Sub FontComboBoxDrawItems(sender As Object, e As DrawItemEventArgs)
Dim size As Integer = 12
Dim myFont As System.Drawing.Font
Dim family As FontFamily = new FontFamily("Arial", 12) <-- to avoid crash
Dim fntStyle As FontStyle = FontStyle.Regular <-- To avoid crash
Dim animalColor As System.Drawing.Color = Color.Black
Dim str As String = DirectCast(sender, ComboBox).Items(e.Index).ToString.Trim
Dim brk() As String = str.Split(",")
For Each fam As FontFamily In FontFamily.Families
If fam.Name = brk(0) Then family = fam
Next
Select Case brk(1)
Case "Regular"
fntStyle = FontStyle.Regular
Case "Bold"
fntStyle = FontStyle.Bold
Case "Italic"
fntStyle = FontStyle.Italic
End Select
' Draw the background of the item.
e.DrawBackground()
' Draw each string in the array, using a different size, color,
' and font for each item.
myFont = New Font(family, size, fntStyle)
e.Graphics.DrawString(DirectCast(sender, ComboBox).Items(e.Index).ToString, myFont, System.Drawing.Brushes.Black,
New PointF(e.Bounds.X, e.Bounds.Y))
' Draw the focus rectangle if the mouse hovers over an item.
e.DrawFocusRectangle()
End Sub
On debugging in the DrawItem function, the values in the statement e.Graphics.DrawString = shows proper font family, style and size values. So why doesn't it draw the items that way?
Result:

Related

VB.NET Multiple titles at same height in a windows forms chart

How do I put multiple titles into a chart at the same height?
No matter what parameters I choose I get results similar to this. My last try before asking here.
The screen shot shows the titles with a backcolor to prove what I expected.
Whenever I add 2 titles WinForms automatically puts them in different heights.
The 3. line is custom added to show you what I want to have as a result.
I could write a method but it should react to resize events and solving this with docking or alignments is preferred.
So right now the titles are inside the chartarea because I was fiddling around with DockingOffsets etc. I want them to be on top of the chartarea.
Here is my code:
Friend Function CreateTitle(ByVal titleName As TitleName, ByVal chart As Chart) As Title
Dim font As Font = Nothing
Dim foreColor As Color = Nothing
Dim backColor As Color = Nothing
Dim alignment As ContentAlignment = Nothing
Dim dockingOffset As Integer
Dim name As String = String.Empty
Dim titleText As String = String.Empty
Dim dockedToChartArea As String = String.Empty
Dim docking As Docking = Nothing
' Default settings
font = New Font("Arial", 12)
foreColor = color.blue
dockingOffset = 0
dockedToChartArea = chart.ChartAreas(0).Name
' Custom settings
Select Case titleName
Case ChartControls.TitleName.ComponentName
name = TITLENAME_COMP
titleText = chart.Name
alignment = ContentAlignment.BottomLeft
dockingOffset = 0
docking = DataVisualization.Charting.Docking.Top
backColor = Color.Coral
Case ChartControls.TitleName.TrafficLight
name = TITLENAME_TRAFFICLIGHT
titleText = "+34.6% / 1800 €"
alignment = ContentAlignment.TopRight
dockingOffset = 0
docking = DataVisualization.Charting.Docking.Top
backColor = Color.Beige
End Select
Dim title As New Title(titleText)
title.Name = name
title.Font = font
title.ForeColor = foreColor
title.BackColor = backColor
title.Alignment = alignment
title.Position = New ElementPosition()
title.Docking = docking
title.DockingOffset = dockingOffset
title.DockedToChartArea = dockedToChartArea
Return title
End Function
I call this method twice with different parameters and add them to my Titles collection.
I had to change my workaround because of requirements. It would have been very time consuming to make my workaround work for 1 .. n charts that differ in size depending on the amount of charts because then the labels would need a different size and position. So I had to find a better solution.
I have a Enum with 2 different title. The following properties are important.
Backcolor = Transparent
Only for one title choose a custom position. This turns the property "Position.Auto" to false. Take a look at my if clause at the end. So because the other property "Position.Auto" stays true because you don't manually change it you can simply assign a offset while bringing the other title manually to the same height.
.
`Friend Function CreateTitle(ByVal titleName As TitleName) As Title
Dim titleText As String = String.Empty
Dim alignment As ContentAlignment
' Custom settings
Select Case titleName
Case ChartControls.TitleName.Title1
titleText = "Title1"
alignment = ContentAlignment.MiddleLeft
Case ChartControls.TitleName.Title2
titleText = "Title2"
alignment = ContentAlignment.TopRight
End Select
Dim title As New Title()
title.Text = titleText
title.Font = New Font("Arial", 12)
title.BackColor = Color.Transparent
If titleName.Equals(CCT.ChartControls.TitleName.Title2) Then
title.Position = New ElementPosition(0, 3, 94, 5)
Else
title.DockingOffset = 0
End If
title.Alignment = alignment
Return title
End Function`
Looks like this: 2 titles on same height.

Can't centre Listview Item when using OwnerDrawn

When trying to custom draw my coloumn headers and listview items, I was getting jagged text (not anti-aliased) which looked crappy. I came across the following code snippet to render the text and display much more nicely - which works. However, I can't work out how to centre my text in the column. Currently, setting my flags to HorizontalCentre actually centres the text within the entire listview control.
Private Sub lsvOverdueCalls_DrawItem(sender As Object, e As DrawListViewItemEventArgs) Handles lsvOverdueCalls.DrawItem
If e.Item.Selected AndAlso e.Item.ListView.Focused Then
e.Item.BackColor = SystemColors.Highlight
e.Item.ForeColor = e.Item.ListView.BackColor
ElseIf e.Item.Selected AndAlso Not e.Item.ListView.Focused Then
e.Item.BackColor = SystemColors.Control
e.Item.ForeColor = e.Item.ListView.ForeColor
Else
e.Item.BackColor = e.Item.ListView.BackColor
e.Item.ForeColor = e.Item.ListView.ForeColor
End If
e.DrawBackground()
' Draw the header text.
Dim rec As New Rectangle(e.Bounds.X + 2, e.Bounds.Y + 2, e.Bounds.Width - 4, e.Bounds.Height - 4)
Dim flags As TextFormatFlags = TextFormatFlags.HorizontalCenter Or TextFormatFlags.EndEllipsis Or TextFormatFlags.ExpandTabs Or TextFormatFlags.SingleLine
TextRenderer.DrawText(e.Graphics, e.Item.Text, e.Item.ListView.Font, rec, e.Item.ForeColor, flags)
End Sub
My result is this:
I need the Call Number (26155) to sit centre of the Call ID Column.
e.Bounds is the entire width. To get the width of your column, try referencing the Width property of the ListView column.
If you gave your columns keys, reference them by key:
listView1.Columns("callID").Width
or index:
listView1.Columns(0).Width
Then your drawing rectangle would look something like this:
Dim colWidth As Integer = listView1.Columns("callID").Width
Dim rec As New Rectangle(e.Bounds.X, e.Bounds.Y, _
colWidth, e.Bounds.Height)

How do I properly apply padding to a group box control?

I have a class that inherits a panel which I am adding a group box to. This group box contains for now a couple text boxes. I would like to have the text boxes centered horizontally and vertically within the group box by using the AutoSize property of the group box and the Padding property of the group box. Here is my attempt:
Imports System.Drawing
Public Class pnlItemMstr_A_OSI
Inherits Panel
Public Sub New(ByRef ItemMstr_DS As DataSet, ByVal padding As Integer)
MyBase.New()
Dim drItemMstr As DataRow = ItemMstr_DS.Tables(0)(0)
Dim txtHeight As Integer = 26
' article numbers
Dim grpArtNum As New GroupBox
Dim txtARTC_NUM_DOM_C As New TextBox
Dim txtARTC_NUM_CAN_C As New TextBox
With txtARTC_NUM_DOM_C
.Text = drItemMstr("ARTC_NUM_DOM_C").ToString
.Size = New Size(200, txtHeight)
.Location = New Point(0, 0)
End With
With txtARTC_NUM_CAN_C
.Text = drItemMstr("ARTC_NUM_CAN_C").ToString
.Size = New Size(200, txtHeight)
.Location = New Point(0, txtHeight)
End With
With grpArtNum
grpArtNum.Text = "Article Number"
grpArtNum.Padding = New Padding(padding)
grpArtNum.Controls.Add(txtARTC_NUM_DOM_C)
grpArtNum.Controls.Add(txtARTC_NUM_CAN_C)
End With
Me.Controls.Add(grpArtNum)
End Sub
End Class
What I am ending up with is ugly and not what I would expect to happen, notice how the group box text is cut off:
It seems the padding is not being applied properly, but I am sure I am just doing something wrong.
The Padding property is used primarily for Dock Styled child controls, so try adding a dock filled panel into your GroupBox to contain those TextBoxes:
With grpArtNum
grpArtNum.Text = "Article Number"
grpArtNum.Padding = New Padding(padding)
Dim innerPanel As New Panel With {.Dock = DockStyle.Fill}
innerPanel.Controls.Add(txtARTC_NUM_DOM_C)
innerPanel.Controls.Add(txtARTC_NUM_CAN_C)
grpArtNum.Controls.Add(innerPanel)
End With

Width of drawn list box?

I've created a custom combobox that uses a custom instance of a listbox control as the dropdown menu.
In order to customize the selection highlight of the listbox, I had to change its 'DrawMode' property to 'OwnerDrawFixed' and added the following code:
Private Sub _listBox_DrawItem(sender As Object, e As DrawItemEventArgs)
If e.Index >= 0 Then
e.DrawBackground()
If (e.State And DrawItemState.Selected) = DrawItemState.Selected Then
Using br = New LinearGradientBrush(e.Bounds, ColorSelectionListbox, ColorSelectionListbox, 0)
e.Graphics.FillRectangle(br, e.Bounds)
End Using
End If
Using b As New SolidBrush(ColorTextListbox)
e.Graphics.DrawString(_listBox.GetItemText(_listBox.Items(e.Index)), e.Font, b, e.Bounds)
End Using
e.DrawFocusRectangle()
RaiseEvent DrawItem(Me, e)
End If
End Sub
But with this, the width that I set for it is ignored and becomes a fixed width of 15 or so pixels.
How can I set the width of the owner-drawn control? Currently I have it as a property:
Public Property DropDownWidth() As Integer
Get
Return _dropDownWidth
End Get
Set(value As Integer)
_dropDownWidth = value
_listBox.Width = value
Invalidate(True)
End Set
End Property
Below is the rest of the code that is relevant, but nevermind.. I fixed the issue by setting the Autosize property of _controlHost to False. I had it set to True in order to display all items within the list (without having to define a dropdown maximum) but for some reason it behaves differently when the DrawMode is set to OwnerDraw.
_listBox = New ListBox()
_listBox.IntegralHeight = True
_listBox.BorderStyle = BorderStyle.FixedSingle
_listBox.SelectionMode = SelectionMode.One
_listBox.BindingContext = New BindingContext()
_dropDownWidth = Me.Width
_listBox.Width = _dropDownWidth
_controlHost = New ToolStripControlHost(_listBox)
_controlHost.Padding = New Padding(0)
_controlHost.Margin = New Padding(0)
_controlHost.AutoSize = False 'Used to be variable property _dropDownAutoSize
_popupControl = New ToolStripDropDown()
_popupControl.Padding = New Padding(0)
_popupControl.Margin = New Padding(0)
_popupControl.AutoSize = True '
_popupControl.DropShadowEnabled = False
_popupControl.Items.Add(_controlHost)

How to change Tab Control Background Color (VB.NET)

how can I change the grey part into white color?
I want my tabcontrol filled with full white color.
So far what i did is like this:
Private Sub TabControl1_DrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs) Handles TabControl1.DrawItem
Dim g As Graphics = e.Graphics
Dim tp As TabPage = TabControl1.TabPages(e.Index)
Dim br As Brush
Dim sf As New StringFormat
Dim r As New RectangleF(e.Bounds.X, e.Bounds.Y + 2, e.Bounds.Width, e.Bounds.Height - 2)
sf.Alignment = StringAlignment.Center
Dim strTitle As String = tp.Text
'If the current index is the Selected Index, change the color
If TabControl1.SelectedIndex = e.Index Then
'this is the background color of the tabpage header
br = New SolidBrush(Color.White) ' chnge to your choice
g.FillRectangle(br, e.Bounds)
'this is the foreground color of the text in the tab header
br = New SolidBrush(Color.Black) ' change to your choice
g.DrawString(strTitle, TabControl1.Font, br, r, sf)
Else
'these are the colors for the unselected tab pages
br = New SolidBrush(Color.White) ' Change this to your preference
g.FillRectangle(br, e.Bounds)
br = New SolidBrush(Color.Black)
g.DrawString(strTitle, TabControl1.Font, br, r, sf)
End If
End Sub
and I also put this at PageLoad function:
TabControl1.DrawMode = TabDrawMode.OwnerDrawFixed
For Each tg As TabPage In TabControl1.TabPages
tg.BackColor = Color.White
Next
There is no property to do this. However it is possible by using something like this
http://dotnetrix.co.uk/tabcontrol.htm
All controls on this site are freely available under MIT license.
Spending fair time to research if someone find a solution; There could be some work around. But according to MSDN Ref.
TabControl.BackColor Property
NET Framework (current version) This API supports the product
infrastructure and is not intended to be used directly from your code.
This member is not meaningful for this control.
Namespace: System.Windows.Forms Assembly: System.Windows.Forms (in
System.Windows.Forms.dll)
As far as I understand, this is adjustable from user's windows setting. (Highlight Color) of TabControl, Forms and other controls; otherwise MS could simply turn this property on.
I make a trick to get around this, I put on the gray part a white label and I have the following result:
Since that color segment of the tabcontrol is unpaintable and cannot be controlled, you have to use a panel or label, etc. to cover up the background color where there is no tabpage header. I use a panel to do this.
This statement working correctly:
Dim PutBackColor As Boolean = False
Private Sub TabControl1_DrawItem(sender As System.Object, e As System.Windows.Forms.DrawItemEventArgs) Handles TabControl1.DrawItem
If Me.PutBackColor = False Then
e.Graphics.FillRectangle(New SolidBrush(<YourColor>), 0 , 0, e.Bounds.Width + 2, e.Bounds.Height + 2)
Me.PutBackColor = True
End If
e.Graphics.FillRectangle(New SolidBrush(<YourColor>), 0 , 0, e.Bounds.Width + 2, e.Bounds.Height + 2)
e.Graphics.DrawString(Me.TabControl1.TabPages(e.In dex).Text, e.Font, Brushes.White, e.Bounds.X + 5, e.Bounds.Y + 5)
If e.State = DrawItemState.Selected Then
Me.PutBackColor = False
End If
End Sub