Display rect focus on subitems / cells in Listview - vb.net

Like the title above, I am trying to display the focus box on the subitem / cell that is clicked.
To get the subitem / cell that is clicked I use the following code:
Private Sub LV_MouseClick(sender As Object, e As MouseEventArgs) Handles LV.MouseClick
Info = LV.HitTest(e.Location)
ClickedColumnLV = Info.Item.SubItems.IndexOf(Info.SubItem)
ClickedRowLV = Info.Item.Index
If e.Button = MouseButtons.Right Then
If LV.FocusedItem.Bounds.Contains(e.Location) Then
CMenu.Show(Cursor.Position)
End If
End If
End Sub
At this point i have Row Index (ClickedRowLV) and Column Index (ClickedColumnLV)
Now I'am trying show focus on that clicked subitem/cell.
How can I do that?
EDIT :
Just to make sure that I didn't click the wrong item. So I want to have a focus rect or a sign if the sub-item is clicked.
Row must be full row select but at subitem /cell there is focus rect inside or outide. For example, please see the picture :

Not quite sure whether you mean something like:
If that is true, then you can handle the MouseDown event of the ListView control as follows:
Private Sub LV_MouseDown(sender As Object, e As MouseEventArgs) Handles LV.MouseDown
Dim selColor = SystemColors.Highlight
Dim item = LV.Items.Cast(Of ListViewItem).
Where(Function(x) x.BackColor.Equals(selColor) OrElse
x.SubItems.Cast(Of ListViewItem.ListViewSubItem).
Any(Function(y) y.BackColor.Equals(selColor))).FirstOrDefault
If item IsNot Nothing Then
item.BackColor = SystemColors.Window
item.ForeColor = SystemColors.WindowText
For Each subItem In item.SubItems.Cast(Of ListViewItem.ListViewSubItem)
subItem.BackColor = SystemColors.Window
subItem.ForeColor = SystemColors.WindowText
Next
End If
Dim ht = LV.HitTest(e.Location)
If ht.SubItem IsNot Nothing Then
ht.Item.UseItemStyleForSubItems = False
ht.SubItem.BackColor = selColor
ht.SubItem.ForeColor = SystemColors.Window
End If
End Sub
Of course this won't work if the FullRowSelect property is enabled.
Edit: Custom ListView
Following up on your comment and update, I don't know any easy way to achieve that. I think you need to create a custom ListView and override the relevant events as follows:
Imports System.Windows.Forms
Imports System.Drawing
Imports System.ComponentModel
<DesignerCategory("Code")>
Public Class ListViewEx
Inherits ListView
Private ht As ListViewHitTestInfo
Sub New()
MyBase.New
DoubleBuffered = True
OwnerDraw = True
FullRowSelect = True
End Sub
Public Property DrawFocusRectangle As Boolean = True
Protected Overrides Sub OnDrawColumnHeader(e As DrawListViewColumnHeaderEventArgs)
e.DrawDefault = True
End Sub
Protected Overrides Sub OnDrawItem(e As DrawListViewItemEventArgs)
If View = View.Details Then Return
If e.Item.Selected Then
e.Graphics.FillRectangle(Brushes.LightSteelBlue, e.Bounds)
e.DrawFocusRectangle()
Else
e.DrawBackground()
End If
e.DrawText()
End Sub
Protected Overrides Sub OnDrawSubItem(e As DrawListViewSubItemEventArgs)
Using sf As New StringFormat With {
.Alignment = StringAlignment.Near,
.LineAlignment = StringAlignment.Center,
.Trimming = StringTrimming.EllipsisCharacter,
.FormatFlags = StringFormatFlags.NoWrap
},
br = New SolidBrush(e.SubItem.ForeColor)
Select Case e.Header.TextAlign
Case HorizontalAlignment.Center
sf.Alignment = StringAlignment.Center
Case HorizontalAlignment.Right
sf.Alignment = StringAlignment.Far
End Select
If e.Item.Selected Then
If e.ColumnIndex = 0 OrElse FullRowSelect Then
e.Graphics.FillRectangle(Brushes.LightSteelBlue, e.Bounds)
End If
Else
e.DrawBackground()
End If
e.Graphics.DrawString(e.SubItem.Text, e.SubItem.Font, br, e.Bounds, sf)
End Using
'Here you go...
If DrawFocusRectangle AndAlso ht IsNot Nothing AndAlso
e.Item.Focused AndAlso e.SubItem Is ht.SubItem Then
Using pn As New Pen(Color.Orange, 2)
Dim r As New Rectangle(e.Bounds.X,
e.Bounds.Y,
e.Header.Width - 1,
e.Bounds.Height - 1)
e.Graphics.DrawRectangle(pn, r)
'or just draw focus rectangle ...
'ControlPaint.DrawFocusRectangle(e.Graphics, r)
End Using
End If
End Sub
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
MyBase.OnMouseDown(e)
ht = HitTest(e.Location)
Invalidate()
End Sub
Protected Overrides Sub OnColumnWidthChanged(e As ColumnWidthChangedEventArgs)
MyBase.OnColumnWidthChanged(e)
Invalidate()
End Sub
End Class
Related
How to change default selection color of a ListView?
WinForms: Changing ForeColor of Selected item in ListView
ListView: MultiSelect items with mouse drag

Related

Custom treeview VB.net

