Using GetWindowDC for drawing - vb.net

I'm having difficulties in using Win API GetWindowDC to get a valid hDC for drawing.
I'm using vb.net 2013, and I tried to bitblt images to a form, draw string, draw rectangle, and nothing.
I'm running in Win7 all the tests.
Do I have to disable aero with DWM functions, is it a handle trick, or what is? I already posted a "draw in titlebar vb.net 2013" question that had no answer, where I have some code used, but right now, I just need a working example to start. All help is appreciated.
But here goes some more code that doesn't work either.
Select Case m.Msg
Case WinAPI.Win32Messages.WM_NCPAINT
Dim hDC As IntPtr = WinAPI.GetWindowDC(m.HWnd)
Dim g As Graphics = Graphics.FromHwnd(hDC)
g.DrawString("TESTE", New Font("ARIAL", 16), New SolidBrush(Color.Black), 5, 5)
g.Dispose()
WinAPI.ReleaseDC(m.HWnd, hDC)
The error is OutOfMemory, and nothing gets drawn anywhere, even with tests done to clientarea.
It's a simple purpose. Getting to draw in all the areas of a form, and from that on, I'll handle the drawing.
Well, thanks at least for the help on correctly editing. About the Graphics.FromHDC, yes, I tried it.
But here goes some more code that doesn't work either.
Select Case m.Msg
Case WinAPI.Win32Messages.WM_NCPAINT
Dim hDC As IntPtr = WinAPI.GetWindowDC(m.HWnd)
Dim g As Graphics = Graphics.FromHwnd(hDC)
g.DrawString("TESTE", New Font("ARIAL", 16), New SolidBrush(Color.Black), 5, 5)
g.Dispose()
WinAPI.ReleaseDC(m.HWnd, hDC)
The error is OutOfMemory, and nothing gets drawn anywhere, even with tests done to clientarea.
It's a simple purpose. Getting to draw in all the areas of a form, and from that on, I'll handle the drawing. And too bad for the negative votes. Doesn't help, cause if people where fast on the negative voting...try to be as fast on reading all of what's placed in a question, and finding out that it is not just "gimme gimme codez" - the other referenced question has code.
People that know a lot forget that once you where like me, and didn't know a lot about the subject...might not even know how to ask the right questions...
Thanks for the help, if someone can provide it.

Graphics.FromHwnd() takes a window handle, not a DC (the clue is in the name). Try Graphics.FromHdc() instead.

Related

Display SQL geometry in VB Picturebox

