Scroll bar for line graph VB.NET - vb.net

I created a line graph in Visual Basic to show how many calories the user eats per day. However, my user requires me to include a scroll bar to scroll back and forward along the x-axis to view more days.
Unfortunately, I have never done anything like this before, and after looking through Stack Overflow and Googling, I cannot see any examples of anyone doing so.
Here is a screenshot of my graph so far:
And here is the code:
Cursor.Current = Cursors.WaitCursor
CalorieChartView = True
BurntChartView = False
NetChartView = False
Dim Series As Series = CalorieChart.Series(0)
'keeps track of if the chart is empty, starting as true
Dim empty As Boolean = True
'Clears the chart
Series.Points.Clear()
'Draws the chart in dark red
Series.Color = Color.DarkRed
'The legend text is changed
Series.LegendText = "Calories Consumed"
'For each of the past 8 days, a point is plotted with how many calories were eaten in that day
For i = -7 To 0
Series.Points.Add(User.GetCaloriesEaten(User.Username, Date.Now.AddDays(i)))
Series.Points(7 + i).AxisLabel = Date.Now.AddDays(i).ToString("dd/MM/yyyy")
'If any of the points are not 0
If User.GetCaloriesEaten(User.Username, Date.Now.AddDays(i)) <> 0 Then
'the chart is not empty
empty = False
End If
Next
HandleEmpty(empty)
Cursor.Current = Cursors.Default
I would appreciate any help.

If I understand your question you want to add a horizontal scroll bar to your graph. I have made some modification and new code to your code as for mock data purpose. Please refer the below code. You can get the idea by running this code separately.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim blockSize As Integer = 10
Cursor.Current = Cursors.WaitCursor
CalorieChartView = True
BurntChartView = False
NetChartView = False
CalorieChart.Series.Clear()
Dim series = CalorieChart.Series.Add("My Series")
series.ChartType = SeriesChartType.Line
series.XValueType = ChartValueType.Int32
'keeps track of if the chart is empty, starting as true
Dim empty As Boolean = True
'Clears the chart
series.Points.Clear()
'Draws the chart in dark red
series.Color = Color.DarkRed
'The legend text is changed
series.LegendText = "Calories Consumed"
'For each of the past 8 days, a point is plotted with how many calories were eaten in that day
Dim sizeOfDayToDisplay As Int16 = 0
For i = 0 To 100
'Series.Points.Add(User.GetCaloriesEaten(User.Username, Date.Now.AddDays(i)))
'Series.Points(7 + i).AxisLabel = Date.Now.AddDays(i).ToString("dd/MM/yyyy")
''If any of the points are not 0
'If User.GetCaloriesEaten(User.Username, Date.Now.AddDays(i)) <> 0 Then
' 'the chart is not empty
' empty = False
'End If
' just for testing purpose.
series.Points.Add(getRandumNumber())
series.Points(i).AxisLabel = Date.Now.AddDays(i).ToString("dd/MM/yyyy")
' series.Points.AddXY(i, Date.Now.AddDays(i).ToString("dd/MM/yyyy"))
sizeOfDayToDisplay += 1
Next
'most new code added is below here
Dim chartArea = CalorieChart.ChartAreas(Series.ChartArea)
chartArea.AxisX.Minimum = 0
chartArea.AxisX.Maximum = sizeOfDayToDisplay
chartArea.CursorX.AutoScroll = True
chartArea.AxisX.ScaleView.Zoomable = True
chartArea.AxisX.ScaleView.SizeType = DateTimeIntervalType.Number
Dim position As Integer = 0
Dim size As Integer = blockSize
chartArea.AxisX.ScaleView.Zoom(position, size)
chartArea.AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll
chartArea.AxisX.ScaleView.SmallScrollSize = blockSize
'HandleEmpty(empty)
'Cursor.Current = Cursors.Default
End Sub
Public Function getRandumNumber() As Int16
Return CInt(Math.Floor((3500 - 1000 + 1) * Rnd())) + 1000
End Function