I'm looking to create a custom treeview control in VB.net, what I need to do is have a standard treeview control displaying the system file strucure for example, but with an extra icon on the right on the folder/file name that only appears on hover over of the node. So, for instance, if I hover over the folder Sup2 as shown in the pic, then the orange icon appears
I've done some research and from what I can see, I have to override the onpaint event to make this happen but I'm not sure exactly how to do this. I also need to add an onclick event to that new orange icon.
This is not professional but is worth giving a try..
I created a class that inherited from a Treeview control and overrode the constructor - changing the default width and height, setting the DrawMode to TreeViewDrawMode.OwnerDrawText.
Next, I handled the TreeView.DrawNode event, using a PictureBox to display the Image and changing its location based on the currently highlighted item.
I also handled the Click event of the PictureBox.Under that event, You can do whatever you want with the highlighted node.
I used images from My.Resources for ImageList.Images(0) and PictureBox.Image
Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim trv As New MyTreeView
trv.Nodes.Add("Suppliers")
trv.Nodes(0).Nodes.Add("Sup 1")
trv.Nodes(0).Nodes.Add("Sup 2")
trv.Nodes(0).Nodes.Add("Sup 3")
trv.Nodes(0).Nodes.Add("Sup 4")
trv.Nodes(0).Nodes.Add("Sup 5")
Controls.Add(trv)
End Sub
End Class
'Class Starts Here
Public Class MyTreeView
Inherits TreeView
WithEvents myImage As PictureBox
Dim activeItem As TreeNode 'Variable to store active TreeNode
Public Sub New()
MyBase.New() 'Call the base class constructor
'And set some values
Height = 300
Width = 300
Location = New Point(50, 50)
DrawMode = TreeViewDrawMode.OwnerDrawText 'Very neccesary
AddHandler DrawNode, AddressOf MyTreeViewDrawNode
'Add event handlers
AddHandler AfterCollapse, AddressOf MyTreeViewCollapsed
'Set HotTracking event to true to allow for MouseHover
HotTracking = True
ImageList = new ImageList
ImageList.Images.Add(My.Resources.FolderImage)
ImageIndex = 0
Font = New Font(Font.FontFamily, 10)
'Initialize picturebox
myImage = New PictureBox() With
{
.Image = My.Resources.editPencilImage,
.SizeMode = PictureBoxSizeMode.Zoom,
.Size = New Size(10, 10),
.Visible = False
}
Controls.Add(myImage)
End Sub
Private Sub MyTreeViewCollapsed(sender As Object, e As TreeViewEventArgs)
myImage.Visible = False
End Sub
Sub ImageClicked(sender As Object, e As EventArgs) Handles myImage.Click
If (Not activeItem Is Nothing) Then
MessageBox.Show("Clicked Item - " & activeItem.Text)
End If
End Sub
Private Sub MyTreeViewDrawNode(sender As Object, e As DrawTreeNodeEventArgs)
e.DrawDefault = True
If (e.State = TreeNodeStates.Hot) Then
myImage.Visible = True
activeItem = e.Node
Dim tmpSize = TextRenderer.MeasureText(e.Node.Text, Font)
myImage.Location = New Point(e.Node.Bounds.Location.X + tmpSize.Width, e.Node.Bounds.Location.Y)
End If
End Sub
End Class
I think the following example will give you some hints and tips.
Option Explicit On
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Drawing.Text
Imports System.Runtime.InteropServices
Public Class TreeViewEx
Inherits TreeView
#Region "API"
Private Const TVM_SETEXTENDEDSTYLE As Integer = &H1100 + 44
Private Const TVS_EX_DOUBLEBUFFER As Integer = &H4
<DllImport("user32.dll")>
Private Shared Function SendMessage(ByVal hWnd As IntPtr,
ByVal msg As Integer,
ByVal wp As IntPtr,
ByVal lp As IntPtr) As IntPtr
End Function
#End Region
#Region "Private Fields"
Private ReadOnly RightImage As Bitmap
Private ReadOnly NSF As StringFormat
Private HoverNode As TreeNode
Private RightImageRect As Rectangle
#End Region
#Region "Constructors"
Sub New()
DrawMode = TreeViewDrawMode.OwnerDrawText
RightImage = New Bitmap(My.Resources.Modify)
NSF = New StringFormat With {
.Alignment = StringAlignment.Near,
.LineAlignment = StringAlignment.Center,
.Trimming = StringTrimming.EllipsisCharacter,
.FormatFlags = StringFormatFlags.NoWrap
}
End Sub
#End Region
#Region "Paint"
Protected Overrides Sub OnDrawNode(e As DrawTreeNodeEventArgs)
MyBase.OnDrawNode(e)
If e.Node Is Nothing Then Return
Dim rect As Rectangle = e.Bounds : rect.Inflate(0, 1)
If Not ClientRectangle.IntersectsWith(rect) Then
Return
End If
Dim G As Graphics = e.Graphics
G.SmoothingMode = SmoothingMode.HighQuality
G.TextRenderingHint = TextRenderingHint.ClearTypeGridFit
'Option1: If you want to draw different background color for the selected node.
'If (e.State And TreeNodeStates.Selected) = TreeNodeStates.Selected Then
' Using br As New SolidBrush(Color.LightSteelBlue) '<- suit yourself!
' G.FillRectangle(br, rect)
' End Using
'Else
' Using br As New SolidBrush(If(e.Node.BackColor.Equals(Color.Empty), BackColor, e.Node.BackColor))
' G.FillRectangle(br, rect)
' End Using
'End If
'Option2: If you don't want Option1.
Using br As New SolidBrush(If(e.Node.BackColor.Equals(Color.Empty), BackColor, e.Node.BackColor))
G.FillRectangle(br, rect)
End Using
Using br As New SolidBrush(If(e.Node.ForeColor.Equals(Color.Empty), ForeColor, e.Node.ForeColor))
G.DrawString(e.Node.Text, If(e.Node.NodeFont, Font), br, rect, NSF)
End Using
If ReferenceEquals(e.Node, HoverNode) Then
RightImageRect = New Rectangle(rect.Right + 5,
rect.Y + ((rect.Height - RightImage.Height) / 2),
rect.Height - 4, rect.Height - 4)
G.DrawImage(RightImage,
RightImageRect,
New Rectangle(0, 0, RightImage.Width, RightImage.Height),
GraphicsUnit.Pixel)
End If
End Sub
#End Region
#Region "Other Events"
'You need this to reduce the flickering.
Protected Overrides Sub OnHandleCreated(ByVal e As EventArgs)
SendMessage(
Handle,
TVM_SETEXTENDEDSTYLE,
IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER),
IntPtr.op_Explicit(TVS_EX_DOUBLEBUFFER)
)
MyBase.OnHandleCreated(e)
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
Dim node = GetNodeAt(e.Location)
If node IsNot Nothing Then
'Avoid unnecessary Invalidate() calls.
If Not ReferenceEquals(node, HoverNode) Then
HoverNode = node
Invalidate()
End If
Else
'Avoid unnecessary Invalidate() calls.
If HoverNode IsNot Nothing Then
HoverNode = Nothing
Invalidate()
End If
End If
End Sub
Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
MyBase.OnMouseDown(e)
If e.Button = MouseButtons.Left AndAlso
RightImageRect.Contains(e.Location) Then
'Notify the container to do something.
OnEditButtonClicked()
End If
End Sub
Protected Overrides Sub OnMouseLeave(e As EventArgs)
MyBase.OnMouseLeave(e)
Invalidate()
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
If disposing Then
RightImage.Dispose()
NSF.Dispose()
End If
End Sub
#End Region
#Region "Custom Events"
Public Class EditButtonClickArgs
Inherits EventArgs
Public Property Node As TreeNode
Sub New(node As TreeNode)
Me.Node = node
End Sub
End Class
''' <summary>
''' Raised when the right image is clicked.
''' </summary>
Public Event EditButtonClicked As EventHandler(Of EditButtonClickArgs)
''' <summary>
''' Raises the <see cref="EditButtonClicked"/> events.
''' </summary>
Protected Overridable Sub OnEditButtonClicked()
RaiseEvent EditButtonClicked(Me, New EditButtonClickArgs(HoverNode))
End Sub
#End Region
End Class
In the Form that contains the new TreeViewEx control, you can handle the EditButtonClicked to do the necessary:
Public Class Form1
Inherits Form
Private Sub TreeViewEx1_EditButtonClicked(sender As Object, e As TreeViewEx.EditButtonClickArgs) Handles TreeViewEx1.EditButtonClicked
'Do something with the e.Node
End Sub
End Class
And here's a quick demo:
Good luck.

