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.
Related
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.
I'm currently making a game, it contains a paddle (called base) that must move from left to right only.
I found a piece of code that allowed the platform to move, however it moves in all directions and isn't synced with my mouse pointer properly:
Private Sub Form1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
base.Location = MousePosition
End Sub
What do I need to change or add in order for the paddle to only move horizontally?
Assume your paddle (I'm naming the Control paddle here, base is not a good name) is placed near the bottom of the Form, its Height ~25 pixels and its bottom distance from the Form's bottom side ~10-20 pixels.
You can clip the Cursor to a narrow band right above it when the Mouse enters the Form.
You can then move the Cursor without intersecting other Controls in the Form, which could interfere with the generation of MouseMove events.
You can also hide the Cursor, so the arrow pointer doesn't become visually obnoxious (unless it's required for something else, of course).
When the Cursor is moved, the movement is translated to the middle of the paddle Control, which is moved only to the left or right, in relation to the current Cursor offset:
(PointToClient(Cursor.Position).X - (paddle.Width \ 2))
When the Form closes, restore the Cursor and the clipping region.
Paste this code inside the Form that contains the paddle (and rename base to paddle):
Protected Overrides Sub OnMouseEnter(e As EventArgs)
MyBase.OnMouseEnter(e)
ClipCursor()
End Sub
Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
MyBase.OnMouseMove(e)
paddle.Left = PointToClient(Cursor.Position).X - (paddle.Width \ 2)
End Sub
Protected Overrides Sub OnFormClosing(e As FormClosingEventArgs)
ShowCursor()
MyBase.OnFormClosing(e)
End Sub
Private Sub ClipCursor()
Dim bandLocation = New Point(
Left + 8 + (paddle.Width \ 2),
Bottom - paddle.Height * 2 - Cursor.Size.Height)
Dim bandSize = New Size(ClientSize.Width - paddle.Width, 20)
Cursor.Clip = New Rectangle(bandLocation, bandSize)
Cursor.Hide()
End Sub
Private Sub ShowCursor()
Cursor.Clip = Rectangle.Empty
Cursor.Show()
End Sub
You can accomplish this by only assigning the X coordinate to the location property:
base.Location = New Point(Cursor.Position.X, Button1.Location.Y)
This will ignore the Y coordinate, resulting only in horizontal movement. Also, be aware that depending on your situation, you may have to translate the mouse pointer coordinates relative to the window. So, in case the result is distorted, do it like this:
base.Location = New Point(PointToClient(Cursor.Position).X, Button1.Location.Y)
This will translate the mouse coordinates (from e.g. Cursor.Position property) into window-relative coordinates.
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.
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
I am going to have a form with 60 Line Shapes (Using Visual Studios PowerPack). I would like the user to be able to rotate the shapes 90 Degrees using the left and right buttons on the keyboard.
What would be the best way to do this? I have tried other methods however this amounts to 1000's of lines of code, I am still learning and I want to know the best practices.
Thanks a lot!
I'm assuming for the moment that you've already written the part to handle the geometry once, and are asking about how to re-use the code, without duplicating it for 60 lines. This matters because it's not 100% clear from the question whether you're rotating around the mid-point or around the starting point, as the LineShape type does make a distinction between the Starting and Ending points. Without that information, I can't write the geometry code for you.
The first part isn't so bad. We just setup a few methods that can handle rotating any line:
'Note that rotating a line 90 degrees around it's midpoint
' will give the same result whether you go clockwise or counterclockwise,
' but I figure you'll want to adapt this for other shapes later, or that
' you're rotating around the line's starting point
Private Sub RotateClockwise(ByVal line As LineShape)
'Code to rotate the passed line clockwise here
Dim x1 As Integer = line.X1
Dim y1 As Integer = line.Y1
Dim x2 As Integer = line.X2
Dim y2 As Integer = line.Y2
End Sub
Private Sub RotateCounterclockwise(ByVal line As LineShape)
'Code to rotate the passed line counter-clockwise here
End Sub
Private Sub LineShape_KeyDown(Byval sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs)
'Which line?
Dim line As LineShape = TryCast(sender, LineShape)
If line Is Nothing Then Exit Sub
'Left key?
If e.KeyCode = Keys.Left Then RotateCounterclockwise(line)
'Right key?
If e.KeyCode = Keys.Right Then RotateClockwise(line)
End Sub
This is where it gets tricky. Notice that the event handler above is missing the Handles keyword. We want to hookup the KeyDown event handler for all of your LineShape controls to this one method. This will be a bit repetitive, as it means one additional line of code for each line on your form, but it's better than needing to write the above code for all of your lines:
Dim Lines As New List(Of LineShape)()
Lines.Add(LineShape1)
Lines.Add(LineShape2)
'...
Lines.Add(LineShape60)
For Each Line As LineShape In Lines
AddHandler Line.KeyDown, AddressOf LineShape_KeyDown
Next
That code goes in your form's constructor after the InitializeComponent() method.
I could do better still if the LineShape type were a true control (For EAch Line In Me.Controls.OfType(Of LineShape)()), but the docs show this is actually a Component, and not a Control.
Alternatively, you can subclass LineShape and build "rotatability" into your new class as :
Imports Microsoft.VisualBasic.PowerPacks
Public Class MySmartLine
Inherits LineShape
Private Sub RotateClockwise()
'Code to rotate clockwise here
Me.X1 = ...
Me.X2 = ...
End Sub
Private Sub RotateAntiClockwise()
'Code to rotate anti clockwise here
End Sub
Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
MyBase.OnKeyDown(e)
If e.KeyCode = Keys.Left Then
RotateAntiClockwise()
End If
If e.KeyCode = Keys.Right Then
RotateClockwise()
End If
End Sub
End Class
After building your project, a custom MySmartLine component will appear in your toolbox and you can use it in place of LineShape.