VB.Net Custom Bitmap - vb.net

Its a bit complicated and I will try my best to explain what I want to achieve.
I've already worked a bit with bitmaps and copy from screen functions.
This all worked very well. But these bitmaps are always rectangles and I would like to use my own bitmap if possible.
As an example:
Somewhere at position x, y on my screen is a map
This map has several paths and junctions.
There are also houses and things that don't interest me, I only focus on the paths in between.
Now I want to scan this map for Argb Pixels using a bitmap and Copy from screen function. I have already done this and it works great, but instead of only scanning the paths for pixels, the whole map is scanned for pixels. But I only want these paths to be scanned.
I have this map as a template and could make a screenshot of it. Can I now import this map into Photoshop, color the houses and everything that I don't need black and make the paths transparent and import them as bitmap so that the Copy From Screen function only scans the paths or is that even possible? I haven't found anything for vb.net if someone could lead me in a right direction I would be very thankful :)
This is the code I got so far - simple pixelsearch function:
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim xd3 = Color.FromArgb(255, 100, 100, 100) 'Searching for this color on the screen
Dim b As New Bitmap(2210, 1100) 'Position of Bitmap
Dim g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(b)
g.CopyFromScreen(Me.Left, Me.Top, 0, 0, b.Size) 'Searching on Screen
For i = 0 To (Me.Width - 0) 'searching each pixel
For j = 0 To (Me.Height - 0) 'searching each pixel
If b.GetPixel(i, j) = xd3 Then 'If pixel has same color that im searching for it will show a messagebox true
MessageBox.Show("true")
End If
Next
Next
End Sub

Related

My image in a picture box is not rotating on keypressed

I am doing a car parking game.i am using the arrow keys to move it,but when the down key is pressed,the picture box does not move down.Also ,when the right or up keys are pressed,the picture box does not stop.I want also to rotate the car while moving right or left.I tried but was not able.
Private Sub Timerdiagonalright_Tick(sender As Object, e As EventArgs) Handles Timerdiagonalright.Tick
RotateImage(pbcar1.Image, 20)
End Sub
Private Function RotateImage(img As Image, angle As Single) As Bitmap
' the calling code is responsible for (and must)
' disposing of the bitmap returned
Dim retBMP As New Bitmap(img.Width, img.Height)
retBMP.SetResolution(img.HorizontalResolution, img.VerticalResolution)
Using g = Graphics.FromImage(retBMP)
' rotate aroung the center of the image
g.TranslateTransform(img.Width \ 2, img.Height \ 2)
'rotate
g.RotateTransform(angle)
g.TranslateTransform(-img.Width \ 2, -img.Height \ 2)
'draw image to the bitmap
g.DrawImage(img, New PointF(0, 0))
Return retBMP
End Using
End Function
If the image is already loaded to your PictureBox, your can use
PictureBox.Image.RotateFlip(RotateFlipType)
to rotate your image.
Please note that this is not an efficient way to do animated graphics; to improve performance a little when moving controls, consider reading on SuspendLayout / ResumeLayout and BeginUpdate / EndUpdate.

Visual Basic Forms Rotating text within a label

Basically I need to have text within a label, or other container of a given size that can be rotated. But act like a label; the text wraps to next line when it can't fit on one line and is centre aligned.
Looking around I found graphics.DrawString and graphics.RotateTransform I tried messing around with them using some tutorials and managed to rotate text to 90 degrees using this.
Private Sub painted(sender As Object, e As PaintEventArgs) Handles label1.Paint
Dim fontObj As Font
fontObj = New System.Drawing.Font("Times", 10, FontStyle.Bold)
e.Graphics.TranslateTransform(sender.width - 15, 10)
e.Graphics.RotateTransform(90)
e.Graphics.DrawString("Test", fontObj, Brushes.Black, 0, 0)
End Sub
However this doesn't solve the problem of text wrapping and I'm still not entirely sure how exactly this works. I'm looking for a sub that could take parameters of a label control, a string, and a rotation angle(90,180,270) and then draw that string inside the control so that it is all visible without changing the size of the control.
So my question is: is it possible? and if so where do I start and how should I go about it?

Find Bounds of GDI+ Shape

