VB.NET PictureBox / Controls - vb.net

So interesting dilemma, I've managed to make a label completely invisible, to where I can use it for a click event on certain parts of a picture.
I then use that click event to call another picturebox into focus using picturebox3.visible = true..
The issue I'm having is when it's calling that picturebox visibility..the controls from the new picturebox (Invisible labels) seem to not function or be missing from the picture in picturebox2 completely.
I need to do this with about 30 different pictures in order to create a kind of "emulator" project for someone.
Any ideas on this? I can post code if needed. Picturebox + controls on picturebox = headache.
Public Class InvisibleLabel
Inherits Label
Public Sub New()
Me.SetStyle(ControlStyles.Opaque, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, False)
End Sub
Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
Get
Dim CC As CreateParams = MyBase.CreateParams
CC.ExStyle = CC.ExStyle Or &H20
Return CC
End Get
End Property
End Class
This is the code for the invisible label, then I'm just using picturebox2.visible = true when certain parts of a picture are clicked.

I made 3 textboxes
textbox1 for X 'just for you to see
textbox2 for Y 'just for you to see
and
CurPicture to compare current image
my picturebox is 300,300
Private Sub PictureBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseClick
Dim LocX As Integer = e.X
Dim LocY As Integer = e.Y
TextBox1.Text = e.X.ToString
TextBox2.Text = e.Y.ToString
If LocX > 200 Then ' click right side op the picture , change LocX With LocY to make it bottom
If CurPicture.Text = "1" Then
PictureBox1.Image = My.Resources.Pic2
CurPicture.Text = "2"
ElseIf CurPicture.Text = "2" Then
PictureBox1.Image = My.Resources.Pic3
CurPicture.Text = "3"
ElseIf CurPicture.Text = "3" Then
PictureBox1.Image = My.Resources.Pic4
CurPicture.Text = "4"
ElseIf CurPicture.Text = "4" Then
PictureBox1.Image = My.Resources.Pic5
CurPicture.Text = "5"
ElseIf CurPicture.Text = "5" Then
PictureBox1.Image = My.Resources.Pic1
CurPicture.Text = "1"
End If
End If
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
PictureBox1.Image = My.Resources.Pic1
CurPicture.Text = "1"
End Sub
Hope this will help you get on the way :)

Use:
Private Sub PictureBox_MouseDown(sender As Object, e As MouseEventArgs) _
Handles PictureBox.MouseDown
'The code to change the picture goes here
End Sub

Related

ListView: MultiSelect items with mouse drag

