Filling a SplitContainer with a TreeView while Dock is set to Fill - vb.net

If I have a new project with a User Control and a MDI with a 2 window Split Container. One on the left an done on the right. Then If I create a new User Control as follows
Public Class
Private Sub TreeView()
Dim pbTreeView As Forms.TreeView
pbTreeView = New Forms.TreeView()
Me.Controls.Add(pbTreeView)
pbTreeView.Nodes.Clear()
Dim root = New TreeNode("Price Book")
pbTreeView.Nodes.Add(root)
pbTreeView.Nodes(0).Nodes.Add(New TreeNode("Settings"))
pbTreeView.Nodes(0).Nodes.Add(New TreeNode("Sales"))
pbTreeView.Nodes(0).Nodes.Add(New TreeNode("Pricing"))
End Sub
End Class
Private Sub TreeViewControl_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TreeView()
End Sub
I put this User Control in the Left panel of the split container and set the dock to Fill. When I run it. the dock itself is filled properly. but the border and the actual TreeView is NOT made to fit the entirety of the UC in the left container. How can I go about fitting it in there. With the actual data, it will be long enough to even need a horizontal scroll while the data from the selected node will populate the right panel of the spit container(haven't tackled this bit yet).

Related

How do you set a dynamically created panel to false in VB.net?

I have on my screen design Panel1(left half), and panel2 through 10(right half), the panels on the right half are named based on data from a database.
I need to be able to click on a button in panel1 and when I do so, I need to set visibility to false for the current panel on the right half and set visibility to true that is referenced from the button click. I know that I can do the following but I think this is just way too much overhead and there has to be a better solution than this:
For Each control In Me.Controls.OfType(Of Panel)
If control.visible = true Then
control.visible = false
exit
Next
Panel that the visibility that needs to be set to false was dynamically created so it can not just be accessed by just name, otherwise that would solve my issue easily.
I seen this bit of code elsewhere and it would make my life easier, however not sure how to implement it dynamically when the panels are created, since the name of the panels are unknown at creation.
This bit of code to be able to reference the panels directly.
Dim machinePanel As Panel = DirectCast(Me.Controls.Item("pnl" & strMTB & strMachineID), Panel)
I'm not sure what you mean but "is referenced from the button click", so I'll assume that the text of the button refers to the panel name.
Create a method that handles the visibility
Private Sub SetPanelVisibility(button As Button)
'panel that the button is in
Dim leftPanel = CType(button.Parent, Panel)
'get right panels and ignore left
Dim rightpanels = Me.Controls.OfType(Of Panel).Where(Function(x) x.Name <> leftPanel.Name)
'set visibility of each panel.
For Each panel In rightpanels
panel.Visible = panel.Name = button.Text
Next
End Sub
To call the method just pass the button in on the click event. e.g.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
SetPanelVisibility(sender)
End Sub

How to create any one dynamic controls with a for loop without using location property and the form should grow automatically

How to create multiple button controls with a for loop without getting the controls overlapped and without using location property in Vb.Net.
I have created 'n' number of vb controls dynamically but the created controls are getting overlapped to each other. When I use location property to each controls all the controls are getting displayed as per the location value.
The real problem is, I'm using a panel of width 300 and height 300, under that I need to display the dynamically created controls. I have figured it out which is tedious work and does take a lot of time. My idea is to find the panel width and height then need to check whether the new control which is getting created has ample of space to fit inside the panel.
I need to know few things,
1) How to display the controls dynamically using for loop without getting overlapped over each other and without using location property.
2) I need the container or the panel to grow as per the number of controls which gets created dynamically.
3) Accessing each controls which got displayed using an ID or educate or explain me any better idea.
I created a new WinForms project and added a Button to the top of the form. I added a FlowLayoutPanel under that and made it narrow enough to fit a single Button widthwise. I set the AutoSize property of the FLP to True and the FlowDirection to TopDown. I then added this code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Create the new Button.
Dim btn As New Button
'Add it to the FLP
FlowLayoutPanel1.Controls.Add(btn)
'Get the position of the bottom, left of the Button relative to the form.
Dim pt = PointToClient(btn.PointToScreen(New Point(0, btn.Height)))
'Resize the form to provide clearance below the new Button.
ClientSize = New Size(ClientSize.Width, pt.Y + 10)
End Sub
I then ran the project and started clicking the Button I added. As expected, each click added a new Button to the FLP in a vertical column and the form resized to fit. In order to access such controls in code, you can simply index the Controls collection of the FLP.
try this helps you.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
'Do Something
Else
'Do Something else
End If
Panel1.Controls.Clear()
For i As Integer = 0 To 10 Step 1
Dim b15 As New Button
b15.Text = "Test3"
b15.ID = "a" & i
AddHandler b15.Click, AddressOf updateFunc
Panel1.Controls.Add(b15)
Next
End Sub

