Multi column combobox change width - vb.net

I have a vb.net combobox with three columns.
How can I make the e.bounds a wider? I want to set the dropdown of the combobox
wider than the actual combobox.
I used the following code :
Private Sub BlokKiesCMB_DrawItem(ByVal sender As
System.Object, ByVal e As
System.Windows.Forms.DrawItemEventArgs)
Handles BlokKiesCMB.DrawItem
' Draw the default background
e.DrawBackground()
' The ComboBox is bound to a DataTable,
' so the items are DataRowView objects.
Dim drv As DataRowView = CType(BlokKiesCMB.Items(e.Index), DataRowView)
' Retrieve the value of each column.
Dim blokno As String = drv("blokno").ToString()
Dim kultivar As String = drv("kultivar").ToString()
Dim klas As String = drv("klas").ToString()
' Get the bounds for the first column
Dim r1 As Rectangle = e.Bounds
r1.Width = r1.Width / 3
' Draw the text on the first column
Using sb As SolidBrush = New SolidBrush(e.ForeColor)
e.Graphics.DrawString(blokno, e.Font, sb, r1)
End Using
' Draw a line to isolate the columns
Using p As Pen = New Pen(Color.Black)
e.Graphics.DrawLine(p, r1.Right, 0, r1.Right, r1.Bottom)
End Using
' Get the bounds for the second column
Dim r2 As Rectangle = e.Bounds
r2.X = e.Bounds.Width / 3
r2.Width = r2.Width / 3
' Draw the text on the second column
Using sb As SolidBrush = New SolidBrush(e.ForeColor)
e.Graphics.DrawString(kultivar, e.Font, sb, r2)
End Using
' Draw a line to isolate the columns
Using p As Pen = New Pen(Color.Black)
e.Graphics.DrawLine(p, r2.Right, 0, r2.Right, r2.Bottom)
End Using
' Get the bounds for the third column
Dim r3 As Rectangle = e.Bounds
r3.X = r2.Width + r2.X
r3.Width = r3.Width / 3
' Draw the text on the third column
Using sb As SolidBrush = New SolidBrush(e.ForeColor)
e.Graphics.DrawString(klas, e.Font, sb, r3)
End Using
End Sub

e.Bounds does not give you the sides of ComboBox or its DropDown box. Bounds refers to the position of the ComboBox relative to its parent. Read this for further reference.
Now, WinForms ComboBox has a property called DropDownWidth which allows you to control the width of the DropDown wider than the actual ComboBox's width. This property, by default, is set as the same value as the ComboBox's width.
Here is the actual example, the size of the ComboBox is 121, by default the size of its DropDown box will be 121 too.
But if you change the DropDownWidth (says, to 200)
Me.ComboBox1.DropDownWidth = 200 'change this
This is what you are going to get
The ComboBox drop down box got wider.

Related

Create a Tiff Bitmap file from a DatagridView