Based on this: How to scroll MS Chart along x-axis in vb.net, you can use:
Chart1.Series("LoadCell").Points.AddY(receivedData)
Chart1.ResetAutoValues()
If Chart1.Series("LoadCell").Points.Count >= 100 Then
Chart1.Series("LoadCell").Points.RemoveAt(0)
End If
It Auto scales the y axis as well as limiting the x axis to 100 by
removing the first entry when the entries exeed 100.

Related

How to freeze merged columns in data grid view when scrolling vertically?

I have a data grid view where I need the columns to be frozen or fixed when scrolling vertically.
I have a data grid view control in vb.net windows application which displays the data in a parent-child hierarchy(as shown below). The first column displays the parent data and the second column displays all its child data. The child data in the second column can be as much as 100 rows or even more. So when scrolling down through the grid, the value in the first column does not remain there as it is while the values in the second column(i.e. the child data) scrolls down. So if the user wants to check to which parent, the current child info belongs to, then again he will have to scroll up to the starting of the column to find the name of the parent. I want the values in the first column to be displayed or frozen till it reaches the end of the list of its child values in the grid or at least till the next row where the next parent data starts. I have suggested the client to go with a tree view but they are not agreeing and need it in a data grid view itself. Is there anyway to achieve this in a data grid view?
Thanks in advance.
You can't freeze a row (in runtime, on dgv scrolling) with index greater than zero because all those before are frozen and at that point you can't scroll your datagridview.
If I understood correctly what you want I wrote this class quickly (probably should be optimized). Usage is simple.
1 - First create your own datagridview.
2 - then add your columns and rows (IMPORTANT: Put a “X” in the Tag in each row is a Parent or is considered as title for other rows as you seen in TestPopulate method) .
3 - Call the class I made by passing the datagridview (you created first) as a parameter. At this point this control takes its size, placement and REPLACE YOUR DATAGRIDVIEW .
Private Class CustomDgv
Inherits Panel
Dim WithEvents TopDgv As DataGridView = New DataGridView
Dim WithEvents DownDgv As DataGridView = New DataGridView
Dim Cols As Integer
' This variable is in case you have more rows as "headrow"
' In TestPopulate you can see how to get those
Dim listOfOwnerRows As List(Of Integer) = New List(Of Integer)
Dim currentTopRow As Integer = -1
Protected Overloads Property Height As Integer
Get
Return MyBase.Height
End Get
Set(value As Integer)
MyBase.Height = value
TopDgv.Height = TopDgv.RowTemplate.Height - 1
DownDgv.Height = value - TopDgv.Height - 1
End Set
End Property
Protected Overloads Property Width As Integer
Get
Return MyBase.Width
End Get
Set(value As Integer)
MyBase.Width = value
TopDgv.Width = value - 1
DownDgv.Width = value - 1
End Set
End Property
Sub New(dgvOriginal As DataGridView)
DownDgv = dgvOriginal
Dim parentCtrl As Control = dgvOriginal.Parent
parentCtrl.Controls.Remove(dgvOriginal)
parentCtrl.Controls.Add(Me)
Me.Location = DownDgv.Location
Me.Size = DownDgv.Size
Me.BorderStyle = DownDgv.BorderStyle
TopDgv.Width = Width - 2 - SystemInformation.VerticalScrollBarWidth
TopDgv.Height = TopDgv.RowTemplate.Height
TopDgv.ScrollBars = ScrollBars.None
TopDgv.ColumnHeadersVisible = False
TopDgv.BorderStyle = BorderStyle.None
DownDgv.ColumnHeadersVisible = False
DownDgv.BorderStyle = BorderStyle.None
TopDgv.Left = 0
DownDgv.Left = 0
DownDgv.Width = Width - 2
DownDgv.Height = Height - 2
For Each Col As DataGridViewColumn In DownDgv.Columns
Dim cIndex As Integer = TopDgv.Columns.Add(Col.Clone)
If Col.Frozen Then
TopDgv.Columns(cIndex).Frozen = True
End If
Cols += 1
Next
DownDgv.Top = 0
Me.Controls.Add(TopDgv)
Me.Controls.Add(DownDgv)
If DownDgv.Rows.Count > 0 Then
listOfOwnerRows = (From R As DataGridViewRow In DownDgv.Rows
Where R.Tag = "X"
Select R.Index).ToList
If listOfOwnerRows.Count > 0 Then
SetFrosenRow(listOfOwnerRows(0))
End If
End If
End Sub
Protected Sub SetFrosenRow(index As Integer)
If DownDgv.Rows.Count > index Then
TopDgv.Rows.Clear()
TopDgv.Rows.Add()
Dim currentRIndex As Integer = DownDgv.FirstDisplayedScrollingRowIndex
'If you want onlly the base row
For i As Integer = 0 To Cols - 1
TopDgv.Rows(0).Cells(i).Value = DownDgv.Rows(index).Cells(i).Value
Next
'Or else get the diplayed on top row
TopDgv.Rows(0).DefaultCellStyle = New DataGridViewCellStyle With {
.BackColor = Color.Bisque
}
currentTopRow = index
End If
End Sub
Protected Sub SetChildValuesInTopRow(index As Integer)
For i As Integer = 1 To Cols - 1
TopDgv.Rows(0).Cells(i).Value = DownDgv.Rows(index).Cells(i).Value
Next
End Sub
Private Sub DownDgv_Scroll(sender As Object, e As ScrollEventArgs) Handles DownDgv.Scroll
Try
If e.ScrollOrientation = ScrollOrientation.VerticalScroll Then
Dim topR As Integer = DownDgv.FirstDisplayedScrollingRowIndex
'If you want in top row the current value that is in the top uncomment this
SetChildValuesInTopRow(topR)
If listOfOwnerRows.Count > 0 Then
Dim rToSetAsOwner As Integer = listOfOwnerRows(listOfOwnerRows.Count - 1)
For i As Integer = listOfOwnerRows.Count - 1 To 0 Step -1
If listOfOwnerRows(i) <= topR Then
rToSetAsOwner = listOfOwnerRows(i)
Exit For
End If
Next
If rToSetAsOwner <> currentTopRow Then
SetFrosenRow(rToSetAsOwner)
End If
Console.WriteLine("rToSetAsOwner: " & rToSetAsOwner)
End If
Else
TopDgv.HorizontalScrollingOffset = DownDgv.HorizontalScrollingOffset
End If
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
End Class
Usage:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
' first populate you grid putting a tag in each row which is a header/parent/title for other rows
TestPopulate()
Dim customControl As Control = New CustomDgv(DataGridView1)
Catch ex As Exception
Console.WriteLine(ex.ToString)
End Try
End Sub
Sub TestPopulate()
For i As Integer = 0 To 100
DataGridView1.Rows.Add()
If i = 0 Then
DataGridView1.Rows.Item(0).Cells(0).Value = "Owner 0"
DataGridView1.Rows(0).Tag = "X"
End If
If i = 50 Then
DataGridView1.Rows.Item(50).Cells(0).Value = "Owner 50"
DataGridView1.Rows(50).Tag = "X"
End If
If i = 70 Then
DataGridView1.Rows.Item(70).Cells(0).Value = "Owner 70"
DataGridView1.Rows(70).Tag = "X"
End If
DataGridView1.Rows.Item(i).Cells(1).Value = "child_" & i.ToString & "_1"
DataGridView1.Rows.Item(i).Cells(2).Value = "child_" & i.ToString & "_2"
Next
End Sub
I hope I have been helpful