In ListView, I can press Ctrl + Shift and click on the item to select. But, I want to drag the mouse to select the items (like DataGridView). I tried this code (below) and I had a problem like this:
My code:
Private mouseDownLV As Boolean
Private Sub ListView1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseDown
mouseDownLV = True
End Sub
Private Sub ListView1_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseMove
If mouseDownLV Then
Try
Dim i = ListView1.HitTest(e.Location).Item.Index
ListView1.Items(i).Selected = True
Catch ' ex As Exception
End Try
End If
End Sub
Private Sub ListView1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseUp
mouseDownLV = False
End Sub
Actually you need to iterate through the currently displayed ListViewItem objects and toggle the Selected property of the items that intersect with the mouse movement. Here's a way to achieve that:
Declare a class member named startPoint:
Private startPoint As Point
Handle the MouseDown event to set the starting position:
Private Sub ListView1_MouseDown(sender As Object, e As MouseEventArgs) Handles ListView1.MouseDown
Dim s = DirectCast(sender, ListView)
If e.Button = MouseButtons.Left AndAlso
s.Items.Count > 1 Then
startPoint = e.Location
End If
End Sub
Handle the MouseMove event to toggle the Selected property:
Private Sub ListView1_MouseMove(sender As Object, e As MouseEventArgs) Handles ListView1.MouseMove
Dim s = DirectCast(sender, ListView)
If e.Button = MouseButtons.Left AndAlso s.Items.Count > 1 Then
Dim selRect As New Rectangle(Math.Min(startPoint.X, e.Location.X),
Math.Min(startPoint.Y, e.Location.Y),
Math.Abs(e.Location.X - startPoint.X),
Math.Abs(e.Location.Y - startPoint.Y))
Dim cr = s.ClientRectangle
'Toggle selection...
For Each item In s.Items.Cast(Of ListViewItem).
Where(Function(x) x.Bounds.IntersectsWith(cr))
item.Selected = selRect.IntersectsWith(item.Bounds)
Next
End If
End Sub
A quick demo to check that:
But what if you have many items where the size of the client area is not large enough to display them all and thus the vertical scrollbar is visible? You will get something like this:
As you can see, the vertical scrollbar does not move and you won't be able to continue selecting/deselecting the hidden items. To fix that, we need some more code:
Import the signature of the GetScrollPos function somewhere in your class:
Imports System.Runtime.InteropServices
'...
<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Shared Function GetScrollPos(hWnd As IntPtr,
nBar As Orientation) As Integer
End Function
Note: Passing a System.Windows.Forms.Orientation value instead of an Interger.
Change the MouseDown event to:
Private Sub ListView1_MouseDown(sender As Object, e As MouseEventArgs) Handles ListView1.MouseDown
Dim s = DirectCast(sender, ListView)
If e.Button = MouseButtons.Left AndAlso
s.Items.Count > 1 Then
Dim vsp = GetScrollPos(s.Handle, Orientation.Vertical)
Dim yOffset = s.Font.Height * vsp
startPoint = New Point(e.X, e.Y + yOffset)
End If
End Sub
And the MouseMove event to:
Private Sub ListView1_MouseMove(sender As Object, e As MouseEventArgs) Handles ListView1.MouseMove
Dim s = DirectCast(sender, ListView)
If e.Button = MouseButtons.Left AndAlso s.Items.Count > 1 Then
Dim vsp = GetScrollPos(s.Handle, Orientation.Vertical)
Dim yOffset = s.Font.Height * vsp
Dim selRect As New Rectangle(Math.Min(startPoint.X, e.Location.X),
Math.Min(startPoint.Y - yOffset, e.Location.Y),
Math.Abs(e.Location.X - startPoint.X),
Math.Abs(e.Location.Y - startPoint.Y + yOffset))
Dim cr = s.ClientRectangle
'Toggle selection...
For Each item In s.Items.Cast(Of ListViewItem).
Where(Function(x) x.Bounds.IntersectsWith(cr))
item.Selected = selRect.IntersectsWith(item.Bounds)
Next
'Scroll if needed...
Dim p = s.PointToClient(Cursor.Position)
Dim lvi = s.GetItemAt(p.X, p.Y)
If lvi Is Nothing Then Return
Dim fh = s.Font.Height
If lvi.Index > 0 AndAlso (p.Y - lvi.Bounds.Height * 1.5) <= fh Then
s.Items(lvi.Index - 1).EnsureVisible()
ElseIf lvi.Index < s.Items.Count - 1 AndAlso
(p.Y + lvi.Bounds.Height * 1.5) > (s.Height - fh) Then
s.Items(lvi.Index + 1).EnsureVisible()
End If
End If
End Sub
The outcome is:
Here is VB.NET custom ListView control for this problem, and another in C#.

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

access to new dynamically controls in vb.net

