VB: How can I make buttons over a picture box transparent? - vb.net

in my program I have a picture box with a specific width x and height y. Then the user can enter an elementsize (e.g. 10) and then the programm will create buttons with the width and height of the elementsize over the picture box. The thing is that these buttons need to be transparent so only their border is visible. That means that through the buttons you can see the content of the picture box.
So this is my code for creating these buttons when I click on my start button:
Imports System.Math
Public Class Form1
Dim x As Double
Dim y As Double
Dim elsize As Integer
Dim numberofbuttons As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
x = 400
y = 200
elsize = 20
numberofbuttons = Round(x / elsize) * Round(y / elsize)
Dim i As Integer
Dim j As Integer
For j = 1 To Round(y / elsize)
For i = 1 To Round(x / elsize)
Dim Btn As New Button
Btn.Width = elsize
Btn.Height = elsize
Btn.Location = New Point(elsize * (i - 1), elsize * (j - 1))
Btn.BackColor = Color.Transparent
PictureBox1.Controls.Add(Btn)
Next
Next
End Sub
End Class
I use
Btn.BringToFront()
to put these buttons in front of the picture box and I wanted to use
Btn.BackColor = Drawing.Color.Transparent
to make them transparent but this won't work. Has anybody any ideas how to do this? Also I wanted to put these buttons in the coordinate system of the picture box and not of the form1. I thought that this is possible through
Btn.Parent = PictureBox1
but the buttons always use the coordinate system of the form.
Thanks in advance for your help.

This:
Me.Controls.Add(Btn)
is setting the Parent of the Button to be the form. You don't Add to one parent and assign a different parent explicitly. Do one or the other. In short, get rid of that Add call and you should be good to go. Alternatively, get rid of the Parent assignmnent and Add to the Controls collection of the PictureBox instead. I'd suggest the latter.
Either way, DO NOT display the Button until you have configured it, i.e. set the Parent or call Controls.Add last.
EDIT: I tested this code and it worked as expected:
Dim btn As New Button
With btn
.Size = mySize
.Location = myLocation
.BackColor = Color.Transparent
.FlatStyle = FlatStyle.Flat
PictureBox1.Controls.Add(btn)
End With

Related

Is it possible to group multiple PictureBoxes?

I can drag a PictureBox onto a Form Control, a Tab Control or a Panel Control, etc. And I can import an image into a PictureBox. However, I don't know how to group multiple PictureBoxes together in Visual Studio 2017. Looks like there is no such a function. I need this function because I want to generate a big picture based on the user's input. That big picture consists of multiple small pictures, the visibility of which is controlled by the user through multiple checkboxes.
In Excel, I could put multiple pictures in it, group them together, use the VBA to control the visibility of each picture, and finally copy that picture group into a Word file. I would do this in a VSTO Word Document project in Visual Studio 2017 using vb.net.
I added some pictures for demonstrate the expected function.
Picture 1 shows the small pictures to be used in a big picture. (Please ignore the .vslx file)
Picture 2 shows a possible result based on user's input.
You can make your own custom control. here is an example/suggestion how to do it with a User control that can be reused across your application. the user control is holding panels in a matrix, you can set a drag&drop Event to each Panel control and the user will be able to drop a picture box on each panel:
USER CONTROL:
Public Class UserControl1
Public NumberOfPanelsInRow As Integer
Sub New(ByVal height As Integer, width As Integer, Optional ByVal numberofPanelsInRow As Integer = 3)
' This call is required by the designer.'
InitializeComponent()
' Add any initialization after the InitializeComponent() call.'
Me.Height = height
Me.Width = width
Me.NumberOfPanelsInRow = numberofPanelsInRow
End Sub
Private Sub UserControl1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
' grouped panels to hold picturebox you can drag & drop to them...'
Dim panelHeight As Integer = Me.Height / NumberOfPanelsInRow
Dim panelWidth As Integer = Me.Width / NumberOfPanelsInRow
Dim colors() As Color = {Color.Pink, Color.Black, Color.Red, Color.Cyan, Color.Green, Color.Orange,
Color.Red, Color.Pink, Color.Black, Color.Red, Color.Cyan, Color.Green, Color.Orange, Color.Red}
Dim total As Integer = NumberOfPanelsInRow * NumberOfPanelsInRow
Dim currentYlocation As Integer = 0
Dim currentXlocation As Integer = 0
Dim location As Point = New Point(0, currentYlocation)
Dim rowcounter As Integer = 0
Dim itemcounter As Integer = 0
For i = 1 To total
If rowcounter >= NumberOfPanelsInRow Then
rowcounter = 0
currentYlocation += panelHeight
currentXlocation = 0
End If
' to each one of this panel you can drag a picture box'
Dim p As New Panel
p.Size = New Size(panelWidth, panelHeight)
p.Location = New Point(currentXlocation, currentYlocation)
p.BackColor = colors(itemcounter)
Me.Controls.Add(p)
rowcounter += 1
itemcounter += 1
currentXlocation += panelWidth
Next
End Sub
End Class
CALLING THE USER CONTROL FROM FORM1:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim uc = New UserControl1(300, 300)
Me.Controls.Add(uc)
End Sub
End Class
GUI OUTPUT:

Resize form on listview height

I have form with only docked.full listview on it. Listview show computer drives so it's content is changeable on runtime. On listview column headers are allways visible.
I would like my form to resize with listview regarding of filled items.
This is my code:
Dim rc As Rectangle = lvDriveInfo.Items(0).GetBounds(ItemBoundsPortion.Entire)
Me.Height = (rc.Height * lvDriveInfo.Items.Count) +
SystemInformation.CaptionHeight +
SystemInformation.BorderSize.Height
But something misses here or is incorrect.
How to get exact height of listview with headers regarding on items.count and properly set height of form with this value?
ListView metrics are rather convoluted, what you are trying to do is most definitely not easy. The one thing you overlooked is the space required by the column headers. That however is not enough, ListView also requires a bit of extra elbow room at the bottom to avoid displaying the scrollbar.
The most straight-forward code that works on my machine is:
Private Sub ResizeView()
If ListView1.Items.Count = 0 Then Exit Sub
Dim last = ListView1.Items(ListView1.Items.Count - 1)
Me.ClientSize = New Size(Me.ClientSize.Width, _
ListView1.Top + last.Bounds.Bottom + 4)
End Sub
The +4 is the rub, I can't give you a warranty that this will work on every Windows version at every video DPI. It is independent of the item height so that's encouraging. But testing required to be sure. If you can guarantee that there will never be too many items in the list then you can avoid the problem by setting the list view's Scrollable property to False.
Try the following code
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lvDriveInfo.BorderStyle = BorderStyle.None
lvDriveInfo.Dock = DockStyle.Fill
With lvDriveInfo
.View = View.Details
.GridLines = True
.Columns.Add("Drive")
End With
SetFormHeight()
End Sub
Private Sub SetFormHeight()
lvDriveInfo.Items.Clear()
For Each Drive In IO.DriveInfo.GetDrives
lvDriveInfo.Items.Add(Drive.Name)
Next
Dim ListViewHeaderHeight As Integer = lvDriveInfo.Items(0).Bounds.Top
Dim ListViewRowHeight As Integer = lvDriveInfo.Items(0).Bounds.Height
Dim ListViewRowsCount As Integer = lvDriveInfo.Items.Count
Dim NewHeight As Integer = ListViewHeaderHeight + (ListViewRowHeight * ListViewRowsCount)
Me.ClientSize = New Size(Me.ClientSize.Width, NewHeight)
End Sub

When creating a label a label inside a panel, the text is cut off VisualBasic

I wanted to be able to dynamically create a panel with a label on it, but the label isn't acting as I would expect it too, its cutting most of it off.
When I create a panel then create a label inside the panel, the text isn't displayed correctly. Anyone know how to fix it?
What is was supposed to do was to create a panel with text on it with the newpanel() sub
Dim timetable(5, 5) As String
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Width = (74 * 5) - 3
Me.Height = My.Computer.Screen.Bounds.Size.Height
Me.Top = My.Computer.Screen.Bounds.Top
Me.Left = My.Computer.Screen.Bounds.Right - Me.Width
GetTimetable()
End Sub
Private Sub newpanel(colour As Color, textT As String)
Dim Npan As New Panel
Npan.Top = 0
Npan.Left = 0
Npan.Width = Me.Width
Npan.Height = 64
Npan.BackColor = colour
Dim NpanT As New Label
NpanT.Parent = Npan
NpanT.Text = textT
Npan.Controls.Add(NpanT)
Me.Controls.Add(Npan)
End Sub
Private Sub GetTimetable()
'Dim path As String = My.Computer.FileSystem.SpecialDirectories.Desktop + "\Timetable"
newpanel(Color.Aqua, "this is a test! test testtesttest test test test")
End Sub
Looking at the MSDN page for the Label.AutoSize Property, it states as was mentioned above that the Labels AutoSize Property defaults to true in the designer, but it is false when created in code.
From above link:
When added to a form using the designer, the default value is true. When instantiated from code, the default value is false.
So you need to change your newpanel method to this:
Private Sub newpanel(colour As Color, textT As String)
Dim Npan As New Panel
Npan.Top = 0
Npan.Left = 0
Npan.Width = Me.Width
Npan.Height = 64
Npan.BackColor = colour
Dim NpanT As New Label
NpanT.Parent = Npan
NpanT.Text = textT
NpanT.AutoSize = True 'Enables Auto sizing
Npan.Controls.Add(NpanT)
Me.Controls.Add(Npan)
End Sub