I want to create a Tiff file from a Datagridview. I was able to get the Datagridview to a Tiff file, however I just want the Rows and Columns and nothing else.
Is this possible without using 3rd party Tool?
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DataGridView1.Rows.Add(New String() {"Value1", "Value2", "Value3"})
Dim height As Integer = DataGridView1.Height
DataGridView1.Height = DataGridView1.RowCount * DataGridView1.RowTemplate.Height
Dim bitmap As Bitmap = New Bitmap(Me.DataGridView1.Width - 1, Me.DataGridView1.Height - 1)
DataGridView1.DrawToBitmap(bitmap, New Rectangle(0, 0, Me.DataGridView1.Width - 1, Me.DataGridView1.Height - 1))
'Save the Bitmap to folder.
bitmap.Save("C:Development\DataGridView.Tiff")
End Sub
I dont want the Highlighted
There are a few things to consider:
The DataGridView Rows and Columns must be visible when the control is drawn to a Bitmap,
ScrollBars may be present,
The height of the Rows may be different, so we have to sum the height of all rows,
The same for the Columns, since each Column has it's own width,
CellFormatting may be in place, so we need to refresh the DataGridView before drawing it: rows that are not visible may not have been formatted yet,
There's a limit (32,767) in the Bitmap dimensions.
Call this method as follows, specifying whether you want to include the Row or Column Headers or exclude both, passing True/False as the ColumnHeaders and RowHeaders arguments.
The dgv argument is of course the DataGridView control instance that will be drawn:
' Prints the DataGridView including the Columns' Headers only
Dim dgvBitmap = DataGridViewToBitmap(DataGridView1, True, False)
Dim imagePath = Path.Combine(AppContext.BaseDirectory, $"{NameOf(DataGridView1)}.tiff")
dgvBitmap.Save(imagePath, ImageFormat.Tiff)
' Dispose of the Bitmap or set it as the PictureBox.Image, dispose of it later.
dgvBitmap.Dispose()
Private Function DataGridViewToBitmap(dgv As DataGridView, ColumnHeaders As Boolean, RowHeaders As Boolean) As Bitmap
dgv.ClearSelection()
Dim originalSize = dgv.Size
dgv.Height = dgv.Rows.OfType(Of DataGridViewRow).Sum(Function(r) r.Height) + dgv.ColumnHeadersHeight
dgv.Width = dgv.Columns.OfType(Of DataGridViewColumn).Sum(Function(c) c.Width) + dgv.RowHeadersWidth
dgv.Refresh()
Dim dgvPosition = New Point(If(RowHeaders, 0, dgv.RowHeadersWidth), If(ColumnHeaders, 0, dgv.ColumnHeadersHeight))
Dim dgvSize = New Size(dgv.Width, dgv.Height)
If dgvSize.Height > 32760 OrElse dgvSize.Width > 32760 Then Return Nothing
Dim rect As Rectangle = New Rectangle(Point.Empty, dgvSize)
Using bmp As Bitmap = New Bitmap(dgvSize.Width, dgvSize.Height)
dgv.DrawToBitmap(bmp, rect)
If (dgv.Width > originalSize.Width) AndAlso dgv.ScrollBars.HasFlag(ScrollBars.Vertical) Then
dgvSize.Width -= SystemInformation.VerticalScrollBarWidth
End If
If (dgv.Height > originalSize.Height) AndAlso dgv.ScrollBars.HasFlag(ScrollBars.Horizontal) Then
dgvSize.Height -= SystemInformation.HorizontalScrollBarHeight
End If
dgvSize = New Size(dgvSize.Width - dgvPosition.X, dgvSize.Height - dgvPosition.Y)
dgv.Size = originalSize
Return bmp.Clone(New Rectangle(dgvPosition, dgvSize), PixelFormat.Format32bppArgb)
End Using
End Function

Fitting runtime buttons inside a form

