How do I trigger the Painting of a rectangle over top of a DataGridView by cellmouse/click? - vb.net

How do I trigger the instantaneous painting of a rectangle over the top of some specific cell [destination: col2, row4] in a DataGridView by an entirely different cell [trigger: col1, row3] being clicked?
Obviously I picked two random cell locations and I have tried to simplify my problem to the basic chunks. Clearly they cannot be forced as is to work together. I don't have a deep enough understanding of the event handler to call one event within the other due to lack of common signatures. I think frustration has clouded my vision and ability to see any logical possibilities.
Private Sub DataGridView1_Paint(sender As Object, e As PaintEventArgs) Handles DataGridView1.Paint
Using ColBlue As New SolidBrush(Color.Blue)
e.Graphics.FillRectangle(ColBlue, x, y, width, height)
'TODO: decide loc and rect size
End Using
End Sub
Private Sub Datagridview1_CellMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles Datagridview1.CellMouseClick
'TODO: Gain a better understanding of the event handler
End Sub
My intuition tells me to write a custom sub or function, but I am not certain what they require, which eventargs to use or not use.

Thanks to Jimi for the patience in pointing out the main pieces required for my solution.
A simplified version of my code for those that find themselves lost and unable to trigger the painting a rectangle by mouse click.
Results [code]
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
‘Init new list of rectangles
Dim bluegradeT As New List(Of Rectangle) From {}‎
Dim ablue As New Rectangle
‘Programmatically adding the cells I want to paint to my list beforehand
bluegradeT.Add(DgvTall.GetCellDisplayRectangle(5, 1, False))
bluegradeT.Add(DgvTall.GetCellDisplayRectangle(7, 2, False))
bluegradeT.Add(DgvTall.GetCellDisplayRectangle(5, 5, False))
bluegradeT.Add(DgvTall.GetCellDisplayRectangle(5, 3, False))
bluegradeT.Add(DgvTall.GetCellDisplayRectangle(6, 2, False))
bluegradeT.Add(DgvTall.GetCellDisplayRectangle(4, 2, False))
End Sub
Private Sub DataGridView1_Paint(sender As Object, e As PaintEventArgs) Handles DataGridView1.Paint
‘I have multiple paint events of different colors that I wanted triggered by clicking
‘specific cells in the dgv
If DataGridView1.CurrentCell.ColumnIndex = 2 Then
If DataGridView1.CurrentCell.RowIndex = 1 Then
‘so if the clicked location is {2,1}, then paint
Using ColBlue As New SolidBrush(Color.FromArgb(50, Color.Blue))
‘this particular brush paints blue at 50 opacity
For Each ablue As Rectangle In bluegradeT
‘use a loop to retrieve all the rects stored for this paint
e.Graphics.FillRectangle(ColBlue, ablue)
Next
End Using
End If
End If
End Sub
Private Sub DataGridView1_CellMouseClick(sender As Object, e As DataGridViewCellMouseEventArgs) Handles DataGridView1.CellMouseClick
If DataGridView1.Rows(e.RowIndex).Selected Then
If DataGridView1.Columns.(e.ColumnIndex).Selected Then
‘If some cell has been selected…
DataGridView1.Invalidate(ablue)
‘trigger painting of dgv, but only in the area of tbe rectangles list
DataGridView1.Refresh()
‘to make sure the control updates immediately
End if
End If
End Sub
Notes
This began as an experiment to see what methods out on the internet can achieve the best color mixing by the required amount of work. I only really found an endless discussion board post with C++ theories and in various methodologies. I could see the only native method—aside from my clever trick--is colorblend(). Initially, color blend seemed impossibly more complex than my concept, but in truth, it is probably easier than I thought. [I’m sure someone else has done this before me, but I don’t care, today it’s my technique] Overall, it does an excellent job in combining colors that look natural by overlapping semi-transparent color rects on top of already painted DGV cells on the fly. It is undoubtedly faster than mixing colors by hand in Photoshop.

Related

How to remove/delete a shape at runtime?

I draw a hexagon at runtime in vbExpress2008:
Private Sub Panel2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Panel2.Paint
Dim Hpoint As Point
yada yada yada
e.Graphics.DrawPolygon(p, Points)
End Sub
Now how can I remove it?
As your code is now, you can't remove it. Every time that code is executed, it will draw that shape, so there's nothing to remove. If you want to remove it then there has to be something to remove. That's why you should store the data that represents the drawing in one or more fields and then get the data from there each time you want to draw. If you have a field of type List(Of Point()) then you can add and remove Point arrays as required and then force a Paint event. In the event handler, you get the current data and draw it, so anything you remove from that List will be removed from drawing. E.g.
Private polygons As New List(Of Point())
Private Sub AddPolygon(points As Point())
polygons.Add(points)
Invalidate()
End Sub
Private Sub RemovePolygon(points As Point())
polygons.Remove(points)
Invalidate()
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
For Each polygon In polygons
e.Graphics.DrawPolygon(Pens.Black, polygon)
Next
End Sub
Alternatively, if it's just one polygon that you want to show or hide, you could still hard-code it in the Paint event handler but use an If statement that tests a field of type Boolean. You can then just toggle that field and invalidate to hide and show that one polygon.

