|
The problem is that you're using the With statement.
With gets you a reference to an object instance. If you try to replace that object instance with a new one, like you're doing in your For loops, the With is still looking at the original object instance, NOT THE NEW ONE.
Remove the With statements and fully qualify all of your object property references and watch what happens:
Sub TestForLoop()
Dim lstRectangles As New List(Of Rectangle)
lstRectangles.Add(New Rectangle(100, 200, 1000, 2000))
lstRectangles.Add(New Rectangle(500, 700, 1500, 2000))
Dim gScale As Single = 0.1
ShowRectDimensions("Before scaling: ", lstRectangles)
Debug.WriteLine("")
For Each rect As Rectangle In lstRectangles
rect = New Rectangle(CInt(rect.Left * gScale), CInt(rect.Top * gScale),
CInt(rect.Width * gScale), CInt(rect.Height * gScale))
Debug.WriteLine("Result inside For Each Loop: {0}x{1},{2}x{3}", rect.Left, rect.Top, rect.Width, rect.Height)
Next
ShowRectDimensions("Result outside For Each Loop: ", lstRectangles)
Debug.WriteLine("")
For i As Integer = 0 To lstRectangles.Count - 1
Dim rect As Rectangle = lstRectangles(i)
lstRectangles(i) = New Rectangle(CInt(rect.Left * gScale), CInt(rect.Top * gScale),
CInt(rect.Width * gScale), CInt(rect.Height * gScale))
Debug.WriteLine("Result inside For Next Loop: {0}x{1},{2}x{3}", lstRectangles(i).Left, lstRectangles(i).Top, lstRectangles(i).Width, lstRectangles(i).Height)
Next
ShowRectDimensions("Result outside For Next Loop: ", lstRectangles)
Debug.WriteLine("")
End Sub
Private Sub ShowRectDimensions(sText As String, ByRef lstRectangles As List(Of Rectangle))
For i As Integer = 0 To lstRectangles.Count - 1
With lstRectangles(i)
Debug.WriteLine("{0}{1}x{2},{3}x{4}", sText, CStr(.Left), CStr(.Top), CStr(.Width), CStr(.Height))
End With
Next
End Sub
|
|
|
|
|
Wanted to prove this but being a Father and Husband I'm unable to control my spare time.
However, If anyone is interested I did this little code to test this:
Sub TestForLoop()
Dim lstRectangles As New List(Of Rectangle)
lstRectangles.Add(New Rectangle(100, 200, 1000, 2000))
lstRectangles.Add(New Rectangle(500, 150, 500, 200))
lstRectangles.Add(New Rectangle(500, 700, 1500, 2000))
Dim pre, n As Integer
Debug.WriteLine(vbCrLf & "Inside Loop:")
For i As Integer = 1 To lstRectangles.Count - 1
With lstRectangles(i)
lstRectangles(i) = New Rectangle(.Left + 10, .Top, .Width, .Height)
Debug.WriteLine("Rectangle " & i)
Debug.WriteLine(" 1st result, Direct Call: {0} - With-block: {1} - (Added:
10)", lstRectangles(i).Left, .Left)
n = lstRectangles(i - 1).Left / i
lstRectangles(i) = New Rectangle(.Left + n, .Top, .Width, .Height)
Debug.WriteLine("New result, Direct Call: {0} - With-block: {1} - (Added:
{2})", lstRectangles(i).Left, .Left, n)
End With
Next
Debug.WriteLine(vbCrLf & "Outside Loop:")
For i As Integer = 1 To lstRectangles.Count - 1
With lstRectangles(i)
Debug.WriteLine("Result: ({0}x{1}, {2}x{3})", .Left, .Top, .Width, .Height)
End With
Next
End Sub
This produced this result:
Inside Loop:
Rectangle 1
1st result, Direct Call: 510 - With-block: 500 - (Added: 10)
New result, Direct Call: 600 - With-block: 500 - (Added: 100)
Rectangle 2
1st result, Direct Call: 510 - With-block: 500 - (Added: 10)
New result, Direct Call: 800 - With-block: 500 - (Added: 300)
Outside Loop:
Result: (600x150, 500x200)
Result: (800x700, 1500x2000)
The result should have been 610 and 815. The added 10s disappears. This shows that the with-block reports the same value to both calculations even though there has been a change between them. However all direct calls give the updated value.
Thank you for clearing this out Dave.
|
|
|
|
|
I don't know what happened to cause this issue. I recreated the project and
the problem went away.
Hello, I'm trying to figure out how to add a custom TabPage to a TabControl.
After searching around I found this sample code of a custom TabControl which supports
my custom XmlTabPage that works as far as adding the page through the Designer but for some reason I get errors after adding the control.
In my Form:
Private Sub InitializeComponent()
Me.CustomTabControl1 = New XmlEditor.CustomTabControl
Me.XmlDataTabPage = New XmlEditor.XmlTabPage
end sub
Friend WithEvents CustomTabControl1 As XmlEditor.CustomTabControl
Friend WithEvents XmlDataTabPage As XmlEditor.XmlTabPage
'The error is that these controls are not defined. ' for the code
New XmlEditor.CustomTabControl and New XmlEditor.XmlTabPage as well
as the Friend declarations.
This code is inserted by the Designer.
These controls are part of the main project.
I can add the prefix 'Global.'XmlEditor.CustomTabControl to both controls and it
works but the next time I use the Designer, it writes the old code.
Can someone help? Below is the partial CustomTabControl code.
Thank you.
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.drawing.Design
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class CustomTabControl
Inherits System.Windows.Forms.TabControl
<System.ComponentModel.Editor(GetType(TabPageCollectionEditor), GetType(UITypeEditor))> _
Public Shadows ReadOnly Property TabPages() As TabPageCollection
Get
Return MyBase.TabPages
End Get
End Property
'UserControl overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub
Public Class TabPageCollectionEditor
Inherits System.ComponentModel.Design.CollectionEditor
Public Sub New(ByVal type As Type)
MyBase.New(type)
End Sub
Protected Overrides Function CreateCollectionItemType() As System.Type
Return GetType(TabPage)
End Function
Protected Overrides Function CreateNewItemTypes() As System.Type()
Return New Type() {GetType(TabPage), GetType(XmlTabPage)}
End Function
End Class
End Class
-- modified 9-Sep-18 19:09pm.
|
|
|
|
|
Hello
In the following line of code
Dim hashedPassword = Crypto.HashPassword(password)
what would crypto be declared as, please? Most examples in tutorials refer to CryptoStream. The full code is
Public Sub CreateAccount(ByVal username As String, ByVal password As String)
Dim hashedPassword = Crypto.HashPassword(password)
CreateAccountInDatabase(username, hashedPassword)
End Sub
Private Sub CreateAccountInDatabase(username As String, hashedPassword As Object)
Throw New NotImplementedException()
End Sub
Private Sub CreateAccount(ByVal username As String, ByVal password As String, ByVal email As String)
Using connection As New OleDbConnection("connectionString")
Dim Sql As String = "INSERT INTO university (username,strEmail,hashed) VALUES (@username,@strEmail,@hashed)"
Dim cmd As New OleDbCommand(Sql)
cmd.Connection = connection
cmd.Parameters.AddWithValue("@username", username)
cmd.Parameters.AddWithValue("@strEmail", email)
Dim hashedPassword = Crypto.HashPassword(password)
cmd.Parameters.AddWithValue("@hashed", hashedPassword)
connection.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
Private Sub BtnReg_Click(sender As Object, e As EventArgs) Handles BtnReg.Click
CreateAccount(username.Text, password.Text, strEmail.Text)
End Sub
Advice appreciated.
|
|
|
|
|
As I told you last month[^]:
Quote: You need to add a reference to the System.Web.Helpers assembly, and add Imports System.Web.Helpers to the top of your code file.
You have one method with infinite recursion, which will result in a StackOverflowException ; and one that deliberately throws a NotImplementedException . You should remove the two non-functioning methods, leaving:
Private Sub CreateAccount(ByVal username As String, ByVal password As String, ByVal email As String)
Dim hashedPassword As String = Crypto.HashPassword(password)
Using connection As New OleDbConnection("... YOUR CONNECTION STRING HERE ...")
Using cmd As New OleDbCommand("INSERT INTO university (username, strEmail, hashed) VALUES (@username, @strEmail, @hashed)", connection)
cmd.Parameters.AddWithValue("@username", username)
cmd.Parameters.AddWithValue("@strEmail", email)
cmd.Parameters.AddWithValue("@hashed", hashedPassword)
connection.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End Sub
Private Sub BtnReg_Click(sender As Object, e As EventArgs) Handles BtnReg.Click
CreateAccount(username.Text, password.Text, strEmail.Text)
End Sub
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hello Richard
Sorry for the delay in replying and many thanks for explaining my code's weaknesses.
It all looks fine now. I was getting a green underline (Imports System.Web.Helpers is not necessary), but on saving the file and reopening it the underline has now disappeared.
I sense that the code is not for the light-hearted, but will persist in coming to terms with it.
Once again, very many thanks.
|
|
|
|
|
I'm working on a project that requires my currency symbol but I don't know how to go about it. My currency code is NGN. Please I need help from you.
|
|
|
|
|
It would be useful if we knew what sort of UI you are working with, winforms, wpf, browser, mobile. The answer is probably different for each.
Most control suites have a masked textbox that will display the currency symbol.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
|
Hi,
Where can I find the version like on winver(cmd command) on the office it is 1511 but some registrysettings only exists from 1607 so I want to check if the version is ok.
I found those:
Dim OSVer As Version = Environment.OSVersion.Version
Dim versie = My.Computer.Info.OSVersion
But thats not the info I need.
Jan
|
|
|
|
|
In the console, I'd use "ver", not "winver"; the latter would open a UI, the first one just prints the version to stdout.
Any program you run on the console, can also be started from your application, where you can fetch the results in a string.
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
OK, look at the Build property of the Version object you're getting back.
To enable all the versions to be available and not just knocked back to Windows 8, add an Application Manifest file to the application. Open that file, go down the compatibility section, and uncomment all the O/S GUID's:
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
is designed to work with. Uncomment the appropriate elements and Windows will
automatically selected the most compatible environment. -->
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
Once you have the build number, compare that build to the list here[^] and you'll find which version of Windows you're running on.
modified 4-Sep-18 10:15am.
|
|
|
|
|
Private Sub DataGridView1_CellPainting(ByVal sender As Object, ByVal e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
'If there is no search string, no rows, or nothing in this cell, then get out.
If ComboBox1.Text = String.Empty Then Return
If (e.Value Is Nothing) Then Return
If e.RowIndex < 0 Or e.ColumnIndex < 0 Then Return
e.Handled = True
e.PaintBackground(e.CellBounds, True)
'Get the value of the text in the cell, and the search term. Work with everything in lowercase for more accurate highlighting
Dim str_SearchTerm As String = ComboBox1.Text.Trim.ToLower
Dim str_CellText As String = DirectCast(e.FormattedValue, String).ToLower
'Create a list of the character ranges that need to be highlighted. We need to know the start index and the length
Dim HLRanges As New List(Of CharacterRange)
Dim SearchIndex As Integer = str_CellText.IndexOf(str_SearchTerm)
Do Until SearchIndex = -1
HLRanges.Add(New CharacterRange(SearchIndex, str_SearchTerm.Length))
SearchIndex = str_CellText.IndexOf(str_SearchTerm, SearchIndex + str_SearchTerm.Length)
Loop
' We also work with the original cell text which is has not been converted to lowercase, else the sizes are incorrect
str_CellText = DirectCast(e.FormattedValue, String)
' Choose your colours. A different colour is used on the currently selected rows
Dim HLColour As SolidBrush
If ((e.State And DataGridViewElementStates.Selected) <> DataGridViewElementStates.None) Then
HLColour = New SolidBrush(Color.DarkGoldenrod)
Else
HLColour = New SolidBrush(Color.Yellow)
End If
'Loop through all of the found instances and draw the highlight box
For Each HLRange In HLRanges
' Create the rectangle. It should start just underneath the top of the cell, and go to just above the bottom
Dim HLRectangle As New Rectangle()
HLRectangle.Y = e.CellBounds.Y + 2
HLRectangle.Height = e.CellBounds.Height - 5
' Determine the size of the text before the area to highlight, and the size of the text to highlight.
' We need to know the size of the text before so that we know where to start the highlight rectangle
Dim TextBeforeHL As String = str_CellText.Substring(0, HLRange.First)
Dim TextToHL As String = str_CellText.Substring(HLRange.First, HLRange.Length)
Dim SizeOfTextBeforeHL As Size = TextRenderer.MeasureText(e.Graphics, TextBeforeHL, e.CellStyle.Font, e.CellBounds.Size)
Dim SizeOfTextToHL As Size = TextRenderer.MeasureText(e.Graphics, TextToHL, e.CellStyle.Font, e.CellBounds.Size)
'Set the width of the rectangle, a little wider to make the highlight clearer
If SizeOfTextBeforeHL.Width > 5 Then
HLRectangle.X = e.CellBounds.X + SizeOfTextBeforeHL.Width - 6
HLRectangle.Width = SizeOfTextToHL.Width - 6
Else
HLRectangle.X = e.CellBounds.X + 2
HLRectangle.Width = SizeOfTextToHL.Width - 6
End If
'Paint the highlight area
e.Graphics.FillRectangle(HLColour, HLRectangle)
Next
'Paint the rest of the cell as usual
e.PaintContent(e.CellBounds)
End Sub
|
|
|
|
|
Dear friends
i write a vb program. in this program a string "john????". and in string count char "?".
thanks ^^
|
|
|
|
|
A string is a sequence of characters with known length. So all you have to do is getting each character from the string, compare it, and upon a match increment a counter variable which has been defined before and initialised with zero.
The above description breaks your requirement down in a way that each part corresponds to a single line of code.
Because this looks like homework, I will not give you code. Try it yourself using my description.
|
|
|
|
|
Find the length of the string, then replace the search character with an empty string, then check the length again. The difference between the two lengths is the number of the characters in the original string. Doing it this way is usually much quicker than testing each character in turn, especially for longer strings.
=========================================================
I'm an optoholic - my glass is always half full of vodka.
=========================================================
|
|
|
|
|
Are you sure?
The replace function has to do the same iterating job internally. It will also create a new string instance when any replacement occurs. And you would have to use the Replace(String, String) method which is slower than operations on characters.
If speed cares I would use String.IndexOf(Char, Integer) within a while loop instead.
|
|
|
|
|
IndexOf is still going to have to compare every character, and has the added overhead of multiple method calls and argument validation.
Your original suggestion of iterating over the characters in the string would probably have the best performance (unless you start introducing unsafe code).
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Try it - you'll be surprised. Native functions and methods such as String.Replace are highly optimized and will be much faster than while loops and string comparisons.
=========================================================
I'm an optoholic - my glass is always half full of vodka.
=========================================================
|
|
|
|
|
I expected them to be highly optimised. My point was that Replace() is creating a new instance and operates on strings rather than characters (the Char version can't be used to remove characters).
IndexOf() is a native function too. On x86 machines the search can be performed with a single CPU instruction: scasw . So this will be faster than a normal loop comparing each character (which is still the expected answer for such homework assignments). If it is finally faster than using Replace() depends on the number of matches.
|
|
|
|
|
It will be highly dependent on the length of the strings. I had reason to write such a function a while back in tSQL for a database system and using the native Replace functionality was much more efficient than looping in all but the shortest of strings, but YMMV.
Module Module1
Sub Main()
Dim iCount As Integer
Dim strToSearch As String = "Every instance. Replace() will inteiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiirnally loop throughiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii the entire source string. It replaces all occurrences of the substring you want to replace. Tip: This behavior is useful when dealing with common string replacements in programs. But: If you do not understand this behavior you may end up writing inefficient code that has unneeded loops. "
Dim strSearchFor As String = "i"
Console.WriteLine(strToSearch)
iCount = strToSearch.Length() - strToSearch.Replace(strSearchFor, "").Length
Console.WriteLine("There are " + iCount.ToString() + " letter " + strSearchFor + "'s in the string")
End Sub
End Module
=========================================================
I'm an optoholic - my glass is always half full of vodka.
=========================================================
|
|
|
|
|
Using BenchmarkDotNet[^]:
public class StringCharCountBenchmark
{
private static readonly string _theStringToSearch = "Every instance. Replace() will inteiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiirnally loop throughiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii the entire source string. It replaces all occurrences of the substring you want to replace. Tip: This behavior is useful when dealing with common string replacements in programs. But: If you do not understand this behavior you may end up writing inefficient code that has unneeded loops. ";
private static readonly char _theCharToFind = 'i';
private static readonly string _theCharToFindAsString = "i";
[Benchmark]
public int UsingReplace()
{
return _theStringToSearch.Length - _theStringToSearch.Replace(_theCharToFindAsString, "").Length;
}
[Benchmark]
public int UsingForEachLoop()
{
int result = 0;
foreach (char c in _theStringToSearch)
{
if (c == _theCharToFind)
{
result++;
}
}
return result;
}
[Benchmark]
public int UsingForLoop()
{
int result = 0;
for (int i = 0; i < _theStringToSearch.Length; i++)
{
if (_theStringToSearch[i] == _theCharToFind)
{
result++;
}
}
return result;
}
} (Yes, I know: C#. But I'm sure you can convert to VB.NET if required. )
Results:
// * Summary *
BenchmarkDotNet=v0.11.1, OS=Windows 10.0.17134.228 (1803/April2018Update/Redstone4)
Intel Core i7-4770K CPU 3.50GHz (Haswell), 1 CPU, 8 logical and 4 physical cores
Frequency=3417969 Hz, Resolution=292.5714 ns, Timer=TSC
[Host] : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3132.0
DefaultJob : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 32bit LegacyJIT-v4.7.3132.0
Method | Mean | Error | StdDev |
----------------- |-----------:|----------:|----------:|
UsingReplace | 3,923.6 ns | 15.267 ns | 12.749 ns |
UsingForEachLoop | 350.1 ns | 4.453 ns | 3.948 ns |
UsingForLoop | 376.1 ns | 7.239 ns | 8.046 ns |
Both loop options are fairly close. The String.Replace version takes roughly 10x as long.
The tool doesn't measure the memory usage, but it should be fairly self-evident that the Replace version will use more memory, since it has to allocate a new string each time.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Module Module1
Sub Main()
Dim strToSearch As String = "john????"
Dim strSearchFor As String = "?"
Console.WriteLine(strToSearch)
Console.WriteLine("There are " + CountOccurrences(strToSearch, strSearchFor).ToString() + " occurrences of " + strSearchFor + " in the string")
End Sub
Function CountOccurrences(strStringToSearch As String, strStringToCount As String) As Integer
Dim iCount As Integer
iCount = strStringToSearch.Length() - strStringToSearch.Replace(strStringToCount, "").Length
Return iCount
End Function
End Module
=========================================================
I'm an optoholic - my glass is always half full of vodka.
=========================================================
|
|
|
|
|
There is no alternative to filecopy that returns the percentage of files copied during the copy, since opening the file in binary mode is not necessary because the put and get commands are probably due to an overflow since I operate on 2GB files up.
|
|
|
|
|
There is no alternative built into VB6.
You're either going to have to code up your own version in something else that can be exposed to COM and handle 64-bit offsets, like in C#/VB.NET/C/C++, or just have the Shell copy files for you. In that case, you'll end up with the Explorer progress window, just as if you dragged and dropped a file to copy by hand.
|
|
|
|
|