I have a number of buttons between 5-20 and it's variable each time the form loads based on the user settings. I am trying to fit all these buttons on my form no matter what the size of the form is. The buttons are generated during runtime. I would like the first button to be 20 points from the top bar (at any size) and the rest of the buttons simply to fit in the form. This is what I have now but I have to maximize the form to view them all and also while I'm expanding the form the space between the buttons decreases and they overlap with each other whereas they should keep a relative distance. Any ideas?
Dim iButtonWidth, iButtonHeight, iVerticalSpace As Integer
If UserButtons.Count > 0 Then
iButtonHeight = Me.Size.Height - (Me.Size.Height * 0.85)
iButtonWidth = Me.Size.Width - (Me.Size.Width * 0.5)
iVerticalSpace = iButtonHeight / 3
For Each btn In UserButtons
btn.Size = New System.Drawing.Size(iButtonWidth, iButtonHeight)
btn.Location = New Point(20, 20 + btn.TabIndex * iVerticalSpace * 3)
Next
End If
Here's a quick example using the TableLayoutPanel to play with:
Public Class Form1
Private UserButtons As New List(Of Button)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Static R As New Random
Dim NumButtons As Integer = R.Next(5, 21) ' "a number of buttons between 5-20 and it's variable each time"
UserButtons.Clear()
For i As Integer = 1 To NumButtons
Dim btn As New Button()
btn.Text = i.ToString("00")
btn.Dock = DockStyle.Fill ' Optional: See how you like it with this on vs. off
UserButtons.Add(btn)
Next
DisplayButtons()
End Sub
Private Sub DisplayButtons()
TableLayoutPanel1.SuspendLayout()
TableLayoutPanel1.Controls.Clear()
TableLayoutPanel1.ColumnStyles.Clear()
TableLayoutPanel1.ColumnCount = 5 ' Fixed Number of Columns
For i As Integer = 1 To TableLayoutPanel1.ColumnCount
TableLayoutPanel1.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 911)) ' the size doesn't matter here, as long as they are all the same
Next
' Variable Number of Rows:
Dim RowsRequired As Integer = ((UserButtons.Count - 1) \ TableLayoutPanel1.ColumnCount) + 1 ' Integer Division
TableLayoutPanel1.RowStyles.Clear()
TableLayoutPanel1.RowCount = RowsRequired
For i As Integer = 1 To TableLayoutPanel1.RowCount
TableLayoutPanel1.RowStyles.Add(New RowStyle(SizeType.Percent, 911)) ' the size doesn't matter here, as long as they are all the same
Next
TableLayoutPanel1.Controls.AddRange(UserButtons.ToArray)
TableLayoutPanel1.ResumeLayout()
End Sub
End Class
First of all what kind of container are the buttons in? You should be able to set the container's AutoScroll property to true - then when controls within it spill out of the visible bounds you will get a scroll bar.
Then also what you could do is draw each button in more of a table with a certain number next to each other before dropping down to the next line (instead of just 1 button on each line). If that is an option that works for you then you could get more buttons within the visible space.
I happen to have an example to do the same thing with picture boxes (and text boxes under each picture box). Hope this helps:
Dim point As New Point(0, 0)
'create 11 picture and text boxes-you can make this number the number your user selects.
Dim box(11) As PictureBox
Dim text(11) As TextBox
Dim i As UInt16
For i = 0 To 11 'or whatever your number is
box(i) = New PictureBox
box(i).Width = 250 'your button width
box(i).Height = 170 'your button height
box(i).BorderStyle = BorderStyle.FixedSingle
box(i).Location = point
layoutsPanel.Controls.Add(box(i)) 'my container is a panel
text(i) = New TextBox
text(i).Height = 50
text(i).Width = 250
point.Y += box(i).Height
text(i).Location = (point)
layoutsPanel.Controls.Add(text(i))
point.Y -= box(i).Height 'reset Y for next picture box
'Put 4 picture boxes in a row, then move down to next row
If i Mod 4 = 3 Then
point.X = 0
point.Y += box(i).Height + text(i).Height + 4
Else
point.X += box(i).Width + 4
End If
Next

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)

muti line text with first line underline in datagridviewTextBoxCell Vb.net

I'm able to add the mutiline text in datagridViewtextboxcell by using Environment.NewLine while inserting. but I would like to add underline for 1st line. so how could i achive this in vb.net
now I'm handling the paint method of DGV for showing date in 2 color for date format(as like in first column).
Please find the attached image,
in that second last column for email and cell number i want to draw underline.
Thanks.
I'm answering my own question.
Handle the DataGridView1_CellPainting and call this method for specific cell/column.firstly seperate the string and render it with TextRenderer class 2 times with new location.
I don't know is this correct way, but it works.
Private Sub CellText_Underline(color As Color, e As DataGridViewCellPaintingEventArgs)
Dim text As String = e.FormattedValue.ToString()
Dim nameParts As String() = text.Split(" ")
Dim topLeft As New Point(e.CellBounds.X, CInt(e.CellBounds.Y + (e.CellBounds.Height / 4)))
Dim arialBold As New Font("Arial", 11, FontStyle.Regular Xor FontStyle.Underline)
TextRenderer.DrawText(e.Graphics, nameParts(0), arialBold, topLeft, color)
Dim topLeft_1 As New Point(e.CellBounds.X, CInt(e.CellBounds.Y + (e.CellBounds.Height / 4) + 5))
Dim s As Size = TextRenderer.MeasureText(nameParts(0), arialBold)
Dim p As New Point(topLeft_1.X, topLeft_1.Y + 12)
Dim arialBold_1 As New Font("Arial", 11, FontStyle.Regular)
TextRenderer.DrawText(e.Graphics, nameParts(1), arialBold_1, p, SystemColors.WindowText)
End Sub
Thanks.

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