Rows Added to a Datagridview not being captured in Screen Capture - vb.net

I am running into an issue where I am attempting to add some blank rows to a datagridview before printing the form for use.
I am having an issue trying to understand where I need to put the code to add the rows to the data gridview so they are added and captured before the user hits print. My concern is that I am not adding the rows in the right spot before the screen is captured however the code to add the rows is run before the code to hide the buttons is implemented however the buttons are removed and the rows are not added in the actual printed image.
If that is not clear hopefully these images will make more sense. At this point I am not sure why the buttons being hidden are being captured but the added rows are not when based on the code it looks like the rows are being added before the buttons are hidden.
Thank you.
Here is the Image before the user hits print
Here is the Image after the user hits Print
And here is what actually printed
And here is the code in question that captures the screen
Private Sub CaptureScreen()
Dim myGraphics As Graphics = Me.CreateGraphics()
Dim s As Size = Me.Size
If dgvReceive.Rows.Count < 27 Then
Dim rowstoadd As Integer = 0
rowstoadd = 27 - dgvReceive.Rows.Count
dgvReceive.Rows.Add(rowstoadd)
End If
If MemoryImage IsNot Nothing Then
MemoryImage.Dispose()
End If
MemoryImage = New Bitmap(s.Width, s.Height, myGraphics)
For Each btn As Button In Me.Controls.OfType(Of Button)
btn.Visible = False
Next
dgvReceive.ClearSelection()
lblTitle.Select()
Me.FormBorderStyle = FormBorderStyle.None
Dim memoryGraphics As Graphics = Graphics.FromImage(MemoryImage)
memoryGraphics.CopyFromScreen(Me.Location.X, Me.Location.Y, 0, 0, s)
Me.FormBorderStyle = FormBorderStyle.Sizable
For Each btn As Button In Me.Controls.OfType(Of Button)
btn.Visible = True
Next
End Sub

Related

How to re-arrange multiple buttons within a panel when panel/form is resized?

I have a vb.net form that has a panel. Inside the panel, there are 40 buttons dynamically created (see code below). If user wants to resize the form, the panel will resize, but the button layout will not change (i.e. 5 columns of buttons instead of 4 when the form expands horizontally. Is there any way to make the buttons automatically arrange, like when user make the form smaller, there are only 3, or 2, or 1 columns of buttons, and when the form is getting larger, the buttons will arrange to 5 or more columns?
Here is the code of the form, and what I have done so far:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim a, b As Integer
For i = 0 To 40
Dim SampleButton As New Button With {
.Name = "Sample_Button" & "-" & i.ToString,
.Text = "Sample_Button" & "-" & i.ToString,
.Location = New Point(a, b),
.Font = New Font("Segoe UI", 11, FontStyle.Regular),
.Height = 50,
.Width = 180,
.FlatStyle = FlatStyle.Flat,
.TextAlign = ContentAlignment.MiddleCenter,
.Cursor = Cursors.Hand
}
a += SampleButton.Width + 10
If (a + SampleButton.Width) > Panel_MainMenu.Width Then
a = 10
b += SampleButton.Height + 10
End If
SampleButton.BackColor = Color.FromArgb(255, 232, 251, 232)
Panel_MainMenu.Controls.Add(SampleButton)
Next
End Sub
Private Sub Panel_MainMenu_Layout(sender As Object, e As LayoutEventArgs) Handles Panel_MainMenu.Layout
'For Each Controls In Panel_MainMenu.Controls
'Next
End Sub
End Class
What I have done:
Anchor Panel_MainMenu to top, left, right, and bottom (it helps resize the panel according to the size of the form, but not the buttons within it)
Panel_MainMenu.AutoScroll = True
Panel_MainMenu.AutoSize = False and Panel_MainMenu.AutoSizeMode = GrowOnly
I searched on Google on how to use Panel.Layout, but I have not figured out a way to parse the button layout to Panel.Layout to let them adjust accordingly.
I set Panel_MainMenu's minimum size to 776, 426
Any help would be greatly appreciated. Thanks for reading my post!
Simply change from using a Panel to a FlowLayoutPanel:
Represents a panel that dynamically lays out its contents horizontally
or vertically.
You will then not need to specify a Location for each button since this will be taken care of for you.
Anchor/Dock the FlowLayoutPanel so that it resizes with the form, then the buttons will automatically be arranged.

For each getting all picture boxes

Building a space invaders game framework and having some issues getting each bullet that's on screen.
The bullet is defined/created using the below :
Dim Bullet As PictureBox
Bullet = New PictureBox()
Controls.Add(Bullet)
For Each Bullet As Control In Me.Controls
If TypeOf Bullet Is PictureBox Then
If Bullet.Visible = True Then
BulletTimer.Enabled = True
Bullet.Top = Bullet.Top - 10
End If
End If
Next
The problem I've got is that this gets every picture box on screen, including the player and enemies and sends the whole lot flying upwards rather than just the bullets.
You can use the Tag property present in every control. Set the Tag property of the PictureBox to something that identify your PictureBox as a bullet. For example you can set it to the string "BULLET".
Then your loop checks if the PictureBox has the Tag set and if the Tag property has the value "BULLET"
Dim Bullet As PictureBox
Bullet = New PictureBox()
Bullet.Tag = "BULLET"
Controls.Add(Bullet)
....
For Each Bullet As PictureBox In Me.Controls.OfType(Of PictureBox)
If Bullet.Tag IsNot Nothing AndAlso Bullet.Tag.ToString = "BULLET" Then
If Bullet.Visible = True Then
BulletTimer.Enabled = True
Bullet.Top = Bullet.Top - 10
End If
End If
Next
Notice that you can simplify your loop using the OfType(T) extension to retrieve only PictureBox from the controls collection. This remove the need to check if the control is a PictureBox.

VB.NET ClientSize

I have one form and I want it to be fullscreen, but taskbar should be still visible. And I want it to have one Panel on it, whose borders are 10px away from form borders
I tried hundreds of combinations, and I simply can't achieve this.
here's my code
Public Class Form1
Sub New()
InitializeComponent()
WindowState = FormWindowState.Maximized
Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height)
Dim p1 As New Panel()
p1.Location = New Point(10, 10)
p1.Size = New Size(ClientSize.Width - 20, ClientSize.Height - 20)
p1.BackColor = Color.Blue
Controls.Add(p1)
End Sub
End Class
what I want: http://i.imgur.com/4BxoBeh.png
what I get: http://i.imgur.com/QynIdaU.png
I would take an entirely different approach where there is no need to calculate anything:
WindowState = FormWindowState.Maximized
Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height)
Padding = New Padding(10)
Dim p1 As New Panel()
p1.Location = New Point(0, 0)
p1.Dock = DockStyle.Fill
p1.BackColor = Color.Blue
Controls.Add(p1)
Your calculation is correct for a form that takes entire screen but is not maximized, which you can see by unmaximizing it as soon as it appears. The reason is that you are observing the form sizes from the constructor which is a bit too early (namely, even though you are setting WindowState = FormWindowState.Maximized before everything else, ClientSize still has values corresponding to non-maximized window because the window has not yet been created and shown). If you move your original code to e.g. a Form.Load handler it will give the opposite result - looking correct when the form is maximized and incorrect if not.
The padding approach works as expected in all cases.