Show dragged item while dragging vb.net

I'm wanting to show the dragged control while dragging in my form. I have a list of controls (textboxes and a picturebox) which are draggable. I would like to show the dragged control all the time, as long as the control is being dragged, even if the user cannot drop it. I also have an issue with dragging the picture box. It shows a dragged image of the control, however it flickers.
Code for drag feedback for picture box
Private Sub qrCode_GiveFeedback(ByVal sender As Object, ByVal e As GiveFeedbackEventArgs) Handles QRCodeDrag.GiveFeedback
Dim bitmap As Bitmap
bitmap = New Bitmap(QRCodeDrag.Width, QRCodeDrag.Height)
QRCodeDrag.DrawToBitmap(bitmap, New Rectangle(Point.Empty, bitmap.Size))
'bitmap.MakeTransparent(Color.White)
Dim cursor As New Cursor(bitmap.GetHicon)
Cursor.Current = cursor
End Sub
Any ideas?
I forgot to add
e.UseDefaultCursors = False
This solved the issue of the flicker

Darken a .Net Form

I have a 1080p touchscreen application. When a modal pops up, i want to emphasize that by darkening the main form.
Right now i use a second form, the size of the main form, that is black and has 50% opacity. Whenever a modal needs to appear, i open the opaque form, and then open the desired modal.
I feel this is a bit devious for my purpose. Its also not asshole-proof that when the user alt tabs, the forms will glitch out of sequence.
Is there a better way to achieve the darkening effect. Perhaps by darkening the main form from within itself?
Solved it myself by doing the following:
Place a hidden picturebox with dock:fill on the main form,
Take a screenshot of the current screen and darken it
assign the image to the picturebox and make it visible
open the modal in a new win
when the modal is dismissed
hide the picturebox
It really stupid that VB.net doesn't have this function built into it. Here's what you do to get around it:
Make a new form and call it Shade. I'm going to assume your main form is called frmMain. For the sake of clarity, lets assume the form you're launching is called dlgX.
Add the following lines in the Load event of dlgX (that's the sub with dlgX.Load or Me.Load or MyBase.Load):
Shade.Opacity = 0.001
Shade.Show()
Shade.Location = frmMain.Location ' Form location will only update if the form is visible.
Shade.Hide()
Shade.FormBorderStyle = Windows.Forms.FormBorderStyle.None 'This gets rid of the windows Titlebar and window border.
Shade.Size = frmMain.Size
Shade.BackColor = Color.Black
Shade.Opacity = 0.5
Shade.Show() ' Form size will only update the next time you show it.
Shade.TopMost = True ' Puts Shade over main form
Me.TopMost = True ' Puts current form over shade
Under all events that dismiss the form dlgX (OK.click, Cancel.click, etc), add the following lines:
Shade.Close
Or you can even make your own sub that handles all events where the form is closed:
Private Sub DispelShades(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.FormClosed
Shade.Close()
End Sub
This is way simpler than the PictureBox scenario and you don't have to mess with layering issues and having to ensure that the PictureBox renders on top of everything (for example, tabs really do not like having things rendered above them and they will not let you render a picture box above them). Rendering a black semi transparent form above your main form gets around all these headaches.
If you have multiple forms to shade, just make a Shad1, Shade2, Shade3 etc.
This is pretty obvious but it's worth stating: if you're shading the main form, you'll also want to make it unclickable by opening dlgX via dlgX.ShowDialog and not dlgX.Show
Here is some code, very similar to the method in Thomas's answer. Note to use the Darkness property in a Try...Finally block, to make sure you never leave the form in the dark state.
Public Class Form1
Private _PB As PictureBox
Public WriteOnly Property Darkness
Set(value)
If value Then
Dim Bmp = New Bitmap(Bounds.Size.Width, Bounds.Size.Height)
Me.DrawToBitmap(Bmp, New Rectangle(Point.Empty, Bounds.Size))
Using g = Graphics.FromImage(Bmp)
Dim Brush As New SolidBrush(Color.FromArgb(125, Color.Black))
g.FillRectangle(Brush, New Rectangle(Point.Empty, Bmp.Size))
End Using
_PB = New PictureBox
Me.Controls.Add(_PB)
_PB.Size = Bounds.Size
_PB.Location = Bounds.Location - PointToScreen(Point.Empty)
_PB.Image = Bmp
_PB.BringToFront()
Else
If _PB IsNot Nothing Then
Me.Controls.Remove(_PB)
_PB.Dispose()
End If
End If
End Set
End Property
Private Sub btnDialog_Click(sender As Object, e As EventArgs) Handles btnDialog.Click
Try
Darkness = True
MsgBox("Modal dialog")
Finally
Darkness = False
End Try
End Sub
End Class

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