Using backcolor to compare in datagridview cells of current row to those of previous row in vb net

I am working out a sequential tank filling plan.
I use a datagridview. In part (2) of the following code, each row represents a sequence and each row cell (beginning from the fourth one in the row) the volume of liquid in a specific tank. If it appears by comparing the current row cell to that of the previous row that the volume has increased, I want the cell backcolor become green, if it decreased then it's yellow color and if no change the color remains white.
The cells receive their data from calculation results when clicking the TkFil button.
The issue I am facing is that the first four or eight cells of the row get their colors in a random order while all the rest behind are fine. I simply fail to understand and need some help: why is the colouring not working?
This is my full code:
Private Sub btnTkFil_Click(sender As System.Object, e As System.EventArgs) Handles btnTkFil.Click
If Form36 Is Nothing Then
MessageBox.Show("Please first open the Ballast Plan form")
Else
'PART(1)
Form36.dgv1.CurrentRow.Cells(0).Value = Form1.txtCondition.Text.ToString
Form36.dgv1.CurrentRow.Cells(1).Value = Val(Form1.txtAftDft.Text)
Form36.dgv1.CurrentRow.Cells(2).Value = Val(Form1.txtForeDft.Text)
Form36.dgv1.CurrentRow.Cells(3).Value = Val(tbGm1.Text)
Try
For i As Integer = 4 To CInt(Val(Form32.tbNbBox.Text) + 3)
'For j As Integer = 0 To CInt(Val(Form32.tbNbBox.Text) - 1)
For j As Integer = 0 To Form31.DataGridView1.Rows.Count - 1
For n As Integer = 0 To CInt(Val(Form32.tbNbBox.Text) - 1) Step +1
Form36.dgv1.Columns(i).Name = CStr(Form31.DataGridView1.Rows(j).Cells(0).Value) ' noms blst tks
Form36.dgv1.Rows(0).Cells(i).Value = CStr(Form31.DataGridView1.Rows(j).Cells(1).Value) 'tank capa
If Form36.rBtn1.Checked = True And Form36.rBtn2.Checked = False Then
Colb(n).Text = CStr(Form31.DataGridView1.Rows(j).Cells(3).Value) 'passe aux boxes "t" les valeurs seules reçues dans Form31.dgv et retranscrites dans GBox1.textbox en %
Form36.dgv1.CurrentRow.Cells(i).Value = Format(Val(Colb(n).Text), "0") & "%"
End If
If Form36.rBtn1.Checked = False And Form36.rBtn2.Checked = True Then
Colb(n).Text = CStr(CDbl(Form31.DataGridView1.Rows(j).Cells(1).Value) * CDbl(Form31.DataGridView1.Rows(j).Cells(3).Value) / 100)
Form36.dgv1.CurrentRow.Cells(i).Value = Format(Val(Colb(n).Text), "0")
End If
i += 1
j += 1
Next
Next
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
'PART(2)
Try
For i As Integer = 4 To CInt(Val(Form32.tbNbBox.Text) + 3)
For j As Integer = 2 To Form36.dgv1.Rows.Count - 2
Dim a As String = CStr(Form36.dgv1.Rows(j).Cells(i).Value)
Dim b As String = CStr(Form36.dgv1.Rows(j - 1).Cells(i).Value)
If a > b Then
Form36.dgv1.Rows(j).Cells(i).Style.BackColor = Color.PaleGreen
ElseIf a < b Then
Form36.dgv1.Rows(j).Cells(i).Style.BackColor = Color.Yellow
ElseIf a = b Then
Form36.dgv1.Rows(j).Cells(i).Style.BackColor = Color.White
End If
Next
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End Sub
You're using strings to compare what should be numbers. That can lead to unexpected results, for example 8 < 10 but "8" > "10"
You just need to modify the code in PART(2) to
Dim a As Double = CDbl(Form36.dgv1.Rows(j).Cells(i).Value)
Dim b As Double = CDbl(Form36.dgv1.Rows(j - 1).Cells(i).Value)