My first post here and somewhat new to VB.NET, so I'm aware that I may breach some protocols. So please be patient.
A bit of background on what I'm trying to do. I've created a Windows form with a picturebox that the user can draw objects on (representing walls, doors, etc). The coordinates for the objects are saved in a SQL backend (think of it as vector drawing in a Paint like interface). The next step is to move a light source (like a person) walking through the object. I've created a light polygon in SQL representing a crude 2D raytrace and created a difference of this from the mat's polygon. Essentially this difference represents the light paths where objects can be seen.
The last step, and the one I'm stuck on, is how to display the final geometry I create (a complex curvepolygon) on the picturebox which will essentially cover up the objects that are not lit by the light source yet. At it's most basic, how do you import a geometry from SQL and then display it in a picturebox in a windows form/picturebox.
Thanks and appreciate any help. Bear in mind that I'm somewhat new to .NET, and am using this project as a way to teach myself VB.NET and SQL.
A little disappointed that there is nobody that can answer this question, but it happens. So I came up with a workaround that while not ideal, will hopefully help someone else stuck in the same situation. Maybe someone will see this and come up with a more elegant solution.
So once I have my final "shadow" polygon, I can't find a VB.NET solution to draw it as is, but that doesn't mean I can't convert it to a format that is possible to draw in a picturebox. Here's the code I came up with:
Private Sub createShadows()
Dim myPen As Pen
Dim myBrush As Brush
Dim myPoints As Point()
Dim listPoints As New List(Of Point)
Dim x As Double
Dim y As Double
' Convert the complex shape into a polygon shape in SQL and bring all the vertex
' points into VB and put into a string variable (curBlack)
mConn.Open()
Dim cmd = New SqlCommand("Select CurrentBlack.STCurveToLine().STAsText() From tbl_Map_Master Where MapID = " &
cmbDN.SelectedItem(0), mConn)
Dim curBlack As String = cmd.ExecuteScalar
mConn.Close()
' Now parse the vertex points from SQL format into a set of VB points
curBlack = curBlack.Replace("POLYGON ((", "").Replace(")", "") & ",,"
While curBlack.Length > 1
x = CInt(Strings.Left(curBlack, InStr(curBlack, " "))) * iZoom + centerX
curBlack = Strings.Right(curBlack, Len(curBlack) - InStr(curBlack, " "))
y = CInt(Strings.Left(curBlack, InStr(curBlack, ",") - 1)) * iZoom + centerY
curBlack = Strings.Right(curBlack, Len(curBlack) - InStr(curBlack, ",") - 1)
listPoints.Add(New Point(x, y))
End While
myPoints = listPoints.ToArray
' Now use the points array to draw a filled polygon
myPen = New Pen(Drawing.Color.White, 0)
myBrush = New SolidBrush(Color.FromArgb(170, 0, 0, 0))
Dim myGraphics As Graphics = pbDN.CreateGraphics
myGraphics.DrawPolygon(myPen, myPoints)
myGraphics.FillPolygon(myBrush, myPoints)
End Sub
As I said, this is not the ideal solution, so it slows things down a bit performance wise, but it works. I'm sure being a VB.NET amateur, heck I can't even get the code sample to look right in here, even the current code is not optimal, but it gets the job done. Hope someone finds this helpful.

Improve Performance With GDI+

As a challenge, I am planning to make a game purely in Visual Studio (using Visual Basic) but in the past, I have noted that GDI+ is not the best rendering tool, but for what it is, it's all right.
What settings should I use and not use when working with GDI+? Here are my assumptions:
InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor It would make sense that this option renders the fastest.
PixelOffsetMode = Drawing2D.PixelOffsetMode.Half This seems like it must be used with NearestNeighbor.
CompositingQuality = ? I am not sure about this one.
CompositingMode = ? Again, I can't tell.
SmoothingMode = Drawing2D.SmoothingMode.None Specifying no smoothing mode would probably run the fastest.
SetClip(ClientRectangle) It would make sense to set this as the clip so the graphics would not draw outside of the form or control.
My next point: I've noticed that adding all the graphics code always works the fastest in Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Is there any benefit to doing something like this inside that void: (Creating a temporary bitmap and drawing it onto the screen.)
Using B As New Bitmap(ClientSize.Width, ClientSize.Height, Imaging.PixelFormat.Format32bppPArgb)
Using G As Graphics = Graphics.FromImage(B)
' Draw objects onto the bitmap.
End Using
e.Graphics.DrawImage(B, 0, 0)
End Using
I ask this because I noticed that when creating a bitmap, you can specify a Imaging.PixelFormat. Is there one type of format that renders faster than the rest?
Thank you all in advance for the help.
~Nic

No result using BITMAP

