Set postition of New Form related to Control - vb.net

I'm stuck with basic's.
Here I need to place New Form "myForm2" in place of DataGridView's "myDgv" location.
Here is my approach:
Dim fl As New myForm2
fl.StartPosition = FormStartPosition.Manual
Dim p As Point = Me.PointToScreen(myDgv.Location)
fl.Location = p
fl.Show(Me)
Showed code places myForm2 at top-left position of the screen.
How to get it to place myForm2 at the top-left position of myDgv?

First, get the screen-coordinates of the grid:
Dim pt As Point = myDgv.PointToScreen(Point.Empty)
Then set the location of the form:
fl.Location = pt

Related

TabControl_DrawItem tab color from Right to left

I'm trying to change tab control tab color by OwnerDrawFixed and I have this code bellow working perfectly, but I have multiple language application and I need to change the layout from lift to right and from right to left depends on application language, I need help to make this code drowse from right to left when the RightToLiftLayout = true, and from left to right (current code) when its false.
thank you .
'Firstly we'll define some parameters.
Dim CurrentTab As TabPage = TabControl1.TabPages(e.Index)
Dim ItemRect As Rectangle = TabControl1.GetTabRect(e.Index)
Dim FillBrush As New SolidBrush(Color.Red)
Dim TextBrush As New SolidBrush(Color.White)
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
sf.LineAlignment = StringAlignment.Center
'If we are currently painting the Selected TabItem we'll
'change the brush colors and inflate the rectangle.
If CBool(e.State And DrawItemState.Selected) Then
FillBrush.Color = Color.White
TextBrush.Color = Color.Red
ItemRect.Inflate(2, 2)
End If
'Set up rotation for left and right aligned tabs
If TabControl1.Alignment = TabAlignment.Left Or TabControl1.Alignment = TabAlignment.Right Then
Dim RotateAngle As Single = 90
If TabControl1.Alignment = TabAlignment.Left Then RotateAngle = 270
Dim cp As New PointF(ItemRect.Left + (ItemRect.Width \ 2), ItemRect.Top + (ItemRect.Height \ 2))
e.Graphics.TranslateTransform(cp.X, cp.Y)
e.Graphics.RotateTransform(RotateAngle)
ItemRect = New Rectangle(-(ItemRect.Height \ 2), -(ItemRect.Width \ 2), ItemRect.Height, ItemRect.Width)
End If
'Next we'll paint the TabItem with our Fill Brush
e.Graphics.FillRectangle(FillBrush, ItemRect)
'Now draw the text.
e.Graphics.DrawString(CurrentTab.Text, e.Font, TextBrush, RectangleF.op_Implicit(ItemRect), sf)
'Reset any Graphics rotation
e.Graphics.ResetTransform()
'Finally, we should Dispose of our brushes.
FillBrush.Dispose()
TextBrush.Dispose()
This is untested but I think that you should be able to change this:
Dim sf As New StringFormat
to this:
Dim sf = If(RightToLeft,
New StringFormat(StringFormatFlags.DirectionRightToLeft),
New StringFormat)
You may need to use RightToLeftLayout rather than RightToLeft. I'm not sure as it's not something that I've ever done.

Positioning UserControl relative to Form or Screen