How to screen a rectangle with a keyup event?

The sun is still above the horizon. With 7:43 from Baden Austria i try to mention my titel question with some additional example.
Following the Window10 environment build 19041.985 Visual Studio Community Version 4.8.04084,
the predfined Keys of a Logitech Deluxe 250 Keyboard are not altered with the visual basic method
Sub Kein_Stress_beim_Essen(e As KeyEventArgs)
Select Case e.KeyCode
Case Keys.Space
Dim Kautchuj As Drawing.Graphics = Me.CreateGraphics
Kautchuj.DrawRectangle(New Pen(Color.PaleGreen, 2), 250, 150, 100, 50)
End Select
End Sub
.
To strengthen the sum for physical exercises, pull the sholder bladebones to the rising sun balance until pushing back without regret where i need them, the DrawRectangle is set with the form property CreateGraphics.
For more then one property i search, to use, the GDI+ objects that can be set to link a Me.KeyUp delegate with the event literature.
For my personal argument i use an additional cross to start and end a even, odd number disscusion.
I try to screen a rectangle through the case Keys.Space. While CreateGraphics is, literally, used for the aim of controls in visual basic with a rectangle object i can imagine a paint event and do not know if the key event can also be used for a object.
I have a search pattern to concatenate operators a not named function. It is not possible that everything is an object. Even with some energy exercises. To aim i fade the predefined color names to build an enum naming convention. Some dictionary brainstorm words are delegate, event eventargs, tupel, keys, select, property, method and instance.
I do not concider the possibility to make new fonts because an ime substitution is not an additional information for me.
It seems like you're asking how to draw boxes on the KeyUp event. In that case, here's a quick demo of how it should be done:
Private ReadOnly points As New List(Of Point)
Private ReadOnly rng As New Random
Private Const BOX_DIMENSION As Integer = 10
Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles MyBase.KeyUp
Select Case e.KeyCode
Case Keys.Space
'Draw a new box at a random location.
Dim x = rng.Next(ClientSize.Width)
Dim y = rng.Next(ClientSize.Height)
points.Add(New Point(x, y))
'Repaint just the area that will be occupied by the new box.
Invalidate(New Rectangle(x, y, BOX_DIMENSION + 1, BOX_DIMENSION + 1))
Case Keys.Escape
'Erase all boxes.
points.Clear()
'Repaint the whole form.
Invalidate()
End Select
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
'Draw a box at each location.
For Each point In points
e.Graphics.DrawRectangle(Pens.Red, point.X, point.Y, BOX_DIMENSION, BOX_DIMENSION)
Next
End Sub
As you can see, all the drawing is done in the Paint event handler. The KeyUp event handler updates the data that represents the drawing and then forces a repaint.

Best way to use transparent controls as invisible triggers

Once I develop a vb6 code to use transparent controls (Dont remember if I use Buttons or PictrureBoxes) with coordinates as invisible tags & invisible labels to show the names of eachone at groupal photos like facebook does. Now Im trying to recreate the same code at vb.net but I can't reach to get it work..
If I use Buttons with transparent .backcolor, no-text and no-borders, flat style, etc. to mark the photo area, they become opaque when I move the mouse over the control. if I disable becomes invisible for the mouse-over function.
If I use empty PictureBoxes instead for the same purpouse, as are empty they became invisible at runtime also for the "mouse over" function...
I dont know wich empty or invisible control must use to this finality. any suggestion?
Here is an example of what I was talking about in my comments:
Public Class Form1
Private ReadOnly actionsByRectangle As New Dictionary(Of Rectangle, Action)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'If the user clicks near the top, left corner, display a message.
actionsByRectangle.Add(New Rectangle(10, 10, 100, 100),
Sub() MessageBox.Show("Hello World"))
'If the user clicks near the bottom, right corner, minimise the form.
actionsByRectangle.Add(New Rectangle(ClientSize.Width - 110,
ClientSize.Height - 110,
100,
100),
Sub() WindowState = FormWindowState.Minimized)
End Sub
Private Sub Form1_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
For Each rectangle As Rectangle In actionsByRectangle.Keys
If rectangle.Contains(e.Location) Then
'We have found a rectangle containing the point that was clicked so execute the corresponding action.
actionsByRectangle(rectangle).Invoke()
'Don't look for any more matches.
Exit For
End If
Next
End Sub
'Uncomment the code below to see the click targets drawn on the form.
'Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
' For Each rectangle As Rectangle In actionsByRectangle.Keys
' e.Graphics.DrawRectangle(Pens.Black, rectangle)
' Next
'End Sub
End Class
Note that I have added code there that can draw the boxes on the form if you want to see them, but those are just representations of the areas, not the Rectangle values themselves.

