|
-
Apr 3rd, 2011, 12:28 PM
#1
Thread Starter
Fanatic Member
General "Graphics" question
Hello everyone.
I am starting to become a bit confused of all the possible "Graphics" that exist inside .NET. Till now I discovered four types of Graphics:
- HIcon, an handle to an ICON image
- HBitmap, an handle to a BITMAP image
- Hdc, an handle to a Device Context
- Graphics, an encapsulation class for GDI+
I can convert Graphics to a bitmap, as I just noticed, and can convert Hdc to Graphics and vice versa. What exactly are the differences between all these types of Graphics? Which type of Graphics is used in a Window and in "OnPaint" events? When specifying a double buffer, what IS this double buffer? Is the Graphics class an encapsulation of the Device Context? If the Graphics class is an encapsulation, why doesn't it have Get/SetPixel and a "ToBitmap" function, since you can transfer DC using BitBlt?
-
Apr 3rd, 2011, 12:36 PM
#2
Re: General "Graphics" question
they aren't types of graphics. the ones that are handles are just that, an intptr handle of a bitmap or icon + hDc is a handle of a device context
the graphics you'd use in vb.net are GDI+
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Apr 3rd, 2011, 12:39 PM
#3
Thread Starter
Fanatic Member
Re: General "Graphics" question
Then I am just wondering though, why is there no "SetPixel" and "GetPixel" and other DC-related functions inside the Graphics class?
For example, using my DC class, I can do this any ways:
Code:
Dim g As Graphics = Me.CreateGraphics()
Dim DC As API.DC = New API.DC(g)
DC.Pixel(10, 10) = DC.Pixel(12, 15)
Dim myscreen As Bitmap = DC.ToBitmap()
DC.Dispose()
g.Dispose()
What does a "Graphics object" contain then, besides an handle to the source? And what does the "GetHdc" function do?
Any difference between the "Graphics.Fromhwnd(windowhandle)" and "Graphics.Fromhdc(gethdc(windowhandle))"?
What is better: extract the image from a window by using the the Graphics objects' HDC, or by using no Graphics object at all and extract it using GetHdc?
It's just hard to maintain a proper balance between Graphics and DC, since both eventually become each other.
E.g.:
Dim g As Graphics = Graphics.FromHdc(hdc)
Dim Hdc As IntPtr = g.GetHdc
I'll try to bring it down to two questions:
- When do we use the Graphics object and when do we use the Device Context?
- Are the two types equal or is one of the types contained in the other?
Last edited by bergerkiller; Apr 3rd, 2011 at 12:49 PM.
-
Apr 3rd, 2011, 12:41 PM
#4
Re: General "Graphics" question
SetPixel and GetPixel are members of the bitmap class
it looks like you're making it unnecessarily complicated
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Apr 3rd, 2011, 12:53 PM
#5
Re: General "Graphics" question
vb Code:
dim img as new bitmap(100,100) 'width,height
or:
vb Code:
dim img as new bitmap("filename")
or:
vb Code:
dim img as bitmap = directcast(picturebox1.image.clone, bitmap)
then create a graphics object:
vb Code:
dim gr as graphics = graphics.fromimage(img)
then you can use any of the GDI+ graphics methods on gr + it'll update img
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Apr 3rd, 2011, 12:56 PM
#6
Thread Starter
Fanatic Member
Re: General "Graphics" question
I know, but once you have the Graphics, there is no way to get the source from it. For example, you can not get a Bitmap out of a Graphics object passed by the Forms' OnPaint event. I then have to get the Hdc, use BitBlt to transfer the data to a new Bitmap object, and that's it. Why is this?
Is there no simple "CopyTo(Byval Destination As Graphics) function for the Graphics object?
I start to believe the Hdc is a simple pointer to that "Bitmap in memory", but why can't the Graphics object, maintaining this Bitmap, use Get or SetPixel on it?
It's just a bit strange that you have to declare new functions for a .NET wrapper around the Hdc (or pointer to the source).
Last edited by bergerkiller; Apr 3rd, 2011 at 01:00 PM.
-
Apr 3rd, 2011, 01:00 PM
#7
Re: General "Graphics" question
a Bitmap contains a Bitmap. a Graphics object points to a bitmap or a drawing surface.
you can use the graphics copyfromscreen method instead of BitBlt
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Apr 3rd, 2011, 01:06 PM
#8
Thread Starter
Fanatic Member
Re: General "Graphics" question
Yep, but is this possible without API's?
Code:
Public Shared Sub TransferGraphics(ByVal source As Graphics, ByVal dest As Graphics, ByVal destrect As Rectangle)
Dim shdc As IntPtr = source.GetHdc
Dim dhdc As IntPtr = dest.GetHdc
BitBlt(dhdc, destrect.X, destrect.Y, destrect.Width, destrect.Height, shdc, 0, 0, SRCCOPY Or CAPTUREBLT)
source.ReleaseHdc(shdc)
dest.ReleaseHdc(dhdc)
End Sub
Private Const SRCCOPY = &HCC0020
Private Const CAPTUREBLT = &H40000000
Private Declare Function BitBlt Lib "gdi32" (ByVal hdc As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As UInteger) As Boolean
I failed to find these types of operations in the Graphics class. How come I can't make my Graphics object write to another source, or, obtain data from another source.
E.g. DrawGraphics(g)
Ow and thanks for pointing me on the "CopyFromScreen", it seems to contain some sort of BitBlt but it does not allow you to specify a source.
CopyFromScreen is nice, but if it is the only function for "BitBlt" the Graphics object is a pretty lousy wrapper.
BTW: it did help me so far, I now understand it is useless to make a DC class since the Graphics class has this mostly implemented.
I will just make some functions to extend the Graphics class, as long it is required. But still...why aren't these logical functions added?!
Last edited by bergerkiller; Apr 3rd, 2011 at 01:21 PM.
-
Apr 3rd, 2011, 02:16 PM
#9
Re: General "Graphics" question
I agree with you bergerkiller. the graphics class IS a pretty lousy wrapper to GDI/GDI+.(mabey we should start our own) I have always wondered why why there isn't something as simple as a Copy Method to do what you did. In my currently Under Development windows api class I've implemented something Similar.
vb.net Code:
<DebuggerStepThrough()> _ Public Shared Function HandleBitBlt(ByVal SourceHwnd As IntPtr, ByVal DestHwnd As IntPtr, ByVal SourceRect As Rectangle, ByVal DestLocation As Point, Optional ByVal dwRop As TernaryRasterOperations = TernaryRasterOperations.SRCCOPY) As Boolean Using g As Graphics = Graphics.FromHwnd(SourceHwnd), g2 As Graphics = Graphics.FromHwnd(DestHwnd) Dim scrhdc As IntPtr = g.GetHdc Dim desthdc As IntPtr = g2.GetHdc Dim result As Boolean = Declarations.BitBlt(desthdc, DestLocation.X, DestLocation.Y, SourceRect.Width, SourceRect.Height, scrhdc, SourceRect.X, SourceRect.Y, dwRop) g.ReleaseHdc(scrhdc) g2.ReleaseHdc(desthdc) If result = False Then Dim ex As New System.ComponentModel.Win32Exception(Runtime.InteropServices.Marshal.GetLastWin32Error) Throw ex End If Return result End Using End Function <DebuggerStepThrough()> _ Public Shared Function hDCBitBlt(ByVal SourceHdc As IntPtr, ByVal destHdc As IntPtr, ByVal SourceRect As Rectangle, ByVal DestLocation As Point, Optional ByVal dwRop As TernaryRasterOperations = TernaryRasterOperations.SRCCOPY) As Boolean Dim result As Boolean = Declarations.BitBlt(destHdc, DestLocation.X, DestLocation.Y, SourceRect.Width, SourceRect.Height, SourceHdc, SourceRect.X, SourceRect.Y, dwRop) If result = False Then Dim ex As New System.ComponentModel.Win32Exception(Runtime.InteropServices.Marshal.GetLastWin32Error) Throw ex End If Return result End Function
EDIT Declarations.BitBlt is just the Imported Function.
-
Apr 3rd, 2011, 02:27 PM
#10
Re: General "Graphics" question
here is the Enum. For some reason when I click on edit It says my IP is banned but I can do everything else 
Code:
''' <summary>
''' Specifies a raster-operation code. These codes define how the color data for the
''' source rectangle is to be combined with the color data for the destination
''' rectangle to achieve the final color.
''' </summary>
Public Enum TernaryRasterOperations As UInteger
''' <summary>dest = source</summary>
SRCCOPY = &HCC0020
''' <summary>dest = source OR dest</summary>
SRCPAINT = &HEE0086
''' <summary>dest = source AND dest</summary>
SRCAND = &H8800C6
''' <summary>dest = source XOR dest</summary>
SRCINVERT = &H660046
''' <summary>dest = source AND (NOT dest)</summary>
SRCERASE = &H440328
''' <summary>dest = (NOT source)</summary>
NOTSRCCOPY = &H330008
''' <summary>dest = (NOT src) AND (NOT dest)</summary>
NOTSRCERASE = &H1100A6
''' <summary>dest = (source AND pattern)</summary>
MERGECOPY = &HC000CA
''' <summary>dest = (NOT source) OR dest</summary>
MERGEPAINT = &HBB0226
''' <summary>dest = pattern</summary>
PATCOPY = &HF00021
''' <summary>dest = DPSnoo</summary>
PATPAINT = &HFB0A09
''' <summary>dest = pattern XOR dest</summary>
PATINVERT = &H5A0049
''' <summary>dest = (NOT dest)</summary>
DSTINVERT = &H550009
''' <summary>dest = BLACK</summary>
BLACKNESS = &H42
''' <summary>dest = WHITE</summary>
WHITENESS = &HFF0062
''' <summary>
''' Capture window as seen on screen. This includes layered windows
''' such as WPF windows with AllowsTransparency="true"
''' </summary>
CAPTUREBLT = &H40000000
End Enum
-
Apr 3rd, 2011, 04:13 PM
#11
Thread Starter
Fanatic Member
Re: General "Graphics" question
Ow the enum is also in .NET it self, under the name:
I contains the exact same values as the "RasterOperation" or "TRO" enumeration.
Is there any way of "extending" the graphics class? Building the entire class all over again using API's seems a bit useless, I would preferably make some sort of wrapper around the Graphics object.
For good measure, the DC class:
vb Code:
Public Class DC Implements System.IDisposable Private Declare Function BitBlt Lib "gdi32" (ByVal hdc As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As CopyPixelOperation) As Boolean Private Declare Function GetPixel Lib "gdi32" Alias "GetPixel" (ByVal hdc As IntPtr, ByVal X As Int32, ByVal Y As Int32) As Int32 Private Declare Function SetPixel Lib "gdi32" Alias "SetPixel" (ByVal hdc As IntPtr, ByVal X As Int32, ByVal Y As Int32, ByVal crColor As UInt32) As UInt32 Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Boolean Private Declare Function GetClipBox Lib "gdi32" (ByVal hdc As IntPtr, ByRef lprc As WRECT) As Integer Private Declare Function GetClipRgn Lib "gdi32" (ByVal hdc As IntPtr, ByRef hrgn As Region) As Integer Private Declare Function GetRandomRgn Lib "gdi32" (ByVal hdc As IntPtr, ByRef hrgn As Region, ByVal inum As Integer) As Integer Private managedtype As DCSource Private managedobject As Object Private managedgraphics As Graphics Private hdc As IntPtr Private _disposed As Boolean Public Enum DCSource None Handle Graphics End Enum Sub New(ByVal g As Graphics) Me.managedobject = g Me.managedtype = DCSource.Graphics Me.hdc = g.GetHdc End Sub Sub New(ByVal hwnd As IntPtr, ByVal hdc As IntPtr) Me.managedobject = hwnd Me.managedtype = DCSource.Handle Me.hdc = hdc End Sub Sub New() Me.managedobject = Nothing Me.managedtype = DCSource.None End Sub Public ReadOnly Property Source() As DCSource Get Return Me.managedtype End Get End Property Public Sub SetPixel(ByVal X As Integer, ByVal Y As Integer, ByVal C As Color) SetPixel(Me.hdc, X, Y, C.ToArgb) End Sub Public Function GetPixel(ByVal X As Integer, ByVal Y As Integer) As Color Return ColorTranslator.FromOle(GetPixel(Me.hdc, X, Y)) End Function Public Property Pixel(ByVal X As Integer, ByVal Y As Integer) As Color Get Return GetPixel(X, Y) End Get Set(ByVal value As Color) SetPixel(X, Y, value) End Set End Property Public ReadOnly Property ClipBox() As Rectangle Get Dim w As WRECT GetClipBox(Me.hdc, w) Return w.Value End Get End Property Public ReadOnly Property ClipSize() As Size Get Return Me.ClipBox.Size End Get End Property Public Property Handle() As IntPtr Get Return Me.hdc End Get Set(ByVal value As IntPtr) Me.hdc = value End Set End Property Public ReadOnly Property Disposed() As Boolean Get Return Me._disposed End Get End Property Public Sub Draw(ByVal source As Graphics, ByVal destrect As Rectangle, ByVal sourceoffset As Point, ByVal operation As CopyPixelOperation) Dim hdc As IntPtr = source.GetHdc Draw(hdc, destrect, sourceoffset, operation) source.ReleaseHdc(hdc) End Sub Public Sub Draw(ByVal source As DC, ByVal destrect As Rectangle, ByVal sourceoffset As Point, ByVal operation As CopyPixelOperation) Draw(source.hdc, destrect, sourceoffset, operation) End Sub Public Sub Draw(ByVal sourcehdc As IntPtr, ByVal destrect As Rectangle, ByVal sourceoffset As Point, ByVal operation As CopyPixelOperation) BitBlt(Me.hdc, destrect.X, destrect.Y, destrect.Width, destrect.Height, sourcehdc, sourceoffset.X, sourceoffset.Y, operation) End Sub Public Sub CopyTo(ByVal destination As Graphics, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) CopyTo(destination, Me.ClipBox, operation) End Sub Public Sub CopyTo(ByVal destination As Graphics, ByVal destrect As Rectangle, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) CopyTo(destination, destrect, New Point(0, 0), operation) End Sub Public Sub CopyTo(ByVal destination As Graphics, ByVal destrect As Rectangle, ByVal sourceoffset As Point, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) Dim hdc As IntPtr = destination.GetHdc CopyTo(hdc, destrect, sourceoffset, operation) destination.ReleaseHdc(hdc) End Sub Public Sub CopyTo(ByVal destination As DC, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) CopyTo(destination.hdc, Me.ClipBox, New Point(0, 0), operation) End Sub Public Sub CopyTo(ByVal destination As DC, ByVal destrect As Rectangle, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) CopyTo(destination.hdc, destrect, New Point(0, 0), operation) End Sub Public Sub CopyTo(ByVal destination As DC, ByVal destrect As Rectangle, ByVal sourceoffset As Point, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) CopyTo(destination.hdc, destrect, sourceoffset, operation) End Sub Public Sub CopyTo(ByVal desthdc As IntPtr, ByVal destrect As Rectangle, ByVal sourceoffset As Point, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) BitBlt(desthdc, destrect.X, destrect.Y, destrect.Width, destrect.Height, Me.hdc, sourceoffset.X, sourceoffset.Y, operation) End Sub Public Function ToBitmap(Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) As Bitmap Return ToBitmap(Me.ClipSize, operation) End Function Public Function ToBitmap(ByVal Resolution As Size, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) As Bitmap ToBitmap = New Bitmap(Resolution.Width, Resolution.Height) Dim g As Graphics = Graphics.FromImage(ToBitmap) Dim ghdc As IntPtr = g.GetHdc BitBlt(ghdc, 0, 0, Resolution.Width, Resolution.Height, Me.hdc, 0, 0, operation) g.ReleaseHdc(ghdc) g.Dispose() End Function Public ReadOnly Property Graphics() As Graphics Get If Me.managedgraphics Is Nothing Then Me.managedgraphics = Graphics.FromHdc(Me.hdc) Return Me.managedgraphics End Get End Property Public Shared Function FromHandle(ByVal handle As IntPtr) As DC FromHandle = New DC() FromHandle.hdc = handle End Function Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) If Me._disposed = False Then Select Case managedtype Case DCSource.Handle ReleaseDC(CType(Me.managedobject, IntPtr), Me.hdc) Case DCSource.Graphics CType(Me.managedobject, Graphics).ReleaseHdc(Me.hdc) End Select If managedgraphics IsNot Nothing Then managedgraphics.Dispose() Me.managedgraphics = Nothing Me.managedobject = Nothing Me.managedtype = Nothing Me.hdc = Nothing Me._disposed = True End If End Sub Public Overloads Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub End Class
It contains SetPixel, GetPixel and BitBlt operations, plus a clip size property to use when copying bits.
EDIT
And of course, "Graphics is declared NonInheritable". SIGH 
Making your own class is probably a bad idea, since it would not be possible to use it common in your code. I added a "Graphics" property to my class, though, so it is an alternative.
I am just not sure whether to add functions specific for the Graphics class or not, and the "releaseHdc" issue makes it even harder to use functions.
I fixed it by releasing them in the dispose sub, but that brings in using yet another class.
Last edited by bergerkiller; Apr 3rd, 2011 at 04:23 PM.
-
Apr 3rd, 2011, 05:12 PM
#12
Re: General "Graphics" question
I've reflected out system.drawing.dll, but my visual studio crashes when trying to load since It is quite large.
The graphics class inherits from IDeviceContext, If that is of any use.
Here are some stats for you:
The graphics class is about ~ 2200 lines of code. Not one empty line
The imported functions and their structures ~ 4500. Also no spaces.
And another fun fact. Microsoft ALWAYS uses handleref for a handle as a argument to a Imported function.
And I don't know if this is the exact code that Microsoft uses or if the reflector changes it, but if it is nearly the same, I could of coded it better providing ample time.
-
Apr 3rd, 2011, 05:49 PM
#13
Thread Starter
Fanatic Member
Re: General "Graphics" question
I kind of expected all of that, really. 
The Graphics class is pretty solid, but the lack of per-pixel operations or BitBlt to copy contexts around is just a bit annoying. I can't think of any other functions I would need.
Of course I can make Set/Get pixel functions for a Graphics object by passing it to the function, but it would be a lot slower since every call would free a DC and release it again. I guess I will remove the "GetDC" and "GetWindowDC" functions from my Window class, and will be using "CreateGraphics" and "CreateWindowGraphics" functions instead. I'll add a simple Graphics wrapper (which uses a Graphics object as parameter for constructing) to it, holding the Graphics object and the HDC derived from it, doing the ReleaseHdc upon disposing.
I guess all it will do is copy from/to other Graphics objects, and no longer to Hdc. Thinking of leaving Hdc out at all in any of my functions. I had "DC" before, but it seems a bit "not what it is". Do you have a good name for me, Blind? May be 'GraphicsEx' or something.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|