Hi I'm trying to get a rectangle that completely surrounds a shape drawn via GDI+ when the pen is thick.
This is my test code to demo which I just added to mybase.load to test out..
Dim bmp As New Bitmap(500, 500)
Dim g As Graphics = Graphics.FromImage(bmp)
g.Clear(Color.Transparent)
g.SmoothingMode = SmoothingMode.HighQuality
g.PixelOffsetMode = PixelOffsetMode.Default
' Setup Matrix
Dim mat As New Matrix
mat.Translate(100, 100)
g.Transform = mat
' Draw Lines and Fill
Dim gp As New GraphicsPath
gp.AddLines({New Point(50, 0), New Point(100, 100), New Point(0, 100)})
gp.CloseAllFigures() ' Closes Open Path (ie join back to origin)
g.FillPath(New SolidBrush(Color.Beige), gp)
' Add Border to Graphics Path
g.DrawPath(New Pen(New SolidBrush(Color.Black), 20), gp)
g.DrawRectangle(New Pen(New SolidBrush(Color.Red), 1), Rectangle.Truncate(gp.GetBounds))
' Tidy Up
g.ResetTransform()
mat.Dispose()
' Set Picturebox Value
PictureBox1.Image = bmp
I'd post the image but the forum doesn't let me.
I want the bounding rectangle to include the pen width too. I used the above triangle to demo that I cant just add penwidth/2.
Any ideas?
Julian
If that is sufficient for your needs you can simply set the pen's .Alignment property to Inset like so:
g.DrawPath(New Pen(New SolidBrush(Color.Black), 20) With {.Alignment = PenAlignment.Inset}, gp)
This basically tells the pen to draw itself on the inside of the path at all times. Default is that it draws itself on the middle which leads to the situation that the outside width at edges is dependant on the angle of the edge.
Result is:
Just in case anyone else struggles like i did trying to find a solution then this is what I did in the end. I gave up trying to do using some form of getbounds method.
My solution in the was to scan the rendered bitmap instead to calculate the bounds based on pixels that were non-transparent (the background of my rendered image(s)). In fact I only need to scan once on the combined image and it takes a fraction of a second to calculate the "true" bounds now.
I used this article Fit a PictureBox to its non-transparent pixels to achieve a starting point that proved the concept and gave me a region that I could do a "getbounds" on. Then I swapped out the slow getpixel method for the lockbits example at Work with bitmaps faster in C# and voila!
Just ran all the code through an online c# to vb convertor and pasted it together to get completely working in less than an hour.
Took a fraction of the time I wasted trying to find a solution on the internet that would work directly on the vector image.
Julian

How to solve 'Generic error occured in GDI+'