Is there any way to get and set the .Location of an UserControl, which is positioned on a Container (e.g. a Panel) relative to the "most-parental" Form?
I know that there is the possibility of calculating the offset of the Panel itself and adding it to the .Location of the UserControl.
But in my case the number of parent-levels is unknown and can differ from case to case.
So once the UserControl could be placed on a Panel which is directly on the Form. But there is also the possibility that the UserControl is placed on a 2nd Panel which is on the 1st Panel which is on the Form.
What if you take your idea of calculating the offset of the Panel and calculate the offset recursively back to the Form? i.e. I have a Textbox1 within a Panel2 within a Panel1. Panel1 is located at .Left 266, Panel2 is at .Left 77 within Panel1.
Private Function GetLeftOffset(ByVal UserControl As Control) As Int32
Dim intLeftOffset As Int32 = 0
If Not TypeOf UserControl.Parent Is Form Then
intLeftOffset = UserControl.Parent.Left
intLeftOffset += GetLeftOffset(UserControl.Parent)
End If
Return intLeftOffset
End Function
Now if I GetLeftOffset(Me.TextBox1), it returns an Offset of 343 (266 + 77).
I use this function to place a context menu near a control like a textbox or button. You can set x and y to zero to return the location of a control itself.
'--- Return the screen location of a control with an offset
Private Function Offset(ByRef controlObj As Control, ByVal x As Integer, ByVal y As Integer) As Point
Dim pt As Point
Dim parentObj As Control = controlObj.Parent
Do While parentObj IsNot controlObj.FindForm
x += parentObj.Location.X
y += parentObj.Location.Y
parentObj = parentObj.Parent
Loop
pt = PointToScreen(controlObj.Location)
pt.Offset(x, y)
Return pt
End Function
Try:
Dim pnt As Point
pnt = UserControl.PointToScreen(New Point(0, 0))
pnt = Me.PointToClient(pnt)
This calculates the location relative to your Form. Change Me to any control, if you like
Now, if you want to set the location eg (100, 100), relative to your Form
pnt = Me.PointToScreen(New Point(100, 100))
pnt = UserControl.Parent.PointToClient(pnt)
UserControl.Location = pnt
Remember that, if the new location is outside the parent area the control will not be visible.

Position a textbox on a control in a tablelayoutpanel

I have a table layout panel on my form.
I have put a usercontrol in one if its cells.
Now I would like to position a textbox above this usercontrol, but I am not sure how to do the positioning.
The textbox is located on the form, not in the tablelayoutpanel.
I have tried a lot with .PointToScreen, but somehow I could not get it right.
The closest I could get was
Dim pt As Point
Me._ucGrid1.PointToScreen(Me._ucGrid1.Location)
Dim iGridOffsetTop As Integer = Me._ucGrid1.Top + pt.Y
Dim iGridOffsetLeft As Integer = Me._ucGrid1.Left + pt.X
But I guess that did not take the position of the table layout panel into account.
Could somebody please tell me where I went wrong?
Thank you!
Got it:
Dim iGridOffsetTop As Integer = Me._ucGrid1.Top
Dim iGridOffsetLeft As Integer = Me._ucGrid1.Left
Dim pt As Point
pt = Me.TableLayoutPanel1.Location
iGridOffsetLeft += pt.X
iGridOffsetTop += pt.Y

How to get child datagrid values