Fitting runtime buttons inside a form

I have a number of buttons between 5-20 and it's variable each time the form loads based on the user settings. I am trying to fit all these buttons on my form no matter what the size of the form is. The buttons are generated during runtime. I would like the first button to be 20 points from the top bar (at any size) and the rest of the buttons simply to fit in the form. This is what I have now but I have to maximize the form to view them all and also while I'm expanding the form the space between the buttons decreases and they overlap with each other whereas they should keep a relative distance. Any ideas?
Dim iButtonWidth, iButtonHeight, iVerticalSpace As Integer
If UserButtons.Count > 0 Then
iButtonHeight = Me.Size.Height - (Me.Size.Height * 0.85)
iButtonWidth = Me.Size.Width - (Me.Size.Width * 0.5)
iVerticalSpace = iButtonHeight / 3
For Each btn In UserButtons
btn.Size = New System.Drawing.Size(iButtonWidth, iButtonHeight)
btn.Location = New Point(20, 20 + btn.TabIndex * iVerticalSpace * 3)
Next
End If
Here's a quick example using the TableLayoutPanel to play with:
Public Class Form1
Private UserButtons As New List(Of Button)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Static R As New Random
Dim NumButtons As Integer = R.Next(5, 21) ' "a number of buttons between 5-20 and it's variable each time"
UserButtons.Clear()
For i As Integer = 1 To NumButtons
Dim btn As New Button()
btn.Text = i.ToString("00")
btn.Dock = DockStyle.Fill ' Optional: See how you like it with this on vs. off
UserButtons.Add(btn)
Next
DisplayButtons()
End Sub
Private Sub DisplayButtons()
TableLayoutPanel1.SuspendLayout()
TableLayoutPanel1.Controls.Clear()
TableLayoutPanel1.ColumnStyles.Clear()
TableLayoutPanel1.ColumnCount = 5 ' Fixed Number of Columns
For i As Integer = 1 To TableLayoutPanel1.ColumnCount
TableLayoutPanel1.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 911)) ' the size doesn't matter here, as long as they are all the same
Next
' Variable Number of Rows:
Dim RowsRequired As Integer = ((UserButtons.Count - 1) \ TableLayoutPanel1.ColumnCount) + 1 ' Integer Division
TableLayoutPanel1.RowStyles.Clear()
TableLayoutPanel1.RowCount = RowsRequired
For i As Integer = 1 To TableLayoutPanel1.RowCount
TableLayoutPanel1.RowStyles.Add(New RowStyle(SizeType.Percent, 911)) ' the size doesn't matter here, as long as they are all the same
Next
TableLayoutPanel1.Controls.AddRange(UserButtons.ToArray)
TableLayoutPanel1.ResumeLayout()
End Sub
End Class
First of all what kind of container are the buttons in? You should be able to set the container's AutoScroll property to true - then when controls within it spill out of the visible bounds you will get a scroll bar.
Then also what you could do is draw each button in more of a table with a certain number next to each other before dropping down to the next line (instead of just 1 button on each line). If that is an option that works for you then you could get more buttons within the visible space.
I happen to have an example to do the same thing with picture boxes (and text boxes under each picture box). Hope this helps:
Dim point As New Point(0, 0)
'create 11 picture and text boxes-you can make this number the number your user selects.
Dim box(11) As PictureBox
Dim text(11) As TextBox
Dim i As UInt16
For i = 0 To 11 'or whatever your number is
box(i) = New PictureBox
box(i).Width = 250 'your button width
box(i).Height = 170 'your button height
box(i).BorderStyle = BorderStyle.FixedSingle
box(i).Location = point
layoutsPanel.Controls.Add(box(i)) 'my container is a panel
text(i) = New TextBox
text(i).Height = 50
text(i).Width = 250
point.Y += box(i).Height
text(i).Location = (point)
layoutsPanel.Controls.Add(text(i))
point.Y -= box(i).Height 'reset Y for next picture box
'Put 4 picture boxes in a row, then move down to next row
If i Mod 4 = 3 Then
point.X = 0
point.Y += box(i).Height + text(i).Height + 4
Else
point.X += box(i).Width + 4
End If
Next