How do I get my Windows Forms drawn user control to resize larger without clipping?

I am in the process of creating my own user control in a Windows Forms application using VB.NET, and having it change in size along with the form containing it. It looks okay so long as the window size stays constant and the control stays within its original bounds. However, if I resize the window so as to make it larger, the control's contents will resize with it but end up getting clipped at the original size. I am unsure where this is coming from and have not found any way so far to fix it.
Below is some quick sample code for a user control which can reproduce the problem I'm having:
TheCircle.vb:
Public Class TheCircle
Private _graphics As Graphics
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
_graphics = CreateGraphics()
SetStyle(ControlStyles.ResizeRedraw, True)
BackColor = Color.Red
End Sub
Private Sub TheCircle_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
_graphics.FillRectangle(Brushes.Blue, ClientRectangle)
_graphics.FillEllipse(Brushes.LimeGreen, ClientRectangle)
End Sub
End Class
I then place this user control after rebuilding the project in my main form and either dock it or anchor it (same result, but the latter helps better show where the clipping issues are). And below is a screenshot of my result when I attempt to resize the control beyond its "default" size:
The green ellipse and the blue "background" rectangle should occupy the entire control area, but they aren't (it's clipped and you see the red BackColor instead). It looks like it behaves as intended though when the control is at the original size or smaller. How can I fix this? I'm pretty new to GDI+, so I'm sure it must be right under my nose...
This is unnecessary, and a generally bad idea: _graphics = CreateGraphics()
It's bad because it's volatile. You get a one-time graphics object, draw something with it, and then the next refresh cycle, it's lost unless you keep doing it.
The proper approach is to use the Paint event, as it supplies you with the Graphics object in its PaintEventArgs and it is called every time a re-paint is required. You can ask for a re-paint at any point in your code by calling theCircle.Invalidate() (or Refresh() for a more immediate redraw).
Public Class TheCircle
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
SetStyle(ControlStyles.ResizeRedraw, True)
BackColor = Color.Red
End Sub
Private Sub TheCircle_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
e.Graphics.FillRectangle(Brushes.Blue, ClientRectangle)
e.Graphics.FillEllipse(Brushes.LimeGreen, ClientRectangle)
End Sub
End Class

How to use the Paint event more than once on a form?

Okay, so I am trying to make a program that each time you click (doesn't matter where) a random colored, and sized circle appears where you happened to click. however, the only way I can add a shape is via Paint event. here is the code I have now:
Private Sub Form1_Paint(ByVal Sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
Using Brush1 As New SolidBrush(Color.Orange)
e.Graphics.FillEllipse(Brush1, MousePosition.X, MousePosition.Y, 100, 100)
End Using
End Sub
I need to know a line of code that I can use in a mouse click event, that will re-run this sub. I know how to change the size, and make it random, I just don't know how to run this sub multiple times, more precisely; run this sub once after each mouse click. If someone can help, I would appreciate it!
Just as Plutonix explained, a refresh is handled by calling the Invalidate method.
The thing you need to remember is that whatever is painted on a surface is not persistent, so you need to redraw the whole screen every time. There are, of course, many ways in which this can be optimized for performance purposes, as this process can be extremely CPU intensive; specially, since GDI+ is not hardware accelerated.
So, what you need to do is:
Record every click (x, y position) and store it
Since the radius of each circle is random, determine the radius when the user clicks the form, then store it along with the x, y position of the click
Then, have the Paint event re-draw each stored sequence of clicks (with their respective radii) and re-draw each circle over and over.
Here's an implementation that will do the trick. Just paste this code inside any Form's class to test it:
Private Class Circle
Public ReadOnly Property Center As Point
Public ReadOnly Property Radius As Integer
Public Sub New(center As Point, radius As Integer)
Me.Center = center
Me.Radius = radius
End Sub
End Class
Private circles As New List(Of Circle)
Private radiusRandomizer As New Random()
Private Sub FormLoad(sender As Object, e As EventArgs) Handles MyBase.Load
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True) ' Not really necessary in this app...
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.SetStyle(ControlStyles.ResizeRedraw, True)
Me.SetStyle(ControlStyles.UserPaint, True)
End Sub
Private Sub FormMouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
circles.Add(New Circle(New Point(e.X, e.Y), radiusRandomizer.Next(10, 100)))
Me.Invalidate()
End Sub
Private Sub FormPaint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim g As Graphics = e.Graphics
g.Clear(Color.Black)
Using p As New Pen(Color.White)
For Each c In circles
g.DrawEllipse(p, c.Center.X - c.Radius \ 2, c.Center.Y - c.Radius \ 2, c.Radius, c.Radius)
Next
End Using
End Sub
Here's what you'll get after a few clicks on the form