How do you show a panel in VB dot net, if all the panels are created dynamically and sit in the exact same spot? - vb.net

I am using Visual Studio 2022 and my language of choice is VB. When the program starts it creates Multiple Panels that are located in the same position created from data from a database.
No matter what I do, I can not get any of the panels to show. I can search for the panels and verify the panels exist, I can search the panels and verify that there are buttons in the panels. However I can not get each individual panel to show.
I am going to list all the panels that are created in the order they are created and they are all in the exact same position and size.
panel2
pnlDeptItems01
pnlDeptItems11
pnlDeptItems22
pnlDeptItems23
pnlDeptItems24
pnlDeptItems25
pnlDeptItems26
pnlDeptItems27
pnlDeptItems28
pnlDeptItems29
pnlDeptItems32
pnlDeptItems54
pnlDeptItems82
pnlDeptItems83
pnlDeptItems84
pnlDeptItems85
pnlDeptItems96
pnlDeptItems97
pnlDeptItems98
pnlDeptItems99
Visible and Enabled are set to true for all panels on creation.
Below is the code that I use to search for the panel by name and if I find it then try to make it visible which it already is and then I try to bring it to front. And it does absolutely nothing but keeps the 1st panel visible.
For Each control In Me.Controls.OfType(Of Panel)
If control.Name = btnPanelName Then
control.Controls.Add(oButton)
control.Visible = True
control.BringToFront()
Console.WriteLine(control.Name & " " & oButton.Name)
End If
Next
CODE TO CREATE PANELS
Private Sub CreateNewPanel(ByRef pnlName As String, ByRef pnltopx As Integer, ByRef pnlLefty As Integer, ByRef pnlSizex As Integer, ByRef pnlSizey As Integer)
Dim iPanel As Panel
iPanel = New Panel
iPanel.Name = pnlName
iPanel.Enabled = True
iPanel.Visible = False
iPanel.Top = pnltopx
iPanel.Left = pnlLefty
iPanel.Size = New Size(pnlSizex, pnlSizey)
iPanel.AutoScroll = True
Me.Controls.Add(iPanel)
If iPanel.Name = "pnlDepartments" Or iPanel.Name = "pnlDeptItems26" Then
iPanel.Visible = True
iPanel.BringToFront()
End If
End Sub
I then tried doing this and this does not work either:
For Each control In Me.Controls.OfType(Of Panel)
If control.Name = btnPanelName Then
control.Controls.Add(oButton)
End If
If control.Name = "pnlDeptItems26" Then
control.Visible = True
End If
Next
Code that is called to create the panels
CreateNewPanel("pnlDeptItems" & dataDeptId, 608, 5, 429, 479)
dataDeptId is pulled from a database in a loop.
Can someone explain to me why this is not working or what the work around is? I know it has something to do with all the panels that are created being created in the exact same position.
Thanks,
Shawn Mulligan

I found the solution. After reading my post I took notice that for some reason that my paneltopx and my panellefty were reversed and too large for some reason as well as my panelsizey and panelsizex.
I made the adjustments and made sure that all panels visibility was set to false, and now when I set visibility to true, the correct panel displays with the buttons that I created.
Thanks,
Shawn Mulligan

Related

How does Tab Index work if the control's enabled property is false

If I'm viewing a form and I set the enabled property of the control with tab index = 0, does the cursor then move to the next tab index? Do I need to, and is there a way, to force the tab to set to the first control with Enabled = True?
So in order to achieve this (assuming there are no panels on your form), this is how you could iterate through the controls in tab order. The first control which you encounter and which is enabled, you set the focus on it and leave the Sub. The myFirstControl variable is initialized by you with the first control in the tab order list of the form.
Private Sub IterateControls()
Dim ctrl As Control = myFirstControl
While ctrl IsNot Nothing
If ctrl.Enabled = True Then
Me.ActiveControl = ctrl
Exit Sub
End If
ctrl = Me.GetNextControl(ctrl, True)
End While
End Sub
If you have panels also, you should build a dictionary of panels (with the panel as key, its first control as value) and take them one by one using a For loop. The For loop should be placed to include the whole method's code, but this time you initiate the ctrl variable with the first control from the panel (i.e. the value of the current dictionary entry), instead of the first control of the Form, and also you would call myPanel.GetNextControl(...) instead of Me.GetNextControl(...). The other code lines should remain the same. If this is not helpful enough, add a comment and I will edit my answer.

Control Tip Text on dual monitors?