First of all excuse me for my poor grammar and vocabulary :)
please see this source and run it:
Public Class Form1
Public pointX As Integer
Public pointY As Integer = 32
Public dynamicText As TextBox
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
pointX = 330
For i = 1 To 4
dynamicText = New Windows.Forms.TextBox
dynamicText.Name = "T" + Trim(Str(i))
dynamicText.Text = ""
dynamicText.Location = New Point(pointX, pointY)
dynamicText.Size = New Size(100, 20)
Me.Controls.Add(dynamicText)
pointX = pointX - 106
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
pointX = 330
pointY = pointY + 26
For i = 1 To 4
dynamicText = New Windows.Forms.TextBox
dynamicText.Name = "T" + Trim(Str(i))
dynamicText.Text = ""
dynamicText.Location = New Point(pointX, pointY)
dynamicText.Size = New Size(100, 20)
Me.Controls.Add(dynamicText)
pointX = pointX - 106
AddHandler dynamicText.Click, AddressOf printHello1
Next
End Sub
Private Sub printHello1(ByVal sender As System.Object, ByVal e As System.EventArgs)
MsgBox(dynamicText.Name)
If dynamicText.Name = "T1" Then MsgBox("Oh! this is T1")
End Sub
End Class
why If never is not true?!
why MsgBox(dynamicText.Name) always return T4?!
i want all controlls to be access by name or array of names.
please help me thank you. :)
The global variable dynamicText takes the value of the last TextBox added in the loop inside the Button1_Click event. This happens to be the control named T4. You don't really need a global variable in this case. You can cast the sender parameter to a TextBox instance because the sender parameter is the control that has raised the event.
Private Sub printHello1(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim txt = CType(sender, "TextBox")
if txt IsNot Nothing then
MsgBox(txt.Name)
If txt.Name = "T1" Then MsgBox("Oh! this is T1")
End If
End Sub
You also don't need to recreate the controls again in the button click event. The action executed in the form load event is enough (You could add the AddHandler there). Global variables are dangerous, avoid them when possible.
See if this is acceptable. Place a panel at the bottom of your form, set Dock to Bottom, add a single button to the panel and a TextBox. Place a FlowLayoutPanel onto the form, Dock = Fill, AutoScroll = True.
The code below creates the amount of TextBox controls as inputted into TextBox. Each newly created TextBox a click event is added with simple logic.
Form code
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim count As Integer = 0
If Integer.TryParse(TextBox1.Text, count) Then
Dim demo = New TextBoxCreate(FlowLayoutPanel1, "Demos", count)
demo.CreateTextBoxes()
End If
End Sub
End Class
Class code (add a new class to the project, name it TextBoxCreate.vb)
Public Class TextBoxCreate
Public Property TextBoxes As TextBox()
Public Property TextBoxBaseName As String
Public Property TextBoxCount As Integer
Public Property ParentControl As Control
Public Sub New(
ByVal ParentControl As Control,
ByVal BaseName As String,
ByVal Count As Integer)
Me.ParentControl = ParentControl
Me.TextBoxBaseName = BaseName
Me.TextBoxCount = Count
End Sub
Public Sub CreateTextBoxes()
Dim Base As Integer = 10
TextBoxes = Enumerable.Range(0, TextBoxCount).Select(
Function(Indexer)
Dim b As New TextBox With
{
.Name = String.Concat(TextBoxBaseName, Indexer + 1),
.Text = (Indexer + 1).ToString,
.Width = 150,
.Location = New Point(25, Base),
.Parent = Me.ParentControl,
.Visible = True
}
AddHandler b.Click, Sub(sender As Object, e As EventArgs)
Dim tb As TextBox = CType(sender, TextBox)
If tb.Name = TextBoxBaseName & "1" Then
tb.Text = "Got it"
Else
MessageBox.Show(tb.Name)
End If
End Sub
Me.ParentControl.Controls.Add(b)
Base += 30
Return b
End Function).ToArray
End Sub
End Class

VB Radio button and Combo Box Flash

I have written a small piece of code to change the display member of my combo box when a radio button is selected. The only problem I'm having is that when I switch between the radio buttons the combo box disappears then comes back a second later, is there any way of resolving this problem.
Private Sub SearchOptionChange(sender As Object, e As EventArgs) Handles RBExchange.CheckedChanged, RBPostcode.CheckedChanged
Dim RB As RadioButton = CType(sender, RadioButton)
If RB.Name = "RBExchange" AndAlso RB.Checked Then
ComboBox1.DisplayMember = "Exchange"
ComboBox1.Text = ""
ElseIf RB.Name = "RBPostcode" AndAlso RB.Checked Then
ComboBox1.DisplayMember = "Postcode"
ComboBox1.Text = ""
End If
End Sub
I used the following to reproduce your issue and it only happens when DropDownStyle is set to Simple. So if possible set DropDownStyle to DropDown.
Note I used 5,000 items and no blinking, jumped to 10,000 and the blinking was there so in addition to the suggestion above consider if possible to reduce how many items in the ComboBox if business logic allows.
Test used and note that even SuspendLayout and ResumeLayout did not help when DropDownStyle is set to Simple.
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) _
Handles MyBase.Load
Dim ItemList As New List(Of item)
For x As Integer = 0 To 50000
ItemList.Add(New item With
{
.Exchange = "E" & x.ToString,
.PostCode = "P" & x.ToString
})
Next
ComboBox1.DisplayMember = "Exchange"
ComboBox1.DataSource = ItemList
End Sub
Private Sub RBExchange_CheckedChanged(sender As Object, e As EventArgs) _
Handles RBExchange.CheckedChanged, RBPostcode.CheckedChanged
Dim RB As RadioButton = CType(sender, RadioButton)
RB.SuspendLayout()
If RB.Name = "RBExchange" AndAlso RB.Checked Then
ComboBox1.DisplayMember = "Exchange"
ComboBox1.Text = ""
ElseIf RB.Name = "RBPostcode" AndAlso RB.Checked Then
ComboBox1.DisplayMember = "Postcode"
ComboBox1.Text = ""
End If
RB.ResumeLayout()
End Sub
End Class
Public Class item
Public Property Exchange
Public Property PostCode
End Class

