Close panel if clicked outside - vb.net

I'm making a custom ComboBox, and I'm struggling to make it's dropdown (a Panel) close when the user clicks outside. As everyone probably knows, using LostFocus event is not enough because when the user clicks on eg.: a scroolbar or the form itself, the control doesn't lose focus. I tried using IMessageFilter, but I don't think I understood how it works. I also tried using the Capture property, forcing the dropdown to capture the mouse, but that also forces the mouse click to happen on the dropdown (Panel) itself, meaning that if the user had clicked on an item on the dropdown, the click won't work.
Let me clarify:
I'm making a custom control, a UserControl, which is compiled to a .DLL, and can be dragged'n dropped from the Toolbox onto forms, just like any other Winforms control.
The control is a Combobox.
I want to make the Combobox's dropdown (which is a panel, created at runtime) close when the user clicks outside of it, just like a normal ComboBox.
And what is the problem? Detecting clicks outside of the panel and then closing it.
-> Using LostFocus event: Not enough. If the user clicks on a blank space on the form, LostFocus is not fired. I know I can place a LostFocus event on my form and set the ActiveContrl to Nothing, but that would require that users (devs) of my custom ComboBox place the same code on every form they use the control.
-> Using Capture property: Has given the best results so far. There are still some problems though. When Capture is set to True, the mouse is indeed captured by the control which has that property set to True. Therefore, no mouse activity is sensed by any other control on the app, but only the control which has the mouse captured. It'll only release the mouse when the user performs a click. This leads to some problems:
If the user clicks on an item (a Button) on the dropdown, and the dropdown (a Panel) has its Capture property set to true, the click will be "ignored", as it'll be handled by the dropdown, and not by the Buttonon which the user actually wanted to click.
If the user clicks on the dropdown's scroolbar, the click will also be "ignored", just like explained above.
When user moves the mouse above the Buttons inside the dropdown (the ComboBox's items), they are not highlighted, because no MouseEnter is fired for them, as the mouse is Captured by the dropdown.
There is a way to solve the first issue: You can find on which button is the mouse pointing using Control.MousePosition, and then force a click on it.
I haven't been able to find a way to solve the 2nd and 3rd issue though. One possible solution I thought of was setting the dropdown's Capture property to False when the mouse enters on it. So, this is how it would work:
User clicks on the Combobox. Dropdown opens, captures the mouse;
User then moves the mouse inside Combobox's dropdown. Capture is set to false, thus making it possible for the user to click on any button inside the dropdown or on the dropdown's scroolbar, and so forth. Buttons inside the dropdown are also properly highlighted as user moves the mouse above them;
User moves the mouse outside Combobox's dropdown, Capture is again set to true, and now any click the user perform outside of it will be "ignored", and the dropdown will be closed. Just like a normal Combobox.
But when I tried to do this, another issue arrived: when a control has its Capture property set to True, it'll constantly fire MouseEnter events. MouseEnter event doesn't use the real mouse pointer location. Even if the mouse pointer is actually outside a Control, that Control will think the mouse is actually inside of it if its Capture property is set to True.

Edit2: here is the code for handling some different types of events (should work for all cases now).
Public Class Form1
Private Shared mouseNotify() As Int32 = {&H201, &H204, &H207} ' WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN
Private Shared scrollNotify() As Int32 = {&H114, &H115} ' WM_HSCROLL, WM_VSCROLL
Private Shared scrollCommands() As Int32 = {0, 1, 2, 3, 4, 5} ' SB_LINEUP, SB_LINEDOWN, SB_PAGEUP, SB_PAGEDOWN, SB_THUMBTRACK, SB_THUMBPOSITION
Private Sub baseLoad(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
AutoScroll = True
Controls.Add(myPanel)
Controls.Add(myTextBox4)
myPanel.myTextBox1.Focus()
End Sub
Private myTextBox4 As New customTextBox(300)
Private myPanel As New customPanel
Protected Overrides Sub OnScroll(ByVal se As ScrollEventArgs)
MyBase.OnScroll(se)
ActiveControl = Nothing
End Sub
Protected Overrides Sub OnMouseWheel(ByVal e As MouseEventArgs)
MyBase.OnMouseWheel(e)
ActiveControl = Nothing
End Sub
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
ActiveControl = Nothing
End Sub
Protected Overrides Sub OnMove(ByVal e As System.EventArgs)
MyBase.OnMove(e)
ActiveControl = Nothing
End Sub
Friend Shared Function isOverControl(ByRef theControl As Control) As Boolean
Return theControl.ClientRectangle.Contains(theControl.PointToClient(Cursor.Position))
End Function
Protected Overrides Sub WndProc(ByRef m As Message)
If mouseNotify.Contains(CInt(m.Msg)) Then
If Not isOverControl(myPanel) Then
ActiveControl = Nothing
Else
myPanel.myTextBox1.Focus()
End If
End If
MyBase.WndProc(m)
End Sub
Friend Class customPanel : Inherits Panel
Friend myTextBox1 As New customTextBox(20)
Private myTextBox2 As New customTextBox(60)
Private myTextBox3 As New customTextBox(200)
Friend Sub New()
AutoScroll = True
Location = New Point(0, 100)
Size = New Size(200, 100)
Controls.Add(myTextBox1)
Controls.Add(myTextBox2)
Controls.Add(myTextBox3)
End Sub
Protected Overrides Sub OnLeave(ByVal e As EventArgs)
MyBase.OnLeave(e)
myTextBox1.Text = "false"
myTextBox2.Text = "false"
BackColor = Color.Green
End Sub
Protected Overrides Sub OnEnter(ByVal e As EventArgs)
myTextBox1.Text = "true"
myTextBox2.Text = "true"
BackColor = Color.Gold
MyBase.OnEnter(e)
End Sub
Protected Overrides Sub WndProc(ByRef m As Message)
If mouseNotify.Contains(CInt(m.Msg)) Then
If isOverControl(Me) Then Form1.WndProc(m)
End If
MyBase.WndProc(m)
End Sub
End Class
Friend Class customTextBox : Inherits TextBox
Friend Sub New(ByVal y As Integer)
Location = New Point(10, y)
Size = New Size(100, 30)
End Sub
Protected Overrides Sub OnLeave(ByVal e As EventArgs)
MyBase.OnLeave(e)
BackColor = Color.Blue
End Sub
Protected Overrides Sub OnEnter(ByVal e As EventArgs)
BackColor = Color.Red
MyBase.OnEnter(e)
End Sub
End Class
End Class
If it doesn't work in all cases, you may have to attach events to all the controls on your form that can't/won't receive focus on mouse events.
also, this works slightly differently depending on the type of control. richtextbox use OnHScroll and OnVscroll for example, instead of OnScroll. you can also get the thumb position with CInt(m.WParam.ToInt32 >> 16), only valid for SB_THUMBTRACK, SB_THUMBPOSITION.
also, here are some interesting techniques: Handling a click event anywhere inside a panel in C#
this was actually taken from the MSDN page for WndProc: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.wndproc%28v=vs.110%29.aspx
and the page for NativeWindow Class: http://msdn.microsoft.com/en-us/library/system.windows.forms.nativewindow.aspx

Related

How to make a user select an image and save the image as a variable?

I am trying to create a VB.net form where the user can click on a button and it is associated with a specific image and when the user clicks the image and then clicks select it will add it to a variable.
If you need more information please let me know (this is the image of my form)
I wanted to know:
how to assign an image to a button ( so when you click it, it means that the user wants that image) I am not sure if my method is correct
how to assign the image that was selected to a variable (so that once the variable is called it will output the image)
and how to end the form once the image is selected. (once use clicks the select button it should end the form, or if the user clicks cancel it should end the form).
Public Class Form1
Private Property SelectedPictureBox() As Image
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Controls.OfType(Of ButtonPictureBox).ToList().ForEach(
Sub(box)
AddHandler box.Click, AddressOf AllButton_Click
End Sub)
End Sub
Private Sub AllButton_Click(sender As Object, e As EventArgs)
SelectedPictureBox = CType(sender, ButtonPictureBox).PictureBox
End Sub
Private Sub GetBtnSelect_Click(sender As Object, e As EventArgs) Handles GetBtnSelect.Click
If SelectedPictureBox IsNot Nothing Then
MessageBox.Show(SelectedPictureBox.Name)
Else
MessageBox.Show("Please select an image")
End If
End Sub
Private Sub BtnTropicalFloral_Click(sender As Object, e As EventArgs) Handles BtnTropicalFloral.Click
SelectedPictureBox = PictureBoxTropicalFloral.Image
End Sub
Private Sub BtnLightGeode_Click(sender As Object, e As EventArgs) Handles BtnLightGeode.Click
SelectedPictureBox = PictureBoxLightGeode.Image
End Sub
Private Sub BtnStripes_Click(sender As Object, e As EventArgs) Handles BtnStripes.Click
SelectedPictureBox = PictureBoxStripes.Image
End Sub
Private Sub BtnAuroraBorealis_Click(sender As Object, e As EventArgs) Handles BtnAuroraBorealis.Click
SelectedPictureBox = PictureBoxAuroraBorealis.Image
End Sub
Private Sub BtnDiagonals_Click(sender As Object, e As EventArgs) Handles BtnDiagonals.Click
SelectedPictureBox = PictureBoxDiagonals.Image
End Sub
Private Sub BtnComb_Click(sender As Object, e As EventArgs) Handles BtnComb.Click
SelectedPictureBox = PictureBoxComb.Image
End Sub
Private Sub BtnMountain_Click(sender As Object, e As EventArgs) Handles BtnMountain.Click
SelectedPictureBox = PictureBoxMountain.Image
End Sub
Private Sub BtnLandscape_Click(sender As Object, e As EventArgs) Handles BtnLandscape.Click
SelectedPictureBox = PictureBoxLandscape.Image
End Sub
Private Sub BtnGradient_Click(sender As Object, e As EventArgs) Handles BtnGradient.Click
SelectedPictureBox = PictureBoxGradient.Image
End Sub
Private Sub BtnAbstract_Click(sender As Object, e As EventArgs) Handles BtnAbstract.Click
SelectedPictureBox = PictureBoxAbstract.Image
End Sub
Private Sub BtnGeode_Click(sender As Object, e As EventArgs) Handles BtnGeode.Click
SelectedPictureBox = PictureBoxGeode.Image
End Sub
End Class
My VB is a bit rusty, so I'll have to give the answer in C#. I'm sure you'll get the gist, and will be able to translate it into VB.
First of all: whenever you see that you are repeating things, for instance by copy-paste, you should stop, and rethink your design: maybe it would be better to create a method for this, or an object.
All your PictureBox/Button combinations have some common behavior. This means that you should think of creating a class for it.
In your case, you have the combination of a Button and a PictureBox. You want to be able to set and get an Image. The PictureBox will show this image. Finally you want to be notified if the operator clicks the Button.
In the event handler of this Notification you want to know which pictureBox/Button combination sent the event. You get the image from this combination and close the form.
In WinForms, whenever you want to have a class that is a combination of several controls, you make a UserControl.
In Visual Studio, in the solution control, right click on the project (not the solution!) and select: Add new Item. Select to add a new User Control. Think of a proper name, I'll call this ImageSelectionControl
Use the visual studio designer to give ImageSelectionControl the proper size. Add a PictureBox and a Button. Also use the visual studio designer to add an EventHandler for if the operator clicks the button.
In the code of the User Control add the property to Set / Get an Image. The Image that you set will be displayed in the PictureBox; the Image that you get is the image that is displayed in the PictureBox.
Here comes the first chunk of C#:
public Image Image
{
get => this.pictureBox1.Image;
set => this.pictureBox1.Image = value;
}
I think in VB this will be very similar.
Now you want that users of your control (= software, not humanoids) get notified that the operator selects an image. Officially, you even want to hide how the operator selected this image: all you want to say: "Hey, the operator selected my image!"
Normally you would do this using an event:
The 2nd piece of C#:
public event EventHandler ImageSelected;
The event won't have any data. It will only say: "Hey, the operator selected my image!". The event event handler will have to find out which user control raised the event, and fetch the image.
Ok, raise the event:
private void OnImageSelected()
{
this.ImageSelected?.Invoke(this, EventArgs.Empty);
}
It will be a bit more difficult to translate this into VB. What it does, it checks if there is at least one person who wants my events. If so it raises the event. with two parameters: the sender (which is me), and no parameters. Later we will see how the receiver of the event works.
Finally: if the operator clicks the button, he indicates that he wants to select the image in the user control, and thus OnImageSelected needs to be called
private void ButtonSelect_Clicked(object sender, EventArgs e)
{
this.OnImageSelected();
}
We've finished creating the UserControl. After Compilation you will find it in visual studio designer toolbox.
So we'll go to the form that will have to display the eleven PictureBox-Button combinations. Let's call this form: ImageSelectionForm.
Using Visual Studio Designer, add 11 ImageSelectionControls. If you know already at design time which control will show which image, you can do this in the designer, similarly to how you set the text or the background of a button.
If you only know at run-time which control should show which image, consider to add a method, for instance if you want to load it from file:
void ShowImage(ImageSelectionControl imageSelectionControl, string imageFileName)
{
Image image = this.LoadImageFromFile(imageFileName);
this.imageSelectionControl.Image = image;
}
Or maybe you have a different method to decide which ImageSelectionControl should displaye which image. I guess you get the gist.
Almost done. ImageSelectionForm needs to be notified about the selected image, so just like you would do with a button, you need to subscribe to event ImageSelected.
In the constructor or ImageSelectionForm, subscribe to the events:
private ImageSelectionForm()
{
InitializeComponent();
// subscribe to events
this.controlBlueGeod.ImageSelected += this.ImageSelected;
this.controlAbstract.ImageSelected += this.ImageSelected;
...
}
Of course, you can put all ImageSelectionControls in one list and use foreach to subscribe (that is too much VB for me, no idea how to do this)
The event handler:
void ImageSelected(object sender, EventArgs e)
{
// we know that the sender is the one that holds the selected images:
ImageSelectionControl imageSelectionControl = (ImageSelectionControl)sender;
We will be closiing the form very soon, so we will have to remember this selected image somewhere in a property:
public Image SelectedImage {get; set;}
So continuing the event handler:
this.SelectedImage = imageSelectionControl.Image;
this.DialogResult = DialogResult.OK;
this.Close();
}
So the selected image is saved. The dialog result is set to indicate that an image was selected, not cancel clicked. And the form is closed.
Showing the form and process the selected image
The form that has to show ImageSelectionForm has a procedure:
private void ShowImageSelectionForm()
{
using (ImageSelectionForm dialog = new ImageSelectionForm())
{
// show the dialog and process the result:
DialogResult dlgResult = dialog.ShowDialog(this);
if (dlgResult == DialogResult.OK)
{
this.ProcessSelectedImage(dialog.SelectedImage);
}
else
{
// TODO: process cancel
}
}
}
There is one memory leak: if you created a lot of images, all images need to be Disposed after usage. Best is to by overriding Component.Dispos(bool)
ImageSelectionControl:
protected override Dispose (bool disposing)
{
if (disposing && this.Image != null)
{
this.Image.Dispose();
}
}
ImageSelectionForm:
protected override Dispose (bool disposing)
{
if (disposing)
{
this.controlBlueGeod.Dispose();
this.controlAbstract.Dispose();
...
} ​
​}
This is quite a nuisance for 11 controls. Therefore quite often a Form or a UserControl has a System.ComponentModel.IContainer components. If you add your ImageSelectionControls to this container, then the ImageSelectionControls will be automatically disposed when ImageSelectionForm is disposed.
​
You have two Controls that work together to allow users to preview and select one or more Images in the UI. When you have this kind of scenario, build a UserControl that contains all the required UI elements and the logic used perform this action.
To build this UserControl:
Open the Project menu and select Add User Control...
Right away, set (in this order):
AutoScaleMode = Dpi
Font = Segoe UI, 9pt
BackColor = Color.Transparent
Set a Size that you think is the minimum required to show an Image and a Button
When you have found the right size, set also the MinimumSize to this value
Add a Button to the UC, configure it as needed, set its Width as the Width of the UC minus 4 pixels. Position the Button at the bottom of UC, 2 pixels to the left and set Anchor = Bottom, Left, Right
Add a PictureBox, same Width and Left location as the Button. Set the Height as required, then Anchor = Top, Bottom, Left, Right
Design completed. Build the Project.
Now, your UserControl needs to provide means to set an Image to the PictureBox and the Text of the Button.
You can add two Public Properties of Type Image and String that, when a value is assigned, set the PicureBox.Image property and the Button.Text property.
Also, when the Button is clicked, the UserControl needs to notify that the User has performed a selection, so whatever other code needs to do something with this information, will be able to act on it.
In an event-driven UI, you make your UC raise a public event that interested parties can subscribed to, to receive a notification that something happened.
You just need to define a Field of Type Event and give it a name. In this case, e.g.:
Public Event ImageSelection As EventHandler
When the Button is clicked, you raise the event:
RaiseEvent ImageSelection(Me, EventArgs.Empty)
The sample UserControl is named ImagePicker, the PictureBox is named picImage and the Button is btnSelectImage
Public Class ImagePicker
Public Event ImageSelection As EventHandler
Private m_Picture As Image = Nothing
Private m_Title As String
Public Property Picture As Image
Get
Return m_Picture
End Get
Set
m_Picture = Value
picImage.Image = m_Picture
End Set
End Property
Public Property Title As String
Get
Return m_Title
End Get
Set
m_Title = Value
btnSelectImage.Text = m_Title
End Set
End Property
Private Sub btnSelectImage_Click(sender As Object, e As EventArgs) Handles btnSelectImage.Click
RaiseEvent ImageSelection(Me, EventArgs.Empty)
End Sub
End Sub
In your Form (for example), you can the subscribe to this event to receive a notification that the User has selected the Image of one of your UserControls.
When the event is raised, the sender object is the UserControl that raised the event. You can then cast sender to your UserControl Type and read the Public Property that references the Image you have assigned to it.
In a Form, you can add some of your UserControls to a FlowLayoutPanel (in the example, named flpPreviews), which will take care of the layout of these Controls.
While adding the UserControls, you set their Public Properties and also subscribe to the Public event.
When the event is raised, cast sender to ImagePicker and read its public Picture property to get the reference of the Image selected:
Public Class SomeForm
Public Sub New()
InitializeComponent()
' Add three ImagePicker UserControls to a FlowLayoutPanel
For i As Integer = 0 To 2
Dim picker = New ImagePicker()
picker.Picture = [Some Image]
picker.Title = "Some Title"
' Subscribe to the event
AddHandler picker.ImageSelection, AddressOf ImageSelectionChanged
flpPreviews.Controls.Add(picker)
Next
End Sub
Private Property SelectedImage As Image
Private Sub ImageSelectionChanged(sender As Object, e As EventArgs)
SelectedImage = DirectCast(sender, ImagePicker).Picture
' Show the selected Image in a PictureBox, child of the Form
picSelected.Image = SelectedImage
End Sub
End Class

Block focus/select in a ReadOnly textbox

Someone knows how to block the focus/select in a read-only textbox (ReadOnly = true), without using enabled = false?
Thanks!
Controls have a GotFocus Event. You can add an event handler for this event and give another control focus, for example by calling Select() on another control or by using SelectNextControl:
Private Sub MyTextBox_GotFocus(sender as Object, e as EventArgs) _
Handles MyTextBox.GotFocus
MyTextBox.Parent.SelectNextControl(MyTextBox, True, True, True, True)
End Sub
Alternately, you can create a custom control that inherits TextBox and set ControlStyles.Selectable to False.
Public Class NonSelectableTextBox Inherits TextBox
Public Sub New()
SetStyle(ControlStyles.Selectable, false)
End Sub
End Class
Setting ControlStyles.Selectable to false will make the TextBox mimic the behavior of other controls which have this bit set to False:
Label
Panel
GroupBox
PictureBox
ProgressBar
Splitter
LinkLabel (when there is no link present in the control)
I'm not sure I understand fully why you would want that. A read only text box allows selection to allow users to copy the text in there for other purposes. What I assume from your question is that you don't want the TextBox to accept input focus when a user is tabbing through controls, which I've seen to be a more common requirement.
You can achieve this via code:
TextBox1.TabStop = False
to ensure that tab doesn't direct focus to the readonly textbox. You can also achieve this in the designer using the same property as the screenshot shows.

how do I make the click of any picturebox within a class call a subprocedure

I'm making monopoly and I've made a class with all the information about each tile (picturebox, name, owner, price...)
how do I get a subroutine so that if I click on any tile, it will bring up a menu asking whether to buy/sell houses and stuff
The main thing I need to know is how to make it happen under any property clicked and how to tell which particular one was clicked without the need for lots of code
Note: I'm new to windows forms (2 days), so I may not understand advanced stuff
You can define a click event in the tile class. Internally this click event would be raised by the picturebox' click event handler. The main program can register an event handler for all tiles' click event:
Class Tile
'Define the signature of the event
Public Delegate Sub TileClickHandler(sender As Tile)
'The UI control of this tile
Dim Container As PictureBox
'The event is raised whenever the tile is clicked
Public Event Click As TileClickHandler
Public Sub New()
'Register a private event handler for the UI control's click event
AddHandler Container.Click, AddressOf Container_Click
End Sub
Private Sub Container_Click(sender As Object, e As EventArgs)
'The UI control has been clicked, raise my own Click event
RaiseEvent Click(Me)
End Sub
End Class
'Main Program
Dim tiles = New List(Of Tile)
'...
For Each t In tiles
AddHandler t.Click, AddressOf TileClicked
Next
Private Sub TileClicked(sender As Tile)
MessageBox.Show("Tile " & sender.ToString() & " has been clicked.")
End Sub

How can I place/drop an image evertime you click the mouse button using vb.net?

I looked at "How do I place an image with a mouse-click in Javascript?" but it had a small snippet of Java; immensely larger than my knowledge of Java. And that is the closest I've come to finding an answer in the past week.
Here's what I would like to do (don't know if its even possible):
I have a panel and a toolstrip with 3 buttons. Each button represents a different image. I want to click on a button (once) and then move into the panel and everytime I click the mouse button it drops the image where ever I clicked. This only ends when either I click back on the same button or one of the other buttons. I do not want to drag an image into the panel each time. In other words the button stays depressed and the event/action stays active.
Any help would be greatly appreciated.
Here is an example application. It's just a form with a ToolStrip on it, along with a couple of buttons with an image added to each button. The key property for each button is CheckOnClick=True, which will keep the button pressed down.
There isn't a radio button like feature for ToolStrips, so you have to "uncheck" the other ToolStripButtons yourself, which I have handled in the ItemClicked event.
Public Class Form1
Private _ActiveImage As Image = Nothing
Private Class ImagePoint
Public Location As Point
Public Image As Image
Public Sub New(ByVal image As Image, ByVal location As Point)
Me.Image = image
Me.Location = location
End Sub
End Class
Private _Images As New List(Of ImagePoint)
Public Sub New()
InitializeComponent()
Me.DoubleBuffered = True
End Sub
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles MyBase.Paint
For Each imageItem As ImagePoint In _Images
e.Graphics.DrawImage(imageItem.Image, imageItem.Location)
Next
End Sub
Private Sub ToolStrip1_ItemClicked(ByVal sender As Object, ByVal e As ToolStripItemClickedEventArgs) Handles ToolStrip1.ItemClicked
For Each toolButton As ToolStripButton In ToolStrip1.Items.OfType(Of ToolStripButton)()
If toolButton.CheckOnClick Then
If e.ClickedItem.Equals(toolButton) Then
_ActiveImage = e.ClickedItem.Image
Else
toolButton.Checked = False
End If
End If
Next
End Sub
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseDown
If _ActiveImage IsNot Nothing AndAlso e.Button = MouseButtons.Left Then
_Images.Add(New ImagePoint(_ActiveImage, e.Location))
Me.Invalidate()
End If
End Sub
End Class
This example just uses a simple class to hold which image was placed at what location and the paint event just loops through the list and paints the image.
If deleting images is in your future, then you would have to call e.Graphics.Clear(Color.White) before painting any images.
For the button UI, check out the alternate style for radio buttons/check boxes. They have a "toggle button" mode which sounds like exactly what you need.
You could go through the motions of detecting mouse down events on the panel, getting the coordinates, creating an image control, and placing a copy of the image in it, but there's a better approach.
Fill the panel with a single image control (fill so that it handles resizes, the image control should always be the same size as the panel). Create a new Bitmap the same size as the image control and associate it with it (set the Image property). Obtain a Graphics object for the Bitmap (Graphics.FromImage() I think). Clear() it with the background color (Color.White?).
Preload your three images on startup and write the code to toggle between them, selecting the "active one" every time a different button is selected. On the mouse down event, you can get the coordinates of the click easily. Use myGraphics.DrawImage(...) to draw the active image at that location onto the Bitmap. You can then save the Bitmap to a file or do whatever you want with it. All of these concepts have lots of examples, Google them.
If you want to interact with the images after you "drop" them (like move them around again or something), then you will need to maintain a data structure that tracks what and where you've dropped. A simple class that has a Point and Image reference will be sufficient. Each drop should add an entry to a List(Of ...) these objects. You'll probably then need to write code such as "which image is under the current mouse location?". This can be accomplished by iterating through the list and doing point/rectangle intersection testing.
Private Sub ToolStripSound_Click(sender As Object, e As EventArgs) Handles ToolStripSound.Click
If ToolStripSound.Checked = False Then
ToolStripSound.Checked = True
Else
ToolStripSound.Checked = False
End If
End Sub
Private Sub ToolStripSound_CheckedChanged(sender As Object, e As EventArgs) Handles ToolStripSound.CheckedChanged
' ToolStripSound.Checked = True
If ToolStripSound.Checked = True Then
Me.ToolStripSound.Image = Global.Traffic_Lights.My.Resources.Resources.Oxygen_Icons_org_Oxygen_Status_audio_volume_high
Else
Me.ToolStripSound.Image = Global.Traffic_Lights.My.Resources.Resources.Oxygen_Icons_org_Oxygen_Status_audio_volume_muted
End If
End Sub

Select the content of textbox when it receives focus

I have found a similar question to mine in Making a WinForms TextBox behave like your browser's address bar
Now i am trying to modify or make it some more different by making it general. I want to apply same action to all the textboxes in form without write code for each one... how many i dun know. As soon as i add a textbox in my form it should behave with similar action of selecting.
So wondering how to do it?
The following code inherits from TextBox and implements the code you mentioned in Making a WinForms TextBox behave like your browser's address bar.
Once you've added the MyTextBox class to your project you can do a global search for System.Windows.Forms.Text and replace with MyTextBox.
The advantage of using this class is you can't forget to wire all the events for every textbox. Also if you decide on another tweak for all textboxes you have one place to add the feature.
Imports System
Imports System.Windows.Forms
Public Class MyTextBox
Inherits TextBox
Private alreadyFocused As Boolean
Protected Overrides Sub OnLeave(ByVal e As EventArgs)
MyBase.OnLeave(e)
Me.alreadyFocused = False
End Sub
Protected Overrides Sub OnGotFocus(ByVal e As EventArgs)
MyBase.OnGotFocus(e)
' Select all text only if the mouse isn't down.
' This makes tabbing to the textbox give focus.
If MouseButtons = MouseButtons.None Then
Me.SelectAll()
Me.alreadyFocused = True
End If
End Sub
Protected Overrides Sub OnMouseUp(ByVal mevent As MouseEventArgs)
MyBase.OnMouseUp(mevent)
' Web browsers like Google Chrome select the text on mouse up.
' They only do it if the textbox isn't already focused,
' and if the user hasn't selected all text.
If Not Me.alreadyFocused AndAlso Me.SelectionLength = 0 Then
Me.alreadyFocused = True
Me.SelectAll()
End If
End Sub
End Class
Assuming you're going to use the accepted solution from the question you link to, all you'd need to do would be that whenever you create a new textbox, you use AddHandler to add the same 3 eventhandlers to each new textbox.
Then you need to change the event handlers to instead of referencing the textbox as this.textBox1 they'll reference it as CType(sender, TextBox) which means that they'll use the textbox that generated the event.
Edit: I'll add that line of code here as well since it's easier to read then
Private Sub TextBox_GotFocus (ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.GotFocus, TextBox2.GotFocus, TextBox3.GotFocus
We use this custom textbox control:
Public Class TextBoxX
Inherits System.Windows.Forms.TextBox
Private Sub TextBoxX_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
SelectAll()
End Sub
end class
You can see the full project of our TextBox (on steroids) on GitHub https://github.com/logico-dev/TextBoxX