Simple VB, handling many buttons

In my VB solution I have a lot of buttons arranged in a grid. When the program is loaded one of the buttons is randomly set to be the right one (You have to click that one to win). Can anybody point my in the right direction? Because there must be a better way than manually coding every single button, and creating an event handler for every single button.
You don't have to give me a working example, just an overall idea of how this is done.
Thanks.
If you want to arrange the buttons in a grid, either use the TableLayoutPanel or add the buttons directly to the form and calculate their positions. The TableLayoutPanel is useful if you want to arrange the buttons automatically when the form resizes, otherwise adding the buttons directly seems easier to me.
Add the buttons to an array defined at form level to make them easily accessible
Public Const NColumns As Integer = 5, NRows As Integer = 4
Private buttons As Button(,) = New Button(NColumns - 1, NRows - 1) {}
You can add the buttons easily in loops
For ix As Integer = 0 To NColumns - 1
For iy As Integer = 0 To NRows - 1
Dim btn = New Button()
btn.Text = String.Format("{0:d2}{1:d2}", ix, iy)
btn.Location = New Point(leftMargin + ix * xDistance,
topMargin + iy * yDistance)
btn.Size = New Size(buttonWidth, buttonHeight)
AddHandler btn.Click, Addressof Button_Clicked
buttons(ix, iy) = btn
Controls.Add(btn)
Next
Next
You can determine the winning button with a random generator. Define it as form member, not as local variable.
Private randomGenrator As System.Random = New System.Random()
Determine the coordinates
Dim xWins = randomGenrator.Next(NColumns) 'Returns a number between 0 and NColumns-1
Dim yWins = randomGenrator.Next(NRows)
The click handler looks like this
Private Sub Button Button_Clicked(sender As Object, e As EventArgs)
If sender = buttons(xWins, yWins) Then
'You win
Else
'You loose
End
End Sub
First, you said you want a grid of buttons, so you have to have a FlowLayoutPanel control in your form in order to let the buttons you want to add, to be arranged automatically.
Second, you have to make use of a for loop, r any kind of look, in order to add the buttons to be added to previously added 'FlowLayoutPanel'.
class Answers
Dim strAnswerText as string
Dim AnswerFlag as Boolean
End Class
Sub LoadForm(byval a_Answers as Answer())
Dim i as Integer = 0
Dim b as Button
For(i=0;i<NUM_OF_BUTTONS;i++)
b = New Button()
b.Text = "Choice -" & i & "- " & a_Answers(i).strAnswerText
b.Tag = a_Answers(i).AnswerFlag
'Supposing that the FlowLayoutPanel control name is fl
AddHandler b.Click, Addressof Clicked
fl.controls.Add(b)
End For
End Sub
Sub Button Clicked(sender as object, e as EventArgs)
if sender.Tag = True
'True answer
else
'Wrong answer
end if
End Sub

Resizing Window Form control

My problem is that I am unable to resize the form control according to the form size.
I have a form which contains a textbox, a label and a button. On button click I need to open the same form in a particular sized window and I want all the controls of the form should be proportional with the form and the font size inside the control should be proportional too. Can anybody please suggest how to do that with code. Unable to solve this by using the anchor and dock property.
My code:
Private Sub Test_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim widthRatio As Single = Me.Size.Width / 300.0F
Dim heightRatio As Single = Me.Size.Height / 300.0F
Dim scale As New SizeF(widthRatio, heightRatio)
Me.Scale(scale)
For Each control As Control In Me.Controls
control.Scale(scale)
control.Font = New Font(control.Font.FontFamily, control.Font.SizeInPoints * widthRatio * heightRatio)
Next
End Sub
here for width and height ratio I have divided 300.0F because my original form is size(300,300), but I am not getting all the controls expand equally... any suggestion is appreciated.
Thanks
pallavi
Check these two lines
Dim widthRatio As Single = Me.Size.Width / 300.0F
Dim heightRatio As Single = Me.Size.Height / 300.0F
in your case Me.Size.Width = 300 and Me.Size.Height = 300 that's why its not working, change width or height then check it