Print multiple images in vb.net

In VB.NET, I need to print multiple Images of bar codes by arranging them in tabular format. For now what I am doing is, Creating the bar codes and adding them in new picture box. These Picture boxes are added on a panel which I am creating on form at run time and print that panel (with picture boxes in 4x9 table).
But, when I need to print more that 36 bar codes, this idea doesn't work.
So, Please suggest me some improvements in my code or any other way to do this job.
I am sorry, here is the code for generating images and adding them to the panel..
''' Method for create bar code images with a loop and adding them to the panel by picture box...
Private Function GetBarcodeText(RowId As Guid)
Dim BarcodeValue As StringBuilder = New StringBuilder(96)
Dim temp As New StringBuilder
Dim data As String
Dim param = New SqlParameter()
Dim imageNo As Integer = 0
Dim colorValue As String = ""
Dim scaleValue As String = ""
'' Adding the panel on the form which is dynamically created
Me.Controls.Add(outputPanel)
'' Setting the Initial size for the panel
outputPanel.Size = New Point(794, 112)
outputPanel.Name = "outputPanel"
outputPanel.BackColor = Drawing.Color.White
param.ParameterName = "#RowId"
param.Value = RowId
param.SqlDbType = SqlDbType.UniqueIdentifier
' Get the particular row of data from database
dt = objStockProvider.GetBarcodeDetails(param)
' GET colour code
Dim color As String = dt.Rows(0)("COLOUR").ToString()
Dim countColors As Integer = 0
' Get the color code numbers
param.ParameterName = "#Dscale"
param.Value = dgvViewTickets.CurrentRow.Cells("SCALE").Value.ToString()
countColors = objStockProvider.CountColorCodes(param)
For i = 1 To countColors
For j As Integer = 1 + ((12 / countColors) * (i - 1)) To (12 / countColors) * i
If dt.Rows(0)("S" + j.ToString()) <> 0 Then
Dim totalTicketsForASize As Integer
totalTicketsForASize = dt.Rows(0)("S" + j.ToString())
For k As Integer = 1 To totalTicketsForASize
' Set Bar code value which has to create
BarcodeValue = "123456789012"
' Create Barcode Image for given value
Dim image = GetBarcodeImage(BarcodeValue, colorValue, scaleValue)
If image IsNot Nothing Then
'' Create picture box to contain generated Image.
Dim pcbImage As New PictureBox
pcbImage.Width = W
pcbImage.Height = H
pcbImage.Image = image
pcbImage.Location = New Point(X, Y)
imageNo += 1
If imageNo Mod 4 = 0 Then
X = 15
Y += H
outputPanel.Height += H
Else
X += W
Y = Y
End If
pcbImage.Visible = True
'' Adding picture box to panel
outputPanel.Controls.Add(pcbImage)
End If
Next
End If
Next
color = color.Substring(color.IndexOf(",") + 1, color.Length - color.IndexOf(",") - 1)
Next
PrintGeneratedTickets()
End Function
Now, I am printing the panel by following method:
Private Sub PrintGeneratedTickets()
bmp = New Bitmap(outputPanel.DisplayRectangle.Width, outputPanel.DisplayRectangle.Height)
Dim G As Graphics = Graphics.FromImage(bmp)
G.DrawRectangle(Pens.White, New Rectangle(0, 0, Me.outputPanel.DisplayRectangle.Width, Me.outputPanel.DisplayRectangle.Height))
Dim Hdc As IntPtr = G.GetHdc()
SendMessage(outputPanel.Handle, WM_PRINT, Hdc, DrawingOptions.PRF_OWNED Or DrawingOptions.PRF_CHILDREN Or DrawingOptions.PRF_CLIENT Or DrawingOptions.PRF_NONCLIENT)
G.ReleaseHdc(Hdc)
pndocument.DocumentName = bmp.ToString()
Dim previewmode As New PrintPreviewDialog
previewmode.Document = pndocument
previewmode.WindowState = FormWindowState.Maximized
previewmode.PrintPreviewControl.Zoom = 1
pndocument.DefaultPageSettings.Margins.Top = 10
pndocument.DefaultPageSettings.Margins.Bottom = 30
pndocument.DefaultPageSettings.Margins.Left = 16
pndocument.DefaultPageSettings.Margins.Right = 16
pndocument.DefaultPageSettings.Landscape = False
' Set other properties.
previewmode.PrintPreviewControl.Columns = 4
previewmode.PrintPreviewControl.Rows = 9
previewmode.ShowDialog()
Dim file As String = DateTime.Now.ToString()
file = Path.GetFullPath("D:\Bar Codes\" + file.Replace("/", "-").Replace(":", ".") + ".bmp")
bmp.Save(file)
G.Dispose()
outputPanel.Controls.Clear()
End Sub
This code is working fine but what I need to do, is to fix the number of images (4x9) per page. But when I am trying to create more than it, that all are printing on a single page with compressed size.
Also when trying to re-run the code, It shows nothing in preview..
Some body please suggest the correction in code so that I can reprint the tickets and use paging for more than 36 images.
Well, Printing the Images on a panel was not a good idea.. I replaced the panel and created an array of images and used the print document directly and print after arranging images on it.
Thanks.

Trouble with Timer_tick not stopping

I'm very new to programming and vb.net, trying to self teach more so as a hobby, as I have an idea for a program that I would find useful, but I am having trouble getting past this issue and I believe it is to do with the timer.
I have a form of size.(600,600) with one button of size.(450,150) that is set location(100,50) on the form. When clicked I want to move down it's own height, then add a new button in it's place. The code included below works as desired for the first two clicks, but on the third click the button keeps moving and the autoscroll bar extends. I initially thought it was the autoscroll function or the location property, but realised that as the button keeps moving, the timer hasn't stopped. I am aware that the code is probably very clunky in terms of achieving the outcome, and that there are a few lines/variables that are currently skipped over by the compiler (these are from older attempts to figure this out).
I have looked around and can't find the cause of my problem. Any help would be greatly appreciated. Apologies if the code block looks messy - first go.
Public Class frmOpenScreen
Dim intWButtons, intCreateButtonY, intCreateButtonX 'intTimerTick As Integer
Dim arrWNames() As String
Dim ctrlWButtons As Control
Dim blnAddingW As Boolean
Private Sub btnCreateW_Click(sender As System.Object, e As System.EventArgs) Handles btnCreateW.Click
'Creates new Button details including handler
Dim strWName, strWShort As String
Dim intCreateButtonY2 As Integer
Static intNumW As Integer
Dim B As New Button
strWName = InputBox("Please enter the name name of the button you are creating. Please ensure the spelling is correct.", "Create W")
If strWName = "" Then
MsgBox("Nothing Entered.")
Exit Sub
End If
strWShort = strWName.Replace(" ", "")
B.Text = strWName
B.Width = 400
B.Height = 150
B.Font = New System.Drawing.Font("Arial Narrow", 21.75)
B.AutoSizeMode = Windows.Forms.AutoSizeMode.GrowAndShrink
B.Anchor = AnchorStyles.Top
B.Margin = New Windows.Forms.Padding(0, 0, 0, 0)
'Updates Crucial Data (w name array, number of w buttons inc Create New)
If intNumW = 0 Then
ReDim arrWNames(0)
Else
intNumW = UBound(arrWNames) + 1
ReDim Preserve arrWNames(intNumW)
End If
arrWNames(intNumW) = strWShort
intNumW = intNumW + 1
intWButtons = WButtonCount(intWButtons) + 1
'updates form with new button and rearranges existing buttons
intCreateButtonY = btnCreateW.Location.Y
intCreateButtonX = btnCreateW.Location.X
‘intTimerTick = 0
tmrButtonMove.Enabled = True
‘Do While intTimerTick < 16
‘ 'blank to do nothing
‘Loop
'btnCreateW.Location = New Point(intCreateButtonX, intCreateButtonY + 150)
B.Location = New Point(intCreateButtonX, intCreateButtonY)
Me.Controls.Add(B)
B.Name = "btn" & strWShort
intCreateButtonY2 = btnCreateW.Location.Y
If intCreateButtonY2 > Me.Location.Y Then
Me.AutoScroll = False
Me.AutoScroll = True
Else
Me.AutoScroll = False
End If
'MsgBox(intCreateButtonY)
End Sub
Function WButtonCount(ByRef buttoncount As Integer) As Integer
buttoncount = intWButtons
If buttoncount = 0 Then
Return 1
End If
Return buttoncount
End Function
Public Sub tmrButtonMove_Tick(sender As System.Object, e As System.EventArgs) Handles tmrButtonMove.Tick
Dim intTimerTick As Integer
If intTimerTick > 14 Then
intTimerTick = 0
End If
If btnCreateW.Location.Y <= intCreateButtonY + 150 Then
btnCreateW.Top = btnCreateW.Top + 10
End If
intTimerTick += 1
If intTimerTick = 15 Then
tmrButtonMove.Enabled = False
End If
End Sub
End Class
So my current understanding is that the tick event handler should be increasing the timertick variable every time it fires, and that once it has hits 15 it should diable the timer and stop the button moving, but it is not doing so.
Thanks in advance.
IntTimerTick is initialized to 0 at the beginning of every Tick event. This won't happen if you declare it to be static:
Static Dim intTimerTick As Integer