Navigating with arrow keys in vb.net

I'm trying to make navigation through controls with arrow keys (up/down).
To try my example just create a new form1 and paste this code into it.
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim tb As New TextBox
Dim cb As New CheckBox
Dim cbb As New ComboBox
Dim b1 As New Button
Dim b2 As New Button
With Me
.KeyPreview = True
.Size = New Size(350, 200)
With .Controls
.Add(tb)
With tb
.TabIndex = 0
.Location = New Point(95, 20)
.Text = "This is"
End With
.Add(cb)
With cb
.TabIndex = 1
.Location = New Point(95, 50)
.Checked = True
.Text = "Example checkbox"
.AutoSize = True
End With
.Add(cbb)
With cbb
.TabIndex = 2
.Location = New Point(95, 80)
.Text = "an Example"
.DropDownStyle = ComboBoxStyle.DropDownList
End With
.Add(b1)
With b1
.TabStop = False
.Location = New Point(90, 130)
.Text = "Nothing"
End With
.Add(b2)
With b2
.TabStop = False
.Location = New Point(170, 130)
.Text = "Exit"
AddHandler b2.Click, AddressOf b2_Click
End With
End With
End With
End Sub
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
If e.KeyCode = Keys.Up Then
e.Handled = True
Me.SelectNextControl(Me.ActiveControl, False, True, True, True)
End If
If e.KeyCode = Keys.Down Then
e.Handled = True
Me.SelectNextControl(Me.ActiveControl, True, True, True, True)
End If
End Sub
Private Sub b2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Me.Close()
End Sub
End Class
What happens?
When starting a program and navigating with arrows there havent 'focus rect' around controls and in some situation focus "run's out" to controls with tabstop = false??
But...
If I pass once with TAB key through controls after that navigating with arrows becomes good, focus rect appear's and everything is OK.
What may be problem here?
What to do that navigating with arrows behaves a same like with tab key immediately after program starts?
I find a solution to get things working as expected "through code" here:
C# code
And here is my translation to VB.
1) In some your public module add imports...
Imports System.Runtime.InteropServices
2) Put this declarations in same module:
<DllImport("user32.dll")> _
Private Sub SystemParametersInfo(ByVal uiAction As UInteger, ByVal uiParam As UInteger, ByRef pvParam As Integer, ByVal fWinIni As UInteger)
End Sub
' Constants used for User32 calls.
Const SPI_SETKEYBOARDCUES As UInteger = &H100B
3) Put this public function in same module:
''' <summary>
''' Change the setting programmatically
''' for keyboard shortcut Issue
''' </summary>
Public Sub GetAltKeyFixed()
Dim pv As Integer = 1
' Call to systemparametersinfo to set true of pv variable.
SystemParametersInfo(SPI_SETKEYBOARDCUES, 0, pv, 0)
'Set pvParam to TRUE to always underline menu access keys,
End Sub
4) From start place of your program (say Form1) just call:
GetAltKeyFixed()
Once is enough :)