Here's a code snippet:
Dim BMf As Bitmap
BMf = New Bitmap(PicBox.Width, PicBox.Height)
Call FourierPlot(PlotHeight, PlotWidth, RPMArray, CoefArray, Count, 2, BMf)
Me.PicBox.Image = BMf
BMf.Dispose()
within the subroutine is code such as:
Dim myGraphics As Graphics = Graphics.FromImage(BMf)
Dim myPen As New Pen(colr)
....
myGraphics.DrawLine(myPen, lastx, lasty, temp1, temp2)
....
myPen.Dispose()
myGraphics.Dispose()
The displayed PicBox consists of a boundary rectangle with lines draw from opposing corners (what I presume is an "error image.)
Any suggestions (hopefully VERY simple ones) as to what I'm doing wrong?
You shouldn't call BMf.Dispose(), because the image is going to be used by the picture box.
Update:
OK, small update because this seems to be confusing to the OP and others.
When you say Me.PicBox.Image = BMf you set a reference to the bitmap. Both BMf and PicBox.Image now point to the same object. Thus, you should not dispose it, because then it can't be used anymore. Again - this is not a copy, this is same object.
And about leaks. Removing this line does not cause any memory or other leaks. .NET is managing this for you. As soon as the bitmap will not be needed (which means nobody has a reference to it = your picture box will load another image), it will be unneeded and disposed at the next run of the garbage collector. This is automatic.
You might want to disposed it manually if you really need to care about resource, for example if you would invoked your code and create new bitmaps often, many times. But in this case you probably would be better off forcing garbage collector to run in places, where you can cause some delay to the user. You can do this like this:
GC.Collect()

How to create an overlay of a full screen application

So I'm trying to make an overlay for a full screen game. Firstly this isn't for hacking purposes, the game shows times as little clocks and I find this difficult to read, so when I press a key to activate something I want to be able to see how long ago I activated it etc.
I currently have this code to write the time to the screen:
Private Shared Sub DrawOverlay(ByVal OverlayString As String)
Dim Processes = Process.GetProcessesByName("GAMECLIENT")
Dim deviceContext As Graphics = Graphics.FromHwnd(Processes(0).MainWindowHandle)
Dim drawFont As New Font("Arial", 14, FontStyle.Bold)
Dim myBrush As New Drawing2D.LinearGradientBrush(deviceContext.ClipBounds, Color.Black, Color.SkyBlue, Drawing2D.LinearGradientMode.Horizontal)
Dim drawFormat As New StringFormat()
drawFormat.FormatFlags = StringFormatFlags.NoFontFallback
deviceContext.DrawString(OverlayString, drawFont, myBrush, 100, 100, drawFormat)
End Sub
To be clear this code isn't mine. It's just what I've found from research. This works, however it's extremely slow. It actually makes the game free for about 5 seconds. I think the time consuming line is:
deviceContext.DrawString(OverlayString, drawFont, myBrush, 100, 100, drawFormat)
By process of playing around with other lines it seems to be almost defiantly this line. However I can't work out how to speed it up. I even published the application, just in case it was the debugger. No difference. However this doesn't work for full screen which isn't ideal, if anyone could explain why that would probably help me out.
On a related note if anyone has/knows of a DLL I can reference to do this quickly and more effectively (ESPECALLY FOR FULL SCREEN) that would be great!
So to sum up:
1) Why is that line so slow
2) How should I speed it up
3) Is there another way to do this that works with full screen.
Thanks!

set location of form instance

I am working on this.. the locations of the marker is in the database..
this is not google's API.
this is GMap.Net for windows.
this is the code..
For Each dtrow In markerDtable.Rows
Dim marker As New GMapMarkerGoogleGreen(New PointLatLng(dtrow("Latitude"), dtrow("Longitude")))
markersOverlay.Markers.Add(marker)
Next
I don't really understand so much, just experimented on code to get their supposed to be latlng and magically it appeared how I wanted it.
how can I make that look like this.. (this is only an emulation, I just dragged the form to what place I want them to be)
only form2 and I only need its instances.. when I click the marker, form2 appears right beside it.
UPDATE: I have my coordinates, but how can I make them appear like that? from my late versions, I use this.. form2.Location = marker.LocalPosition + New Point(20, -240) - to offset
but that code is pre-defined, hard coded. and that's not my goal. I want it on a sub, just like the code above (for markers) thank you for helping.
UPDATE2: current code - shows the three forms, but does not go to the location of the markers
For Each dtrow In markerDtable.Rows
Dim marker As New GMapMarkerGoogleGreen(New PointLatLng(dtrow("Latitude"), dtrow("Longitude")))
markersOverlay.Markers.Add(marker)
Dim f As New Form2
f.Location = marker.LocalPosition
f.Show()
Next