Why is this event handler method being repeatedly called?

The DataGridViewComboBoxColumn control can be difficult to work with. I've been fighting various permutations of this code for two long days, so I've decided to throw in the towel and seek some assistance.
The latest incarnation of weirdness is a ComboBox event handler that fires an increasing number of times for a single user action. Oddly, the rate of increase is an exact doubling of the count just preceding (i.e. 1, 2, 4, 8, 16, 32, 64 etc.)
To start things off, I'll explain what I'm trying to accomplish and also clarify some terminology.
I have a Dictionary(Of Integer, String). In my domain rules, I'm calling its Key property Channel and its Value property Label. I'm mapping each KeyValuePair to a third String value called Target. The Dictionary(Of Integer, String) items are fixed—they exist as a visual aid for the user, so he can easily select the Target from a List(Of String).
I've settled on a DataGridView control to provide this functionality. I'm using three columns, like so:
Note that already-mapped Target list items are displayed in a nearly-invisible color, so as to discourage the user from trying to use them again. (This is where the event handler problem comes in—when an already-mapped Target is selected for mapping to a different Label.)
I'm including my full code base below, but for a quick look here's the event handler that repeats:
Private Sub ComboBox_SelectionChangeCommitted(Sender As ComboBox, e As EventArgs)
' '
' Look for other labels that have already been mapped to this target '
' '
If Me.OtherTargetCells.Any(Function(Cell) Cell.FormattedValue = Sender.Text) Then
If Me.IsInteractiveChange Then
MsgBox("Target [] is already mapped to Label []. If you want to map Target [] to Label [], you must first set Label [] to [Not mapped].", MsgBoxStyle.Exclamation, Me.DataGridView.FindForm.Text)
Me.IsInteractiveChange = False
Sender.SelectedIndex = 0
Me.IsInteractiveChange = True
End If
End If
End Sub
And here's how I'm wiring it all up:
Public Sub New()
Task.Run(Sub()
Dim oHandler As DataGridViewEditingControlShowingEventHandler
While Me.DataGridView Is Nothing
End While
oHandler = New DataGridViewEditingControlShowingEventHandler(AddressOf DataGridView_EditingControlShowing)
RemoveHandler Me.DataGridView.EditingControlShowing, oHandler
AddHandler Me.DataGridView.EditingControlShowing, oHandler
End Sub)
End Sub
Private Sub DataGridView_EditingControlShowing(Sender As DataGridView, e As DataGridViewEditingControlShowingEventArgs)
Dim oComboBox As ComboBox
If TypeOf e.Control Is ComboBox Then
oComboBox = e.Control
oComboBox.DrawMode = DrawMode.OwnerDrawFixed
RemoveHandler oComboBox.DrawItem, New DrawItemEventHandler(AddressOf ComboBox_DrawItem)
AddHandler oComboBox.DrawItem, New DrawItemEventHandler(AddressOf ComboBox_DrawItem)
RemoveHandler oComboBox.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
AddHandler oComboBox.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
End If
End Sub
The repeat count multiplies when I select an already-mapped Target from a different list than previously (e.g. selecting twice from SCC doesn't increase the count, but selecting from SCC and then Scale does.)
I've tried many, many, many possible solutions for this—too many to list here and most of which I just don't remember—but none with any success.
What can I do to constrain the handler to fire only once for each selection change?
Mapping.TargetsColumn.vb
Namespace Mapping
Public Class TargetsColumn
Inherits DataGridViewComboBoxColumn
Public Sub New()
Task.Run(Sub()
Dim oHandler As DataGridViewEditingControlShowingEventHandler
While Me.DataGridView Is Nothing
End While
oHandler = New DataGridViewEditingControlShowingEventHandler(AddressOf DataGridView_EditingControlShowing)
RemoveHandler Me.DataGridView.EditingControlShowing, oHandler
AddHandler Me.DataGridView.EditingControlShowing, oHandler
End Sub)
End Sub
Private Sub DataGridView_EditingControlShowing(Sender As DataGridView, e As DataGridViewEditingControlShowingEventArgs)
Dim oComboBox As ComboBox
If TypeOf e.Control Is ComboBox Then
oComboBox = e.Control
oComboBox.DrawMode = DrawMode.OwnerDrawFixed
RemoveHandler oComboBox.DrawItem, New DrawItemEventHandler(AddressOf ComboBox_DrawItem)
AddHandler oComboBox.DrawItem, New DrawItemEventHandler(AddressOf ComboBox_DrawItem)
RemoveHandler oComboBox.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
AddHandler oComboBox.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
End If
End Sub
Private Sub ComboBox_DrawItem(Sender As ComboBox, e As DrawItemEventArgs)
Dim sThisTarget As String
Dim oForeColor As Color
Dim _
iSeparatorBottom,
iSeparatorRight,
iSeparatorLeft As Integer
Dim _
oSeparatorStart,
oSeparatorStop As Point
sThisTarget = DirectCast(Me.Items(e.Index), Target).Value
iSeparatorBottom = e.Bounds.Bottom - 2
iSeparatorRight = e.Bounds.Right
iSeparatorLeft = e.Bounds.Left
e.DrawBackground()
If e.Index = 0 Then
oSeparatorStart = New Point(iSeparatorLeft, iSeparatorBottom)
oSeparatorStop = New Point(iSeparatorRight, iSeparatorBottom)
oForeColor = SystemColors.HotTrack
e.Graphics.FillRectangle(SystemBrushes.Control, e.Bounds)
e.Graphics.DrawLine(SystemPens.ControlDark, oSeparatorStart, oSeparatorStop)
Else
If Me.OtherTargets.Contains(sThisTarget) Then
oForeColor = SystemColors.ControlLight
Else
oForeColor = e.ForeColor
End If
End If
Using oBrush As New SolidBrush(oForeColor)
e.Graphics.DrawString(sThisTarget, e.Font, oBrush, e.Bounds)
End Using
If e.State.HasFlag(DrawItemState.Focus) Then e.DrawFocusRectangle()
Me.DataGridView.FindForm.Text = sThisTarget
End Sub
Private Sub ComboBox_SelectionChangeCommitted(Sender As ComboBox, e As EventArgs)
' '
' Look for other labels that have already been mapped to this target '
' '
If Me.OtherTargetCells.Any(Function(Cell) Cell.FormattedValue = Sender.Text) Then
If Me.IsInteractiveChange Then
MsgBox("Target [] is already mapped to Label []. If you want to map Target [] to Label [], you must first set Label [] to [Not mapped].", MsgBoxStyle.Exclamation, Me.DataGridView.FindForm.Text)
Me.IsInteractiveChange = False
Sender.SelectedIndex = 0
Me.IsInteractiveChange = True
End If
End If
End Sub
Private ReadOnly Property OtherTargets As List(Of String)
Get
Return Me.OtherTargetCells.Select(Function(Cell) DirectCast(Cell.FormattedValue, String)).ToList
End Get
End Property
Private ReadOnly Property CurrentTargetCell As DataGridViewCell
Get
Return Me.AllTargetCells(Me.DataGridView.CurrentRow.Index)
End Get
End Property
Private ReadOnly Property AllTargetCells As List(Of DataGridViewCell)
Get
Dim oAllCells As IEnumerable(Of DataGridViewCell)
Dim oRows As IEnumerable(Of DataGridViewRow)
oRows = Me.DataGridView.Rows.Cast(Of DataGridViewRow)
oAllCells = oRows.SelectMany(Function(Row) Row.Cells.Cast(Of DataGridViewCell))
Return oAllCells.Where(Function(Cell) TypeOf Cell Is DataGridViewComboBoxCell).ToList
End Get
End Property
Private ReadOnly Property OtherTargetCells As List(Of DataGridViewCell)
Get
Return Me.AllTargetCells.Where(Function(Cell) Cell.RowIndex <> Me.RowIndex).ToList
End Get
End Property
Private ReadOnly Property RowIndex As Integer
Get
Return Me.DataGridView.CurrentRow.Index
End Get
End Property
Private IsInteractiveChange As Boolean = True
Private ReadOnly ComboBoxes As New Dictionary(Of Integer, ComboBox)
End Class
End Namespace
Form1.vb
Public Class Form1
Inherits Form
Public Sub New()
Dim oColTargets As Mapping.TargetsColumn
Dim oTargets As IEnumerable(Of String)
Dim oQuery As Func(Of Target, Boolean)
Dim sChannel As String
Dim oTarget As Target
Dim oMaps As Dictionary(Of Integer, String)
Dim oMap As Map
Dim _
oColChannels,
oColLabels As DataGridViewTextBoxColumn
Me.InitializeComponent()
Me.Targets.Add(New Target("Not mapped"))
sChannel = String.Empty
oQuery = Function(Target) Target.Value = sChannel
'oTargets = Reader.Client.Create.Call(Function(Service As Reader.IService) Service.GetChannelTargets)'
oTargets = New List(Of String) From {"Scale", "SCC", "CO", "O2"}
oTargets.ToList.ForEach(Sub(Target)
Me.Targets.Add(New Target(Target))
End Sub)
'oMaps = Reader.Client.Create.Call(Function(Service As Reader.IService) Service.GetChannelMaps)'
oMaps = New Dictionary(Of Integer, String) From {{3, "Test"}, {7, "SCC"}, {8, "Scale"}, {9, "CO"}, {10, "O2"}}
oMaps.ToList.ForEach(Sub(Map)
sChannel = Map.Value
If Me.Targets.Any(oQuery) Then
oTarget = Me.Targets.Single(oQuery)
Else
oTarget = Me.Targets.First
End If
oMap = New Map With {
.Channel = Map.Key,
.Label = Map.Value,
.Target = oTarget
}
Me.Maps.Add(oMap)
End Sub)
oColChannels = New DataGridViewTextBoxColumn With {
.DataPropertyName = NameOf(Map.Channel),
.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader,
.HeaderText = NameOf(Map.Channel),
.ReadOnly = True,
.Name = NameOf(oColChannels)
}
oColLabels = New DataGridViewTextBoxColumn With {
.DataPropertyName = NameOf(Map.Label),
.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader,
.HeaderText = NameOf(Map.Label),
.ReadOnly = True,
.Name = NameOf(oColLabels)
}
oColTargets = New Mapping.TargetsColumn With {
.DataPropertyName = NameOf(Map.Target),
.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
.DisplayMember = NameOf(Target.Value),
.ValueMember = NameOf(Target.Self),
.HeaderText = NameOf(Map.Target),
.DataSource = Me.Targets,
.Name = NameOf(oColTargets)
}
dgvMapping.AutoGenerateColumns = False
dgvMapping.Columns.AddRange({oColChannels, oColLabels, oColTargets})
For Each oColumn As DataGridViewColumn In dgvMapping.Columns
oColumn.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter
If oColumn.Index = 0 Then
oColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter
End If
Next
dgvMapping.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize
dgvMapping.DataSource = New BindingList(Of Map)(Me.Maps)
If dgvMapping.RowCount = 0 Then
dgvMapping.Height = 150
Else
dgvMapping.Height = ((dgvMapping.RowCount + 0) * dgvMapping.Rows(0).Height) + dgvMapping.ColumnHeadersHeight
End If
End Sub
Private Sub Form1_FormClosing(Sender As Form1, e As FormClosingEventArgs) Handles Me.FormClosing
Dim oPolicy As Target = Me.Maps.First.Target
Dim sName As String = Me.Maps.First.Channel
End Sub
Private Sub _dgvMapping_DataError(Sender As DataGridView, e As DataGridViewDataErrorEventArgs) Handles dgvMapping.DataError
MsgBox(e.Exception.Message, MsgBoxStyle.Critical, Me.Text)
End Sub
Private Targets As New BindingList(Of Target)
Private Maps As New List(Of Map)
End Class
Public Class Map
Public Property Channel As Integer
Public Property Label As String
Public Property Target As Target
End Class
Public Class Target
Public Sub New(Target As String)
Me.Value = Target
End Sub
Public ReadOnly Property Self As Target
Get
Return Me
End Get
End Property
Public ReadOnly Property Value As String
End Class
Form1.Designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class Form1
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.'
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer'
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer'
'It can be modified using the Windows Form Designer.'
'Do not modify it using the code editor.'
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Me.dgvMapping = New System.Windows.Forms.DataGridView()
CType(Me.dgvMapping, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
' '
'dgvMapping'
' '
Me.dgvMapping.AllowUserToAddRows = False
Me.dgvMapping.AllowUserToDeleteRows = False
Me.dgvMapping.AllowUserToOrderColumns = True
Me.dgvMapping.AllowUserToResizeColumns = False
Me.dgvMapping.AllowUserToResizeRows = False
Me.dgvMapping.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dgvMapping.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter
Me.dgvMapping.Location = New System.Drawing.Point(12, 12)
Me.dgvMapping.Name = "dgvMapping"
Me.dgvMapping.RowHeadersVisible = False
Me.dgvMapping.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect
Me.dgvMapping.Size = New System.Drawing.Size(250, 150)
Me.dgvMapping.TabIndex = 0
' '
'Form1'
' '
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.dgvMapping)
Me.Font = New System.Drawing.Font("Segoe UI", 8.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
Me.Name = "Form1"
Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
Me.Text = "Form1"
CType(Me.dgvMapping, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
End Sub
Friend WithEvents dgvMapping As DataGridView
End Class
Fixed.
I was instantiating a new event handler object for each AddHandler/RemoveHandler call.
When I removed the instantiations and used simple expressions instead, the ComboBoxes started behaving correctly.
Public Sub New()
Task.Run(Sub()
While Me.DataGridView Is Nothing
End While
RemoveHandler Me.DataGridView.EditingControlShowing, AddressOf DataGridView_EditingControlShowing
AddHandler Me.DataGridView.EditingControlShowing, AddressOf DataGridView_EditingControlShowing
End Sub)
End Sub
Private Sub DataGridView_EditingControlShowing(Sender As Object, e As DataGridViewEditingControlShowingEventArgs)
Dim oComboBox As ComboBox
If TypeOf e.Control Is ComboBox Then
oComboBox = e.Control
oComboBox.DrawMode = DrawMode.OwnerDrawFixed
RemoveHandler oComboBox.DrawItem, AddressOf ComboBox_DrawItem
AddHandler oComboBox.DrawItem, AddressOf ComboBox_DrawItem
RemoveHandler oComboBox.SelectionChangeCommitted, AddressOf ComboBox_SelectionChangeCommitted
AddHandler oComboBox.SelectionChangeCommitted, AddressOf ComboBox_SelectionChangeCommitted
End If
End Sub
I had to relax the Sender parameter types to Object in the event handler methods, but that didn't carry any serious consequence.
Private Sub DataGridView_EditingControlShowing(Sender As Object, e As DataGridViewEditingControlShowingEventArgs)
End Sub
Private Sub ComboBox_DrawItem(Sender As Object, e As DrawItemEventArgs)
End Sub
Private Sub ComboBox_SelectionChangeCommitted(Sender As Object, e As EventArgs)
End Sub
For what it's worth: I generally prefer to constrain the Sender parameter to the calling type, for more efficient coding, but that wasn't possible in this case. Nevertheless, the only impact was the need to cast the Sender in one place in one method body:
Dim oQuery = Function(Cell) Cell.FormattedValue = DirectCast(Sender, ComboBox).Text
It works as expected now.

Scrolling a Picturebox inside a Panel with a static label over

I have a PictureBox inside a Panel, to get automatic scrollbars when the picture is big, a Label with the photo title.
If I place the Label over the PictureBox, the "transparent" backcolor shows correctly but the Label remains at the top of the PictureBox and gets out of the screen if I scroll up-down or side-side the Panel's scrollbar!
Instead, if I put the Label outside the Panel (over the Form), the Label remains static on top of the screen, as I want, but the transparent backcolor doesn't show correctly becomes opaque.
Then if I set the Label's Parent property to the PictureBox, the transparent backcolor works fine again, but the static position of the Label is not respected anymore and joins PictureBox again!
How can I get a static Label with transparent backcolor over a PictureBox when using the scrollbars of the Panel?
I've tested the Overlay Form. It seems to work pretty well in your context.
Source Code in PasteBin
Uploaded the modified Project in OneDrive
(I don't have FW 4.5.2, tested with FW 4.5.1 and FW 4.7.1)
An Overlay can be an interesting feature, but, as I already said, this can also be done with TextRender.DrawText() or Graphics.DrawString(), backed by the simple math needed to offset the painted text when the picture container is scrolled.
In your Project, I've eliminated Label1 and all references to it.
Then, I've set this class field:
Private OverlayShown As Boolean = False
In frmPho_Load()
Overlay.Size = New Size(200, 50)
Overlay.OverlayPosition = Overlay.Alignment.Center
Overlay.Reposition(Me.Location, Me.Size)
OverlayShown = True
Overlay.Visible = False
Overlay.Show(Me)
In frmPho_Deactivate():
If OverlayShown = False Then
antip.Width = Me.Width
antip.Height = Me.Height
antip.Visible = True
End If
OverlayShown = False
These are all the changes made to the hosting Form (Form4), the form that uses the Overlay.
Public Class frmPho
Private Overlay As New OverlayForm
Private Sub frmPho_Load(sender As Object, e As EventArgs) Handles Me.Load
Overlay.Size = New Size(200, 50)
Overlay.OverlayPosition = Overlay.Alignment.Center
Overlay.Reposition(Me.Location, Me.Size)
OverlayShown = True
Overlay.Visible = False
Overlay.Show(Me)
'(...)
Overlay.Text = IO.Path.GetFileNameWithoutExtension(_ImageFileNames(_CurrentImage))
End Sub
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
If CheckBox1.CheckState = False Then
Overlay.Visible = False
Else
OverlayShown = True
Overlay.Visible = True
End If
End Sub
Private Sub ShowPrevImage()
'(...)
OverlayShown = True
Overlay.Text = IO.Path.GetFileNameWithoutExtension(_ImageFileNames(_CurrentImage))
End Sub
Private Sub ShowNextImage()
'(...)
OverlayShown = True
Overlay.Text = IO.Path.GetFileNameWithoutExtension(_ImageFileNames(_CurrentImage))
End Sub
Private Sub frmPho_Deactivate(sender As Object, e As EventArgs) Handles Me.Deactivate
If OverlayShown = False Then
antip.Width = Me.Width
antip.Height = Me.Height
antip.Visible = True
End If
OverlayShown = False
End Sub
Private Sub frmPho_Move(sender As Object, e As EventArgs) Handles Me.Move
Overlay.Reposition(Me.Location, Me.Size)
End Sub
Private Sub frmPho_Resize(sender As Object, e As EventArgs) Handles Me.Resize
Overlay.Reposition(Me.Location, Me.Size)
End Sub
Private Sub frmPho_Shown(sender As Object, e As EventArgs) Handles Me.Shown
ShowOverlay(300)
End Sub
Private Async Sub ShowOverlay(Delay As Integer)
Await Task.Delay(Delay)
Overlay.Visible = True
Me.Focus()
End Sub
And this is the complete OverlayForm:
All Borders/Control Boxes to None (It's a borderless Form)
.StartPosition = Manual
.TransparncyKey = WhiteSmoke <= Depends on the font color (mod. when needed)
.BackColor = WhiteSmoke <= Depends on the font color (mod. when needed)
.ShowInTaskbar = False
Public Class OverlayForm
Private _Text As String
Private TextPosition As Point
Private _Brush As SolidBrush = New SolidBrush(Color.White)
Private _Flags As StringFormatFlags = StringFormatFlags.NoWrap
Public Enum Alignment
Left = 0
Right = 1
Center = 2
End Enum
Public Sub New()
InitializeComponent()
End Sub
Public Overrides Property Text() As String
Get
Return Me._Text
End Get
Set(ByVal value As String)
_Text = value
Me.Invalidate()
End Set
End Property
Public Property OverlayPosition As Alignment
Private Sub OverlayForm_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit
e.Graphics.TextContrast = 12
Dim _Size As SizeF = e.Graphics.MeasureString(Me._Text, Me.Font,
New SizeF(Me.Width, Me.Height),
New StringFormat(Me._Flags))
e.Graphics.DrawString(Me._Text, Me.Font, Me._Brush, New RectangleF(TextAlign(_Size.Width), _Size))
End Sub
Private Sub OverlayForm_ForeColorChanged(sender As Object, e As EventArgs) Handles Me.ForeColorChanged
Me._Brush = New SolidBrush(Me.ForeColor)
Me.Invalidate()
End Sub
Public Sub Reposition(ParentPosition As Point, ParentSize As Size)
Select OverlayPosition
Case Alignment.Left
Me.Location = New Point(ParentPosition.X + 20, ParentPosition.Y + 40)
Case Alignment.Right
Me.Location = New Point(ParentSize.Width - Me.Width - 20, ParentPosition.Y + 40)
Case Alignment.Center
Me.Location = New Point(ParentPosition.X + 20 + (ParentSize.Width \ 2) - (Me.Width \ 2), ParentPosition.Y + 40)
End Select
End Sub
Private Function TextAlign(TextWidth As Single) As PointF
Select Case OverlayPosition
Case Alignment.Left
Return New PointF(1, 1)
Case Alignment.Right
Return New PointF((Me.Width - TextWidth) - 1, 1)
Case Alignment.Center
If TextWidth > Me.Width Then TextWidth = Me.Width - 2
Return New PointF(CSng((Me.Width - TextWidth) / 4) - 1, 1)
End Select
End Function
End Class

VB.NET Draw Button Over Another Button

Is it possible to draw a button on top of another button (besides just having a second button and moving it relative to the first button's Left and Top position)? I'm trying to make a little small optional question mark (button) appear in the corner of the main button that will take various actions if clicked.
Otherwise I was toying with the idea of just drawing the question mark on top of the button and getting the relative position of the mouse OnClick, then taking the action if the HasLink property is true and the mouse is in a specific area.
These will be dynamically created as well.
Public Class clsButton
Inherits Button
Private Property HasLink As Boolean = False
Public Sub New(ByVal Image As Image, ByVal ShowLink As Boolean)
Me.BackgroundImage = Image
Me.BackgroundImageLayout = ImageLayout.Center
Me.Height = 100
Me.Width = 200
If ShowLink Then DrawLink()
End Sub
Public Sub DrawLink()
Dim bmpBitmap As New Bitmap(Me.Width, Me.Height)
Dim graGraphic As Graphics = Graphics.FromImage(bmpBitmap)
Dim i As New Bitmap("c:\temp\question_mark.png")
graGraphic.DrawImage(i, (Me.Width - i.Width) - 5, 5)
Me.Image = bmpBitmap
End Sub
Protected Overrides Sub OnClick(e As EventArgs)
MyBase.OnClick(e)
Debug.WriteLine("X: " & MousePosition.X & " Y: " & MousePosition.Y)
Debug.WriteLine(Me.PointToClient(MousePosition))
End Sub
End Class
I think drawing that on top is a good idea and easily accomplished. The entire idea as such may be debatable, but I don't think it's necessarily bad.
Here is a quick example how the event flow can be set up.
Public Class SpecialButton
Inherits Button
Private flagIsHovering As Boolean = False
Private ReadOnly Property r As Rectangle
Get
Return New Rectangle(Me.Width - 20, 5, 15, 15)
End Get
End Property
Public ReadOnly Property clickInSpecialArea(p As Point) As Boolean
Get
Return (Me.r.Contains(p))
End Get
End Property
Private iconBG_normal As Color = Color.White
Private iconBG_hover As Color = Color.DarkOrange
Protected Overrides Sub OnPaint(pevent As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(pevent)
With pevent.Graphics
.FillRectangle(New SolidBrush(If(Me.flagIsHovering, iconBG_hover, iconBG_normal)), r)
.DrawRectangle(Pens.Blue, r)
.DrawString("?", New Font("Verdana", 8), Brushes.Blue, r.Location)
End With
End Sub
Protected Overrides Sub OnMouseMove(mevent As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseMove(mevent)
Dim oldState As Boolean = Me.flagIsHovering
Me.flagIsHovering = (r.Contains(mevent.Location))
If oldState <> Me.flagIsHovering Then Me.Invalidate()
End Sub
Protected Overrides Sub OnMouseLeave(e As System.EventArgs)
MyBase.OnMouseLeave(e)
If Me.flagIsHovering Then
Me.flagIsHovering = False
Me.Invalidate()
End If
End Sub
End Class
Form test code:
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim ct As New SpecialButton
ct.Text = "Text"
ct.Location = New Point(200, 20)
ct.Size = New Size(100, 30)
Me.Controls.Add(ct)
AddHandler ct.MouseClick, Sub(sender_ As Object, e_ As MouseEventArgs)
MessageBox.Show(
"Special click: " &
DirectCast(sender_, SpecialButton).clickInSpecialArea(e_.Location).ToString)
End Sub
End Sub
End Class
You can just position a small button with a question mark on it in the corner of your main button, lets say the small question mark button is called butq , now use the code below:
butq.BringToFront

Weird Picturebox Behavior

I have this program that i have 10 pictureboxes if the textbox of form1 is the same as the text in the textbox of form3 it will show the picture of a check mark otherwise it will show the picture of a crossmark..But when I typed in the answers when it shows the result it only shows one picturebox and one picturebox and always shows a checkmark which is not doing the purpose of the program and the other nine pictureboxes were missing.. (I already checked the pictureboxes and it the enabled and visible properties were all set to TRUE) Thanks in advance guys I hope you can help me with this problem.
Imports System.Convert
Imports System.IO
Imports System.Windows.Forms.PictureBox
Imports System.Drawing.Image
Public Class Form4
Inherits System.Windows.Forms.Form
Public frm1 As Form1
Private frm2 As Form2
Public frm3 As Form3
Private frm4 As Form4
Private frm5 As Form5
Private Form5 As Form5
Private Sub Form4_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim lbl3 As Integer
lbl3 = CInt(lbl3)
Me.Visible = False
End Sub
Public Sub New1(ByVal callerInstance As Form1)
' Call required if you add your constructor manually
InitializeComponent()
' save the instance of the Me variable passed to this constructor
frm1 = callerInstance
End Sub
Public Sub New5(ByVal callerInstance As Form2)
' Call required if you add your constructor manually
InitializeComponent()
' save the instance of the Me variable passed to this constructor
frm2 = callerInstance
End Sub
Public Sub New4(ByVal callerInstance As Form3)
' Call required if you add your constructor manually
InitializeComponent()
' save the instance of the Me variable passed to this constructor
frm3 = callerInstance
End Sub
Public Sub New3(ByVal callerInstance As Form4)
' Call required if you add your constructor manually
InitializeComponent()
' save the instance of the Me variable passed to this constructor
frm4 = callerInstance
End Sub
Public Sub New5(ByVal callerInstance As Form5)
' Call required if you add your constructor manually
InitializeComponent()
' save the instance of the Me variable passed to this constructor
frm5 = callerInstance
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim frm1 As Form1 = Form1
Dim frm2 As Form2 = Form2
Dim frm3 As Form3 = Form3
Dim frm5 As Form5 = Form5
If frm5 Is Nothing Then
frm5 = New Form5(Me)
AddHandler frm2.FormClosed, AddressOf Me.Form5HasBeenClosed
frm5.Label21.Text = frm1.TextBox1.Text
frm5.Label21.ForeColor = Color.Black
frm5.Label22.Text = frm1.TextBox2.Text
frm5.Label22.ForeColor = Color.Black
frm5.Label23.Text = frm1.TextBox3.Text
frm5.Label23.ForeColor = Color.Black
frm5.Label24.Text = frm1.TextBox4.Text
frm5.Label24.ForeColor = Color.Black
frm5.Label25.Text = frm1.TextBox5.Text
frm5.Label25.ForeColor = Color.Black
frm5.Label26.Text = frm1.TextBox6.Text
frm5.Label26.ForeColor = Color.Black
frm5.Label27.Text = frm1.TextBox7.Text
frm5.Label27.ForeColor = Color.Black
frm2.Label28.Text = frm1.TextBox8.Text
frm2.Label28.ForeColor = Color.Black
frm5.Label29.Text = frm1.TextBox9.Text
frm5.Label29.ForeColor = Color.Black
frm5.Label30.Text = frm1.TextBox10.Text
frm5.Label30.ForeColor = Color.Black
frm5.Label31.Text = frm1.TextBox11.Text
frm5.Label31.ForeColor = Color.Black
frm5.Label32.Text = frm1.TextBox12.Text
frm5.Label32.ForeColor = Color.Black
frm5.Label33.Text = frm1.TextBox13.Text
frm5.Label33.ForeColor = Color.Black
frm5.Label34.Text = frm1.TextBox14.Text
frm5.Label34.ForeColor = Color.Black
frm5.Label35.Text = frm1.TextBox15.Text
frm5.Label35.ForeColor = Color.Black
frm5.Label36.Text = frm1.TextBox16.Text
frm5.Label36.ForeColor = Color.Black
frm5.Label37.Text = frm1.TextBox17.Text
frm5.Label37.ForeColor = Color.Black
frm5.Label38.Text = frm1.TextBox18.Text
frm5.Label38.ForeColor = Color.Black
frm5.Label39.Text = frm1.TextBox19.Text
frm5.Label39.ForeColor = Color.Black
frm5.Label40.Text = frm1.TextBox20.Text
frm5.Label40.ForeColor = Color.Black
End If
If frm5 IsNot Nothing Then
frm5.Show(Me) 'Show Second Form
Me.Hide()
End If
If CBool(String.Compare(frm1.TextBox2.Text.Trim(), frm3.TextBox1.Text.Trim(), True)) Then
frm5.PictureBox1.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox1.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
If CBool(String.Compare(frm1.TextBox4.Text.Trim(), frm3.TextBox2.Text.Trim(), True)) Then
frm5.PictureBox2.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox2.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
If CBool(String.Compare(frm1.TextBox6.Text.Trim(), frm3.TextBox3.Text.Trim(), True)) Then
frm5.PictureBox3.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox3.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
If CBool(String.Compare(frm1.TextBox8.Text.Trim(), frm3.TextBox4.Text.Trim(), True)) Then
frm5.PictureBox4.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox4.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
If CBool(String.Compare(frm1.TextBox10.Text.Trim(), frm3.TextBox5.Text.Trim(), True)) Then
frm5.PictureBox5.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox5.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
If CBool(String.Compare(frm1.TextBox12.Text.Trim(), frm3.TextBox6.Text.Trim(), True)) Then
frm5.PictureBox6.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox6.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
If CBool(String.Compare(frm1.TextBox14.Text.Trim(), frm3.TextBox7.Text.Trim(), True)) Then
frm5.PictureBox7.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox7.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
If CBool(String.Compare(frm1.TextBox16.Text.Trim(), frm3.TextBox8.Text.Trim(), True)) Then
frm5.PictureBox8.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox8.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
If CBool(String.Compare(frm1.TextBox18.Text.Trim(), frm3.TextBox9.Text.Trim(), True)) Then
frm5.PictureBox9.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox9.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
If CBool(String.Compare(frm1.TextBox20.Text.Trim(), frm3.TextBox10.Text.Trim(), True)) Then
frm5.PictureBox10.Image = Image.FromFile("D:\vbproject\vbp\checkmark.jpg")
Else
frm5.PictureBox10.Image = Image.FromFile("D:\vbproject\vbp\crossmark.jpg")
frm5.Show()
Me.Hide()
End If
End If
End If
End If
End If
End If
End If
End If
End If
End If
If frm5 IsNot Nothing Then
frm5.Visible = False
frm5.Show() 'Show Second Form
Me.Hide()
End If
End Sub
Private Sub Form5HasBeenClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs)
Throw New NotImplementedException
End Sub
End Class
There are some issues here that needs to be addressed:
1. You have pasted far to much code. All you needed was to paste the If statements (Because that is where you are having problem, and that is where the problem is).
2. And this is regarding your problem:
String.Compare will give you the result 0 if two strings match. 0 (which is also known as false if you convert it to Boolean). So when two strings match you correctly display a Cross. Compare will also tell you which String is bigger than the other. 1 if the first one is bigger, -1 if it isn't (Sidetrack not important here). I suggest you do the following instead:
If frm1.TextBox2.Text.ToUpper().Equals(frm3.TextBox1.Text.ToUpper()) Then
In this case it is pretty obvious what happends. If string 1 is equal to string two then the result is True. No CBool required.
Your ifstatements are messed up. Question 2-oo will only be addressed if the first statement is false. I will show you what I mean.
If statement = true Then
Display checkmark
Else
Display cross
'Now you do the next one inside the else statement
If statement2 = True Then
'Display checkmark
Else
Display cross
'And then you continue the nesting
End If
End If
What you need to do is this:
If statement = true Then
'Display check
Else
'Display cross
End If 'Notice how I close the ifstatement before I go to the next one.
If statement2 = true Then
'Display check
Else
'Display cross
End If
etc...
I hope you get this, otherwise let me know and I'll try to simplify it further.