I want to place a picturebox based on the location of the form, so I can move the form around and the box will stay in the same place.
However, when setting the location of the picturebox to be equal to the location of the form, as I move the form, the picturebox change location within the form.
Image 1
Image 2
You'll notice in the first image, the picturebox is close to the topleft corner of the form. This is what I expect.
When the form moves away from the corner of the screen, the picturebox moves in a similar manner.
The code relevant to this is as follows.
PictureBox2.Location = New Point(Me.Location.X, Me.Location.Y)
How can I set the location of the picturebox to be in the same place on the form.
Further Details:
Before you ask: why not make them definite values, this isn't the actual implementation that I'm after.
I'm running an OCR and using a transparent picturebox as my image capture window. However, it wont line up correctly due to the above issue.
The code used to get the image is
gfx.CopyFromScreen(New Point(Me.Location.X + PictureBox1.Location.X + 100, Me.Location.Y + PictureBox1.Location.Y + 50), New Point(0, 0), pic.Size)
However, as I move the form, the image taken is never the same relative location from the form location.
Edit: Attempt 2
Ignore my previous question as I asked it badly. Hopefully this attempt is better.
Image 3
Image 3 shows ideally what I want the form to look like. The top box of the form is transparent picturebox1. When I click the update button, I want to to take a screen shot of that picturebox1 location, and then fill a second picturebox2 below. This is what the image shows.
However, if I move the form to the around, you get the following.
Image4
You can see here the 'photo' taken that is now in picturebox2 no longer lines up perfectly, but instead the image that has been taken is offset.
I want the image captured to always be in the same location as the picturebox1.
The only code being run when the picture is taken is the following.
gfx.CopyFromScreen(New Point(Me.Location.X + PictureBox1.Location.X + 100, Me.Location.Y + PictureBox1.Location.Y + 50), New Point(0, 0), pic.Size)
PictureBox2.Image = pic
And the code at the start of the project is
Dim pic As Bitmap = New Bitmap(270, 100)
Dim gfx As Graphics = Graphics.FromImage(pic)
As the picturebox1 location is constant due to being a relative value to the form corner, the only values that are changing are me.location.x/y.
Therefore, it seems to me that the actual form moves further than the location.x/y value updates.
Why is that and how can I fix my problem?
Related
Say for example I draw a box on my screen. The box's X and Y coord will change pretty much all the time. When I am drawing the box and all of it's new position, a new box keeps appearing. I want to draw the same box, and as its location is changed, draw that same box on the new location.
Example :
Box1 : X/Y = 0,0
Box1 (new X/Y) = 0,15
I now have 2 box on my screen.
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim doo As Integer = 1
While doo = 1
For i As Integer = 0 To MonsterCount
Dim xx As Integer = GetPrivateProfileInt("iPC=" & i, "X-Int:", 0, INI)
Dim yy As Integer = GetPrivateProfileInt("iPC=" & i, "Y-Int:", 0, INI)
Box(i) = New Box(xx, yy)
If Box(i).x > -10 And Box(i).y > -10 And Box(0).x <= 1920 And Box(0).y <= 1080 Then
Dim rect As New Rectangle(Box(i).x, Box(i).y, 120, 80)
e.Graphics.DrawRectangle(Pens.Green, rect)
Invalidate()
End If
Next i
Threading.Thread.Sleep(5)
End While
End Sub
That code is very wrong. You need to handle the Paint event of the control you want to draw on and just do your drawing as it should be at that instant. All the data that describes the drawing should be stored in member variables. Any code that changes what needs to be drawn should be outside the Paint event handler. Once it has made changes that need implementing, it should call Invalidate and specify the smallest area that it reasonably can. The next time the control is painted, the Paint event handler will update the drawing and then the invalidated area will be repainted. You might check this out for an example.
In your specific case, you should declare a member variable to store the data required for the box. If the size remains the same then all you need is a Point, otherwise you should keep a Rectangle. Each time the box needs to move, you should store the new value in your field and then call Invalidate twice. The first time you should specify the old Rectangle and the second time you should specify the new Rectangle. By doing that, you ensure that any area that may have changed will be repainted but the rest of the area, which can't have changed, won't be repainted. It's the actual painting to screen, not the drawing code, that is the slow part so you should try to keep that to a minimum. If you really need the repaint done immediately then you can call Update but, otherwise, the new drawing will be displayed the next time the UI thread is free to do so.
I have a PictureBox on which a contour is drawn. Let's say this contour is in form of a circle. Now when I click a button a lot of buttons are created over the PictureBox row by row until the PictureBox is full:
For n As Integer = 1 To buttonNumberY
For m As Integer = 1 To buttonNumerX
Dim Btn As New Button
Btn.Width = elementsize
Btn.Height = elementsize
Btn.Flatstyle = Flatstyle:Flat
Btn.FlatAppearance.BorderSize = 1
Btn.FlatAppearance.BorderColor = Color.Gray
Btn.Location = new Point(elementsize*(m-1)+BORDER, maxContourHeight * scaley + BORDER - elementsize * n)
Btn.BackColor = Color.Transparent
Btn.Name = "Btn" & m & n
PictureBox1.Controls.Add(Btn)
Next
Next
As true transparency doesn't exist in WinForms I used some code so that the contour will be visible through the small buttons lying over the PictureBox (thanks for the help with this problem :)).
Now I have to determine whether a button is inside the contour or outside. I already have an idea of how to do this:
In a For Next loop every button should be checked if it has been painted.
If yes, it is partially inside the contour.
If no I have to check whether one of all the buttons under this one (in y direction) is painted.
If none of the buttons below this one is painted then it is not inside the contour.
If only one button below is painted then it is inside the contour and if two buttons are painted then it is outside of the contour again.
The problem I have is the following:
How can I check if a button is painted or not?
All the small buttons are generated through the code. Can I actually write code to check these buttons by referring to their name when they don't even exist yet in the code?
Essentially it sounds like you want to check if a point is within a circle, mathematically speaking this would be the algorithm:
(point.x - center.x) ^ 2 + (point.y - center.y) ^ 2 < radius ^ 2
In terms of your two questions, the button would be painted after you create the control. Probably not immediately, but you can force the control to be repainted dynamically by refreshing the parent.
Since you're setting the Button's name, then you could use the Form.Controls.Find method and set the searchAllChildren parameter to True.
I am trying to create a custom UI element: a panel, derived from the original panel, which is scrollable with special scrollbars (not the integrated ones) and has some other special abilities.
The actual problem is the scrolling. When I change the value of the custom scrollbar (e.g. scrolling), the panel-integrated scrollbars show up suddenly, although autoScroll = false.
Leading to the unintended state where both scrollbars are visible, the integrated and my custom one.
Private Sub ScrollB_EvValueChanged(NewVal As Integer) Handles ScrollB.EvValueChanged
Me.CleanPanel1.VerticalScroll.Value = NewVal
End Sub
How can I assign the new scrolling position (the new offset), determined by the custom scrollbar, to the panel without showing up panel-integrated scrollbars?
Sadly a panel (or usercontrol) with another panel on it and playing with the .Top and .Left properties of the inner panel to simulate scrolling is not an appropriate solution in my case.
Thank you for all your hints!
'I've been looking for methods of doing this all over, most of it is way more complicated than it needs to be, or you gotta write a whole dang program just to remove the bars to scroll. Anyhow, here's a quick, effective, neat method of doing this (since I was having trouble finding anything, I'll post it.
'e.delta detects a mouse wheel tick, if greater than 0, scroll up, less than 0 scroll down.
' the -91 part deducts some of the panel overhang (adjust as needed)
'I have buttons in this project that are 50 tall, so this scrolls perfectly for me.
'the nested if statements where there is no code (just else), tells the program to stop 'do nothing if a border is near by. The bottom of my panel, while scrolling, doesn't 'stop when the bottom of the panel (which is hanging off the bottom of the form quite 'some ways) reaches the bottom of the form, this can be adjusted by altering the 700 constant.
Private Sub DaddyPanel_MouseWheel(sender As Object, e As MouseEventArgs) Handles DaddyPanel.MouseWheel
If e.Delta < 0 Then
If (-DaddyPanel.Height - 91) > (DaddyPanel.Location.Y - 700) Then
Else
TextBox1.Text = DaddyPanel.Height & " " & DaddyPanel.Location.Y
DaddyPanel.Location = DaddyPanel.Location + New Point(0, -50)
End If
Else
If DaddyPanel.Location = New Point(0, 0) Then
Else
DaddyPanel.Location = DaddyPanel.Location + New Point(0, 50)
End If
End If
End Sub
I have to create dynamic table layout panel with some controls with auto sized rows and and fixed columns size.
My problem is that i want to show whole checkbox text .
Any help
My code is
Dim textBox2 As New CheckBox()
textBox2.Text = "You forgot to add the ColumnStyles. Do this on a sample form first with the designer. Click the Show All Files icon in the Solution Explorer window. Open the node next to the form and double-click the Designer.vb file. "
textBox2.AutoSize = True
textBox2.Dock = DockStyle.Top
'' textBox2.Size = New Point(200, 90)
Dim lbl1 As New Label()
lbl1.Location = New Point(10, 10)
lbl1.Text = "Yoer.vb"
lbl1.AutoSize = True
lbl1.Location = New Point(120, 50)
lbl1.Dock = DockStyle.Top
'' dynamicTableLayoutPanel.Padding = New Padding(2, 17, 4, 5)
dynamicTableLayoutPanel.Controls.Add(lbl1, 0, 0)
dynamicTableLayoutPanel.Controls.Add(textBox2, 1, 0)
Me.dynamicTableLayoutPanel.SetColumnSpan(textBox2, 5)
If you mean you want the table to size to the controls within it, then:
dynamicTableLayoutPanel.AutoSize = True
I know this is old, but I stumbled across it and figured I'd throw my 2 cents in in case someone else comes along.
Note: I'm using Visual Studio 2015 with .NET 4.6. Functionality may differ between versions.
The problem is that the really long text is not word-wrapping to fit within the table or form. Instead, it is set to Dock = DockStyle.Top. This will cause it to make a single line that continues on and gets clipped, similar to a single-line textbox.
If you want it to automatically word wrap, you'll need to use Dock = DockStyle.Fill. Now, this doesn't completely resolve the problem if your row or table isn't large enough to display the text. Since all of the rows are set to AutoSize, it will only do the bare minimum to fit the control vertically. It doesn't care if text gets clipped off. The end result, using your example code against a 6-column, 10-row table, is this:
Since there isn't a word wrap property, you'll need to manually fit it. Now, to do this, you'll need to change the row to be Absolute instead of AutoSize. To figure out how big to make it, you can pretty much rely on PreferredSize. This reveals a much wider Width than the existing regular Width. From that, we can determine how many lines it would take if we wrap it.
This is what my code ended up looking like:
Dim h As Single = 0
Dim chk As New CheckBox()
chk.Text = "You forgot to add the ColumnStyles. Do this on a sample form first with the designer. Click the Show All Files icon in the Solution Explorer window. Open the node next to the form and double-click the Designer.vb file. "
chk.AutoSize = True
chk.Dock = DockStyle.Fill
Dim lbl1 As New Label()
lbl1.Text = "Yoer.vb"
lbl1.AutoSize = True
lbl1.Dock = DockStyle.Top
dynamicTableLayoutPanel.Controls.Add(lbl1, 0, 0)
dynamicTableLayoutPanel.Controls.Add(chk, 1, 0)
dynamicTableLayoutPanel.SetColumnSpan(chk, 5)
' Find the preferred width, divide by actual, and round up.
' This will be how many lines it should take.
h = Math.Ceiling(chk.PreferredSize.Width / chk.Width)
' Multiply the number of lines by the current height.
h = (h * chk.PreferredSize.Height)
' Absolute size the parent row to match this new height.
dynamicTableLayoutPanel.RowStyles.Item(0) = New RowStyle(SizeType.Absolute, h)
The changes included delaring a height variable, renaming the CheckBox variable, setting its Dock to Fill, removing the Location from lbl1, and adding in size calculation. The output:
This isn't perfect since the height includes the checkbox itself, and the checkbox takes up padding, so there can be too much or too little height calculated. There are other calculations that may need to be considered. But, this is a starting point.
I want to capture the image of my webbrowser, or actually just a part of it.
I already achieved it, but it just takes a screenshot of it instead of capturing the bitmap itself.
So when i use this technique and you drag another window above it, the window is also captured. (this is what I don't want.)
My code:
' 1. Get the WebBrowsers bitmap.
Dim bmp As New Bitmap(WebBrowser1.Width, WebBrowser1.Height)
Dim BMPEndResult As Bitmap
Dim graph As Graphics = Graphics.FromImage(bmp)
Dim p As Point = Me.PointToScreen(WebBrowser1.Location)
graph.CopyFromScreen(p.X, p.Y, 0, 0, bmp.Size)
picDest.Image = bmp
So I need to get the image of the webbrowser:
- without the scrollbars if possible
- Even if the window is minimized or in the task bar
- Full webbrowser
- and also if possible just a part of it, where I can specify the top, left, width and height
WebBrowser.DrawToBitmap(bitmap, rectangle)