I have a small user community for an application that contains a lot of user forms and fields.
I have added ControlTipText on most of the fields as helper/reminder.
The problem occurs when the user form is opened/displayed on the secondary monitor, the yellow stuff
(ControlTipText) is popping up on the right edge of the primary monitor.
Not a huge issue, but annoying.
Anyone who has a fix for this?
Same issue, resolved by:
Creating a label with a distinctive background colour positioned over the control that you want to write tip text for
Initialise the UF with the label visible = false, e.g. Userform1.label1.visible = false
use the "mousemove" event to write code to show the label
Private Sub TextBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
label1.visible = true
'position label as desired
End Sub
use the click or mousemove event on the label this time to banish the tool tip. You will have lots of labels over controls in the VB editor.
As an alternative I creatie a label with an "Information" icon that is clickable to unhide the tooltip label rather than mousemove event sometimes
As ControlTipText is a property of the Text Box it doesn't have any members which would allow you to adjust it's position.
It seems like the only way the issue can be resolved is by viewing Excel on your primary monitor. If it's useful, you can force Excel to move to the primary monitor with something like this:
With Application
.WindowState = xlNormal
.Left = 0
.Top = 0
.WindowState = xlMaximized
End With

How to get Winforms Panel to correctly layout many items?

I've got a WinForms Panel control which holds a large number of child controls. Each child is left docked, causing the horizontal width of the contents to grow. The containing Panel has its AutoScroll property set so that you can get to all the contents.
I'm running into a problem when the total width of the contents gets too large. Once you've hit this maximum width, additional content elements are placed on top of existing contents instead of being placed to the right. But, if I resize the Panel after it has done its initial layout, it corrects itself by expanding its logical width and placing each content element in the correct location. How do I get it to layout correctly before the user resizes the window?
Here's a simple example:
Form1.vb
Public Class Form1
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
For i As Integer = 1 To 200
Dim gb As New GroupBox
gb.Text = "Box " & i.ToString
gb.Width = 250
gb.Dock = DockStyle.Left
Panel1.Controls.Add(gb)
gb.BringToFront()
Next
End Sub
End Class
Form1.Designer.vb
Partial Class Form1
Inherits System.Windows.Forms.Form
Private Sub InitializeComponent()
Me.Panel1 = New System.Windows.Forms.Panel()
Me.SuspendLayout()
'
'Panel1
'
Me.Panel1.AutoScroll = True
Me.Panel1.Dock = System.Windows.Forms.DockStyle.Fill
Me.Panel1.Location = New System.Drawing.Point(0, 0)
Me.Panel1.Name = "Panel1"
Me.Panel1.Size = New System.Drawing.Size(284, 262)
Me.Panel1.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(284, 262)
Me.Controls.Add(Me.Panel1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
Friend WithEvents Panel1 As System.Windows.Forms.Panel
End Class
This is what the window looks like when it first comes up, scrolled nearly to the end so you can see the problem area. Notice that Box 183 to 199 are missing because they are placed on top of each other. This is not right.
This is what the window looks like after you manually resize it, scrolled nearly to the end. The panel fixed itself in response to the resize; the total logical width of the panel was automatically extended enough to hold all the contents. This is what I want it to look like when it first comes up.
I've tried manually setting the location of each box, and I've tried calling PerformLayout() and several other functions. Nothing seems to work. So far I haven't found the magic combination to get the good layout. Does anyone know how to fix this?
Edit:
Here's a screenshot that might make the issue more obvious. I adjusted the box widths and the number of boxes to show the problem better. See how the last box overlaps box 656? Every box from 657 to 700 has the same incorrect location. Turning off docking and setting the location myself doesn't help.
Looks like a bug with the scrolling information. If you call PerformLayout when the Panel is scrolled all the way to the right, it correctly places the controls in the proper place. That requires some code in the OnShown method:
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
Panel1.AutoScroll = True
Panel1.SuspendLayout()
For i As Integer = 1 To 200
Dim gb As New GroupBox
gb.Text = "Box " & i.ToString
gb.Width = 250
gb.Dock = DockStyle.Left
Panel1.Controls.Add(gb)
gb.BringToFront()
Next
Panel1.ResumeLayout(False)
End Sub
Protected Overrides Sub OnShown(e As EventArgs)
MyBase.OnShown(e)
Panel1.AutoScrollPosition = New Point(Panel1.HorizontalScroll.Maximum - _
Panel1.HorizontalScroll.LargeChange, 0)
Panel1.PerformLayout()
Panel1.AutoScrollPosition = Point.Empty
End Sub
Of course, having over 200 container controls on the form is never recommended.
AutoScroll is not AutoPositionMyChildren. From MSDN:
When adding controls programmatically to a form, use the AutoScrollPosition property to position the control either inside or outside of the current viewable scroll area.
If you looped thru the controls, to print their location, you's see at some point (probably around 130) that Location.Y becomes fixed at 32767 probably some default unscrolled max. This is also the point they start stacking because they in fact have the same initial location. Some of the code you have makes up for that but it isnt quite right. Once you scroll it, the panel fixes the coords on the child controls.
First, I would suggest that you set Panel1.AutoScrollMinSize to something like {480, 0} so that the HScroll bar appears at design time; this allows you to calc a good height for the boxes which wont cause a VScroll as you add controls.
Dim gb As GroupBox
' only 150 because problem is when (i * width) > 32k
For i As Integer = 0 To 150
gb = New GroupBox
gb.Name = i.ToString ' added
gb.Text = "Box " & i.ToString
gb.Width = 250
' no docking so set the height
gb.Height = Panel1.Bounds.Height - 30 ' trying to avoid the VSCroll
' set location explicitly
gb.Location = NewCtlLocation(Panel1.Controls.Count,
Panel1.AutoScrollPosition.X)
' Dock and Anchor mess up the AutoScroll
'gb.Dock = DockStyle.Left
Panel1.Controls.Add(gb)
' allow panel to update its scroll positions
Panel1.ScrollControlIntoView(gb)
' not needed; seems to offset something with Dock
' changing ZOrder may not always be desirable
'gb.BringToFront()
' debug illumination
Console.WriteLine("{0} {1} {2}", i.ToString,
Panel1.AutoScrollPosition.X.ToString,
gb.Location.X.ToString)
Next
'Go back to start
Panel1.ScrollControlIntoView(Panel1.Controls("0"))
Location helper so you can tweak gutters or margins (dock replacement):
Friend Function NewCtlLocation(ByVal n As Integer,
ByVal ScrollPosX As Integer) As Point
Const TopMargin As Integer = 5
Const LeftMargin As Integer = 5
Return New Point((n * 250) + ScrollPosX, 0)
End Function
Notes:
I have a vertical scroller which repeatedly adds up to 120 user controls which works well but it does not need/use ScrollControlIntoView and they never stack up like yours do. I suspect maybe because they are smaller. There is also at least a second or two before the next one can be added, which may matter. But, good to know.
It might be possible to use the ControlAdded event of the panel to do something, but it would likely amount to ScrollControlIntoView. Doing it once at the end only doesnt work, so using it as they are added is allowing something to get updated as you go.
With the right fiddling, you might be able to get Dock to work, but I suspect it may be part of the problem such as Height and Left set this way dont update the panel's internal scroll map.
Your boxes actually look narrower than 250 - is autosize on?
Suspend/Resume Layout hurt rather than help - they prevent the control from doing anything about the virtual area being populated. It should happen fast enough that no one will see anything. Results:
Works on My SystemTM

Reversi VB.net logic behind it

I am trying to make the reversi game in VB.Net. I have some difficulties translating the game`s logic into vb.net
If a button is black and the button next to it is white,than the button next to the white one will be black wen pressed.
newButton.tag = colum of button + (row of button * amount of columns)
-> I made 64 buttons via a function loop and added a tag
Dim knop As Button = sender
Dim value As String = knop.Tag
If value = "...(?)" Then
knop.BackColor = Color.Black
If ....(?)
End If
End If
I already made a scheme with the label of the buttons, but I find it hard to implement the logic. Can someone help me out with thid one?
EDIT: http://i.stack.imgur.com/3gdrJ.png
If you use Dim ButtonList As List(Of List(Of Button)) and add the buttons to the form in runtime you can add each the button for each row to a list then add that list to ButtonList. Now you can access each button by the indexes in the 2 dimensional list.
Since you're changing the backcolor just use that instead of using the tag.

Opening new form after right click on selected record in continuous form

In my access database before I was using a list box in the form for having list of items and I had below code for opening new form after right click on each selected item in list box.
Private Sub ItemList_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Const RIGHTBUTTON = 2
If Button = RIGHTBUTTON Then
DoCmd.OpenForm "frmShortcut_GenerateTask"
DoCmd.MoveSize udtPos.X * mp.TwipsPerPixelX, udtPos.Y * mp.TwipsPerPixelY
End If
End Sub
Now I am using a continuous form instead of list box and I have defined a [isselected) field for selecting each record in continuous form after clicking on that. Now my problem is how I have to write code for right clicking and opening new form.
I used the same code I had used for list box, but it does not work and nothing happened.
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Const RIGHTBUTTON = 2
If Button = RIGHTBUTTON Then
DoCmd.OpenForm "frmShortcut_GenerateTask"
DoCmd.MoveSize udtPos.X * mp.TwipsPerPixelX, udtPos.Y * mp.TwipsPerPixelY
End If
End Sub
Private Sub P_Click()
On Error Resume Next
Me.IsSelected = Not Me.IsSelected
' Save the status
Me.Dirty = False
' Force conditional highlighting
P_ForceHighLight
' Update display in SF_Selected
Me.Parent("SF_Selected").Requery
ActiveControl.SelLength = 0
On Error GoTo 0
End Sub
I recommend either using a DoubleClick event in all of your textboxes and combos, or else putting a small button at one edge of your continuous form that allows the user to open records. Right-click is going to give you problems (so will labels and image controls) because this event doesn't cause (or ensure) that the Form's internal Recordset Bookmark property is actually moved to the record they right-clicked on. In my experience, only buttons, textboxes, and comboboxes will move the Bookmark to the record the user is trying to select.
To Test this, try putting code at the top of your different routines that shows you what record is selected:
MsgBox "RecordID = " & Me!RecordIDField
If you are consistently getting the correct ID, then your problem has to do with how your opening your new form, passing parameters or arguments, etc.