0

So I have been trying to Google this, and haven't been able to find a solution, or found a proper way to even Google this issue I am having.

So let's say I am creating a form in Visual Studio. I have set the size of the form to be Width = 250, Height = 250. I using the toolbox add a Textbox to the form that is as Location X = 25, Y = 25 with Width = 100.

You all with me so far?

The load method for the form has the following code:

Public Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim TextBox2 As New TextBox With {
        .Location = New Point(25,25),
        .Visible = True,
        .Width = 100
    }
    Me.Controls.Add(TextBox2)
End Sub

The expected result when I run this program is to have 2 textboxes directly on top of each other, essentially making it look like 1 text box is on the form. But what is actually happening if I have the TextBox I placed on the form non-programmatically appearing where I placed it, and the TextBox I created in the Load method appearing offset from where it is suppose to.

So why is this happening? Is it a problem with how I am adding the element to the form?

EDIT: This is what my Form looks like when I run the above code:

Offset Text Boxes

EDIT 2:

To clarify I am not trying to figure out how to place one form element on top of another. I am trying to figure out why I am having a problem with placing any element at a specific location when trying to add the element programmatically.

Skitzafreak
  • 1,797
  • 7
  • 32
  • 51
  • Can I ask why didn't you use the designer? – Simo Sep 24 '18 at 15:38
  • 1
    @Simo because this was a test of a problem I was having with another project where elements are added programmatically based on user input. – Skitzafreak Sep 24 '18 at 15:42
  • 1
    I just did exactly what you described and used your exact code and it worked exactly as expected for me, i.e. the `TextBoxes` were occupying the same space on the form. I changed the 25 values to 27 and could see both slightly offset. Something seems to be up with your system. Either that or you have some other code that is changing things. – jmcilhinney Sep 24 '18 at 15:46
  • is the control placed by the designer on a panel or some other container ? In that case the second should also be – GuidoG Sep 24 '18 at 15:56
  • @jmcilhinney I updated the post to show a picture of what my form looks like when I run my above example on my system exactly as written. – Skitzafreak Sep 24 '18 at 16:03
  • @GuidoG No, there is no panel. Everything I am doing is exactly as I have written it above. – Skitzafreak Sep 24 '18 at 16:03
  • 1
    Doing this in the Load event is very problematic. At that point auto-scaling and layout has already completed so controls are not necessarily where you originally placed them anymore. Especially problematic in Win10, dpiAware layout is very important today. It is never necessary, use the constructor instead. If you must then simply give the control the same Location and Size as the one you want to overlap. – Hans Passant Sep 24 '18 at 16:04
  • @HansPassant I created a constructor and moved the code to that. Same issues. And if you read my issue, I **am** giving the new one the **exact** same location and size as the one in the designer. – Skitzafreak Sep 24 '18 at 16:08
  • If you check the values of the `Location` and `Size` properties of the two `TextBoxes` after the form has been displayed, what are they? – jmcilhinney Sep 24 '18 at 16:12
  • When the Form is shown, what are the actual locations of the two TextBoxes? From what is shown in the picture, the width is also off. What Hans Passant is saying is the most probable cause. Is you app DPI Aware? How is the Form scaling its viewport? What is its AutoScaleMode? – Jimi Sep 24 '18 at 16:12
  • @Skitzafreak I added an answer, it might helps you – Simo Sep 24 '18 at 16:22
  • @jmcilhinney TextBox1 (the one added in the designer) is showing it's Location as (17,16) instead of (25,25). TextBox2 (the one added programmatically) is showing it's location as (25,25). So the one I created in the designer as having their locations changed? O_o – Skitzafreak Sep 24 '18 at 16:29
  • @Jimi apparently that is the issue. How do I figure out if it is DPI aware? The AutoScaleMode is set to Font atm. – Skitzafreak Sep 24 '18 at 16:36
  • You don't have to figure it out, you are the one that determine this behaviour. Read [these notes](https://stackoverflow.com/questions/50239138/dpi-awareness-unaware-in-one-release-system-aware-in-the-other?answertab=active#tab-top) and [Hans Passant's in this other question](https://stackoverflow.com/questions/13228185/how-to-configure-an-app-to-run-correctly-on-a-machine-with-a-high-dpi-setting-e?answertab=active#tab-top). Update your `app.manifest` accodingly. Add one if it's missing. – Jimi Sep 24 '18 at 16:41
  • As I said, dpiAware layout is very important today. Visual Studio is dpiAware but your program is not. So you form gets auto-scaled for a 96 dpi monitor and that moved the control to (17,16). Always avoid hard-coding location and sizes, get used to Sub New in VB.NET. TextBox2.Location = TextBox1.Location is also a simple workaround. – Hans Passant Sep 24 '18 at 16:49
  • @HansPassant But let's say I wanted to create TextBox 2 5 pixels below TextBox1? How would I program that in a DPI-Aware environment? – Skitzafreak Sep 24 '18 at 17:02
  • Get used to Sub New in VB.NET, that is where that code belongs. – Hans Passant Sep 24 '18 at 17:31
  • @Skitzafreak can you tell me if my answer works for you? – Simo Sep 25 '18 at 15:23

1 Answers1

1

If you want to programmatically create a new TextBox, this might help you:

Dim TextBox1 As New TextBox
    With TextBox1
        .Location = New Point(10, 10)
        .Name = "TextBox1"
        .Text = " "
        .Visible = True
    End With
 AddHandler TextBox1.Click, AddressOf TextBox1_Click
 Me.Controls.Add(TextBox1)

As we added the Hanlder for the .Click event, we have to declare the function that handles it:

Private Sub TextBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MsgBox("You clicked Me!")
End Sub

If you have another TextBox on your form, for example TextBox1 we can use its location in orther to create a new TextBox, as shown below:

Dim newTextBox As New TextBox
    With newTextBox
        .Location = New Point(TextBox1.Location.X, TextBox1.Location.Y + newTextBox.Height + 10)
        .Name = "newTextBox"
        .Visible = True
    End With
AddHandler newTextBox.Click, AddressOf newTextBox_Click
Me.Controls.Add(newTextBox)

Remarks:

Remember to rename the Function that handles the .Click event if you change the name of the button. E.G:

 AddHandler newTextBox.Click, AddressOf newTextBox_Click

and

Private Sub newTextBox_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    MsgBox("You clicked Me!")
End Sub

Clearly you can add an Handler for every TextBox events that can be handled in vb.net. TextBox.Click was just an example!

Simo
  • 955
  • 8
  • 18