How can I save values in child popup DataGridView?
I am having parent datagridview and child DataGridView in vb.net
Consider I have 2 columns and 2 rows.
When I click 1st column, I will get child DataGridView just near to this cell. Child DataGridView also has 2 rows and 2 columns where I can enter values.
When I click 2nd column, I'll get another new child DataGridView near this cell.
Now if I move back to first column, values I entered are lost. How can I save entered values in popup child window?
Here is my code:
sub cell_click Dim _pointCell As Point = Me.DgV.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True).Location Dim _pointGrid As Point = DgV.Location Dim _pointLocation As Point _pointLocation.X = _pointCell.X 'width _pointLocation.Y = _pointCell.Y 'height SelectionInGrid() mPopup.Show(DgV.PointToScreen(New Point(_pointLocation.X, _pointLocation.Y))) end sub
Public SelectionInGrid() Dim t1,t2 As New DataGridViewTextBoxColumn() Dim gv As New DataGridView
gv.Columns.Add(t1)
gv.Columns.Add(t2)
gv.Columns(0).HeaderText = "Employee"
gv.Columns(1).HeaderText = "Currency"
gv.Width = t1.Width + t2.Width
Dim mControlHost As ToolStripControlHost = New ToolStripControlHost(gv)
mControlHost.Padding = Padding.Empty
mControlHost.AutoSize = False
mPopup = New ToolStripDropDown()
mPopup.Padding = Padding.Empty
mPopup.Items.Add(mControlHost)
End
sub cell_click
Dim _pointCell As Point = Me.DgV.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True).Location
Dim _pointGrid As Point = DgV.Location
Dim _pointLocation As Point
_pointLocation.X = _pointCell.X 'width
_pointLocation.Y = _pointCell.Y 'height
SelectionInGrid()
mPopup.Show(DgV.PointToScreen(New Point(_pointLocation.X, _pointLocation.Y)))
end sub
Public SelectionInGrid()
Dim t1,t2 As New DataGridViewTextBoxColumn()
Dim gv As New DataGridView
gv.Columns.Add(t1)
gv.Columns.Add(t2)
gv.Columns(0).HeaderText = "Employee"
gv.Columns(1).HeaderText = "Currency"
gv.Width = t1.Width + t2.Width
Dim mControlHost As ToolStripControlHost = New ToolStripControlHost(gv)
mControlHost.Padding = Padding.Empty
mControlHost.AutoSize = False
mPopup = New ToolStripDropDown()
mPopup.Padding = Padding.Empty
mPopup.Items.Add(mControlHost)
End
The problem lies in the SelectionInGrid Sub which is called every single time you click a cell. In this function you have these lines:
Dim gv As New DataGridView
Dim mControlHost As ToolStripControlHost = New ToolStripControlHost(gv)
mPopup = New ToolStripDropDown()
This means that everytime cell_click runs a new DataGridView, a new ToolStripControlHost and a new ToolStripDropDown are created. To solve this you need to keep track of the different ToolStripDropDowns. For example using a dictionary:
Private PopUps As New Dictionary(Of String, ToolStripDropDown)
sub cell_click
Dim _pointCell As Point = Me.DgV.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, True).Location
Dim _pointGrid As Point = DgV.Location
Dim _pointLocation As Point
_pointLocation.X = _pointCell.X 'width
_pointLocation.Y = _pointCell.Y 'height
If PopUps.ContainsKey(<Parent Selected cell identifyer>) Then
mPopup = PopUps(<Parent Selected cell identifyer>)
Else
SelectionInGrid()
PopUps.Add(<Parent Selected cell identifyer>,mPopup)
End If
mPopup.Show(DgV.PointToScreen(New Point(_pointLocation.X, _pointLocation.Y)))
end sub
I do believe this should work. "Parent Selected cell identifyer" must be something unique from the Parent DGV row/cell that was clicked.

Treat the two set separately

The woes of a programming newbie... In my program.
I am calculating and displaying how many calories a person needs to maintain current weight. I have 2 sets of 2 radioButtons: 1 set is for the gender, male or female, the other set is for their activity rate, active or inactive.
With two different sets of radioButtons, one from each should be able to be selected, however only one radio button is being selected at a time, how can I tell the program to treat the two sets of radio buttons separately?
You should use GroupBoxes to put a set of radiobuttons inside a groupbox and the other set inside another Group box
In this way every set of radiobuttons is isolated from the other set and works as expected
The following code is just an example of a form build manually, working with the designer will create an equivalent of this code for you inside the InitializeComponent method. Note how the two radiobutton sets are childs of a different container (the groupbox)
' A generic form
Dim f as Form = new Form()
f.Size = new Size(300, 500)
' Create a Group box
Dim b1 as GroupBox = new GroupBox()
b1.Text = "Gender"
b1.Location = new Point(0,0)
' Create two radiobutton for Gender
Dim r1 as RadioButton = new RadioButton()
r1.Text = "Male"
r1.Location = new Point(5,15)
Dim r2 As RadioButton = new RadioButton()
r2.Text = "Female"
r2.Location = new Point(5, 40)
' Add the two radiobuttons to the GroupBox control collection
b1.Controls.AddRange(new Control() {r1, r2})
' Repeat for the second set of radiobuttons
Dim b2 as GroupBox = new GroupBox()
b2.Text = "Activity Rate"
b2.Location = new Point(0,100)
Dim r3 As RadioButton = new RadioButton()
r3.Text = "Active"
r3.Location = new Point(5,15)
Dim r4 as RadioButton = new RadioButton()
r4.Text = "Inactive"
r4.Location = new Point(5,40)
b2.Controls.AddRange(new Control() {r3, r4})
' Finally add the GroupBoxes to the Form ControlsCollection
f.Controls.AddRange(new Control() {b1, b2})
f.ShowDialog()
Radio buttons work in groups. Separate them with a container and your good.