Goal
To be able to paint rows in my DataGridViews in order to help a user better understand what is going on in the application. Take this image for an example:
Light red = Deleted
Yellow = Relationship to the Option Type Select (top left)
Bright Red = Deleted & Related to the Option Type Selected (top left)
Problem
When I go up / down in my Option Types DataGridView, it will paint the Mandatory and Additional sections depending on which Option Type I choose. After doing this for a while (70 or so times), I get the generic error in the GDI.
As you can see in the screenshot above, one of the additional edit buttons are not displayed correctly (this is where the error occurs). It is always on the following line:
ico = Icon.FromHandle(bmpFind.GetHicon)
See complete code below:
Code
Private Sub dgvAdditionalOptions_CellPainting(sender As Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgvAdditionalOptions.CellPainting
'Dim bmpFind As Bitmap
Dim drRow As HunterManagement.dtConveyorFunctionAdditionalOptionsRow
Dim myOptn As clsOptions
If dgvAdditionalOptions.Columns(e.ColumnIndex).Name = "ColBtnEditAdditional" AndAlso e.RowIndex >= 0 Then
drRow = dsHunterManagement.dtConveyorFunctionAdditionalOptions.FindByPK_ConveyorFunctionAdditionalOption(dgvAdditionalOptions.Rows(e.RowIndex).Cells("PK_ConveyorFunctionAdditionalOption").Value)
myOptn = New clsOptions(CInt(drRow.FK_Option))
e.Paint(e.CellBounds, DataGridViewPaintParts.All)
If Not drRow Is Nothing AndAlso myOptn.InDrawing Then
Using bmpFind As Bitmap = My.Resources.Edit_16x16_2 'Use 16x16 PNG / BitMap images
Using ico As Icon = Icon.FromHandle(bmpFind.GetHicon)
e.Graphics.DrawIcon(ico, e.CellBounds.Left + 3, e.CellBounds.Top + 2.5)
e.Handled = True
End Using
End Using
Else
Using bmpFind As Bitmap = My.Resources.Edit_Disabled_16x16_2 'Use 16x16 PNG / BitMap images
Using ico As Icon = Icon.FromHandle(bmpFind.GetHicon)
e.Graphics.DrawIcon(ico, e.CellBounds.Left + 3, e.CellBounds.Top + 2.5)
e.Handled = True
End Using
End Using
End If
ElseIf dgvAdditionalOptions.Columns(e.ColumnIndex).Name = "ColBtnDeleteAdditional" AndAlso e.RowIndex >= 0 Then
e.Paint(e.CellBounds, DataGridViewPaintParts.All)
Using bmpFind As Bitmap = My.Resources.Delete_16x16 'Use 16x16 PNG / BitMap images
Using ico As Icon = Icon.FromHandle(bmpFind.GetHicon)
e.Graphics.DrawIcon(ico, e.CellBounds.Left + 2, e.CellBounds.Top + 2.5)
e.Handled = True
End Using
End Using
End If
End Sub
I tried searching this problem and it is all related to 'saving' an image... I am not saving an image though, I am only getting the icon of a BMP image. I must be forgetting to dispose something.
Any ideas?
Typically this error is caused my a gdi+ leak. You need to Dispose the Icon which is a gdi+ resource. Add ico.Dispose once you're done with it.
When using Icon.FromHandle, you need to manually clean it up via DestroyIcon API.
When using this method you must dispose of the resulting icon using
the DestroyIcon method in the Win32 API to ensure the resources are
released.
Refer this answer, Hans gives a workaround for this problem.
Also note that you must Dispose the Bitmap also when you get it from Resources.YourBitmap because Resources.YourBitmap basically creates a new bitmap everytime it is called. Bitmap is also a gdi+ resource, you ought to dispose that also.
As #Hanspassant noted in comments prefer Using statements to Dispose the resources. They provide a convenient and reliable way of disposing a resource.

DataGridViewButtonColumn icon

i am using vb.net 2.0 and i would like to set an icon or image in a DataGridViewButtonColumn. I know the class has no member for it. Anyone has an idea?
Best answer is from http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/b0dfb55c-8bad-4c2d-aa72-36d8c138484e/
But as usual, you Google vb.Net and get answers in C#. I use C# to vb.net tool on the developerfusionwebsite to help me convert to vb.net but usually end up changing a fair amount.
Once you have a pointer this one is quite easy really.
In the dataGridView_CellPainting event add something like this
Private Sub InvoiceLinesDataGridView_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles InvoiceLinesDataGridView.CellPainting
If e.ColumnIndex = 3 AndAlso e.RowIndex >= 0 Then
e.Paint(e.CellBounds, DataGridViewPaintParts.All)
Dim bmpFind As Bitmap = My.Resources.binoc16_h1
Dim ico As Icon = Icon.FromHandle(bmpFind.GetHicon)
e.Graphics.DrawIcon(ico, e.CellBounds.Left + 3, e.CellBounds.Top + 3)
e.Handled = True
End If
End Sub
Just to explain this a little, I wanted to use a resource which is a bitmap so I am converting that to an icon also. This works really well for me and I get a proper button column with an image. The column index is a bit rough as that could change so I was looking to refer using the column name - shouldn't be too hard but you get the idea. SO much easier than the other options I have see around that get you making an extended custom column type.
This really should have just been part of the original control and I cannot fathom why MS crippled the grid so much. I have been trying to use third party controls like Telerik but the originals always seem to be more stable so am now seeing if I can stick with vanilla controls and adding my on extensions where required.
I created a method that can be called in the CellPainting datagridview event.
Public Shared Sub SetImageToDataGridViewButtonColumn_CallInCellPaintingEvent(ByRef img As Bitmap, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs)
e.Paint(e.CellBounds, DataGridViewPaintParts.All & (DataGridViewPaintParts.ContentBackground) & (DataGridViewPaintParts.ContentForeground))
Dim destRect As Rectangle = New Rectangle(e.CellBounds.X + (e.CellBounds.Width - img.Width) / 2, e.CellBounds.Y + (e.CellBounds.Height - img.Height) / 2, img.Width, img.Height)
Dim srcRect As Rectangle = New Rectangle(0, 0, img.Width, img.Height)
e.Graphics.DrawImage(img, destRect, srcRect, GraphicsUnit.Pixel)
e.Handled = True
End Sub
In the CellPainting event, call this method passing the image you want on the button and e. Ensure you use some sort of condition to set on the column you need, this example the If specifies column 0. Also notice I have my image in My.Resources:
Private Sub dgv_CellPainting(sender As Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgv.CellPainting
If (e.ColumnIndex = 0 And e.RowIndex >= 0) Then
SetImageToDataGridViewButtonColumn_CallInCellPaintingEvent(My.Resources.myImg, e)
End If
End Sub
Tips: I found 16x16 png were perfect for my use. You can resize using http://images.my-addr.com/resize_png_online_tool-free_png_resizer_for_web.php
You can try using a DataGridViewImageColumn add attach an event to the grid's CellContentClick event (in the event process only the events comming from the column/columns that is/are images)