winforms: Slow performance on form load

I have a VB.NET winforms application. One of its forms, contains a flowlayoutpanel which I populate dynamically (programmatically) on form load event with pairs of label-textbox. My flowlayoutpanel is created in design time with all the properties set to default except below ones:
AutoSize: true
AutoScroll: true
Dock: fill
FlowDirection: TopDown
Then I populate it using below code within the form load event:
Private Sub MyForm_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles Me.Load
Dim lbl As Label
Dim txt As TextBox
Dim flowLayout As FlowLayoutPanel
Dim g As Graphics
For i As Integer = 0 To 253
lbl = New Label
lbl.Text = i.ToString("000") + ":"
lbl.Anchor = AnchorStyles.None
lbl.AutoSize = True
txt = New TextBox
txt.Text = "<" + i.ToString.PadLeft(3, " ") + ">"
txt.MaxLength = 5
txt.Anchor = AnchorStyles.None
txt.ReadOnly = True
g = txt.CreateGraphics
txt.Width = g.MeasureString(txt.Text, txt.Font).Width + 5
g.Dispose()
flowLayout = New FlowLayoutPanel
flowLayout.FlowDirection = FlowDirection.LeftToRight
flowLayout.AutoSize = True
flowLayout.Anchor = AnchorStyles.None
flowLayout.Margin = New Padding(0)
flowLayout.Padding = New Padding(0)
flowLayout.Controls.Add(lbl)
flowLayout.Controls.Add(txt)
Me.FlowLayoutPnl.Controls.Add(flowLayout)
Next
End Sub
As I have stated above FlowLayoutPnl is created on design time and components on this are added following TopDown flow direction.
Above code produces this result.
The problem here is that on opening this form it takes so much time (a few seconds) to open because it is doing all the stuff in form load event. It takes 35 seconds to open!. When all the stuff is done then form becomes visible after 35 seconds...
So I would like to know if there is some kind of method to speed up form load. I have read some posts here saying about implement and show some kind of splash screen while it loads indicating user that it is being loaded or even perform an asynchronous load. What about creating a background thread from form load event in order to do this stuff? Anyone could guide me in the right direction? A very little example will be highly appreciated. How this kind of problems are normally resolved?

Order of controls being added to panel, control not showing unless docked

I imagine this is probably an easy to answer question but for some reason I can't get it to work
Sub New(ByVal Sess As AudioSessionControl2)
S_Session = Sess
'Create the panel and position it.
S_Panel.BackColor = Color.AliceBlue
S_Panel.Width = 200
S_Panel.Height = 40
Dim Position As New Point(6, 19)
If G_AppSessions.Count > 0 Then
Position = Point.Add(G_AppSessions.Item(G_AppSessions.Count - 1).SessionPanel.Location, New Point(0, 45))
End If
S_Panel.Location = Position
'Create a label which has the name of the process
Dim S_PName As New Label
S_PName.Text = "Test"
S_PName.Dock = DockStyle.Left
S_Panel.Controls.Add(S_PName)
'Create a button to change volume
Dim S_Save As New Button()
S_Save.Text = "Save"
AddHandler S_Save.Click, AddressOf Save_Click
S_Save.Parent = S_Panel
S_Panel.Controls.Add(S_Save)
S_Volume.Parent = S_Panel
S_PName.Parent = S_Panel
MainForm.Controls.Add(S_Panel)
S_Panel.Parent = MainForm.gb_Applications
End Sub
The problem is that, the label will show because its docked, but the button won't. It will only show if its docked as well, and thats just not what I want. This is part of a class for creating a dynamic UI, where I can create a number of this class to create a bunch of panels for various things.
I don't see anywhere where you are setting the label or button position. You probably have them both at 0,0 and the label is on top of the button, obscuring it. Did you try setting the position of both the controls, making sure they don't overlap?