Results 1 to 13 of 13

Thread: General "Graphics" question

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    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?

  2. #2
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,419

    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+

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    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?

  4. #4
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,419

    Re: General "Graphics" question

    SetPixel and GetPixel are members of the bitmap class

    it looks like you're making it unnecessarily complicated

  5. #5
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,419

    Re: General "Graphics" question

    vb Code:
    1. dim img as new bitmap(100,100) 'width,height

    or:

    vb Code:
    1. dim img as new bitmap("filename")

    or:

    vb Code:
    1. dim img as bitmap = directcast(picturebox1.image.clone, bitmap)

    then create a graphics object:

    vb Code:
    1. dim gr as graphics = graphics.fromimage(img)

    then you can use any of the GDI+ graphics methods on gr + it'll update img

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    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).

  7. #7
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,419

    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

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    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?!

  9. #9
    Fanatic Member BlindSniper's Avatar
    Join Date
    Jan 2011
    Location
    South Africa
    Posts
    865

    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:
    1. <DebuggerStepThrough()> _
    2.     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
    3.         Using g As Graphics = Graphics.FromHwnd(SourceHwnd), g2 As Graphics = Graphics.FromHwnd(DestHwnd)
    4.             Dim scrhdc As IntPtr = g.GetHdc
    5.             Dim desthdc As IntPtr = g2.GetHdc
    6.             Dim result As Boolean = Declarations.BitBlt(desthdc, DestLocation.X, DestLocation.Y, SourceRect.Width, SourceRect.Height, scrhdc, SourceRect.X, SourceRect.Y, dwRop)
    7.             g.ReleaseHdc(scrhdc)
    8.             g2.ReleaseHdc(desthdc)
    9.  
    10.             If result = False Then
    11.                 Dim ex As New System.ComponentModel.Win32Exception(Runtime.InteropServices.Marshal.GetLastWin32Error)
    12.                 Throw ex
    13.             End If
    14.             Return result
    15.  
    16.         End Using
    17.     End Function
    18.     <DebuggerStepThrough()> _
    19.     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
    20.  
    21.  
    22.         Dim result As Boolean = Declarations.BitBlt(destHdc, DestLocation.X, DestLocation.Y, SourceRect.Width, SourceRect.Height, SourceHdc, SourceRect.X, SourceRect.Y, dwRop)
    23.         If result = False Then
    24.             Dim ex As New System.ComponentModel.Win32Exception(Runtime.InteropServices.Marshal.GetLastWin32Error)
    25.             Throw ex
    26.         End If
    27.         Return result
    28.  
    29.     End Function

    EDIT Declarations.BitBlt is just the Imported Function.

  10. #10
    Fanatic Member BlindSniper's Avatar
    Join Date
    Jan 2011
    Location
    South Africa
    Posts
    865

    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

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: General "Graphics" question

    Ow the enum is also in .NET it self, under the name:
    Code:
    CopyPixelOperation
    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:
    1. Public Class DC
    2.         Implements System.IDisposable
    3.  
    4.         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
    5.         Private Declare Function GetPixel Lib "gdi32" Alias "GetPixel" (ByVal hdc As IntPtr, ByVal X As Int32, ByVal Y As Int32) As Int32
    6.         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
    7.         Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Boolean
    8.         Private Declare Function GetClipBox Lib "gdi32" (ByVal hdc As IntPtr, ByRef lprc As WRECT) As Integer
    9.         Private Declare Function GetClipRgn Lib "gdi32" (ByVal hdc As IntPtr, ByRef hrgn As Region) As Integer
    10.         Private Declare Function GetRandomRgn Lib "gdi32" (ByVal hdc As IntPtr, ByRef hrgn As Region, ByVal inum As Integer) As Integer
    11.  
    12.         Private managedtype As DCSource
    13.         Private managedobject As Object
    14.         Private managedgraphics As Graphics
    15.         Private hdc As IntPtr
    16.         Private _disposed As Boolean
    17.         Public Enum DCSource
    18.             None
    19.             Handle
    20.             Graphics
    21.         End Enum
    22.         Sub New(ByVal g As Graphics)
    23.             Me.managedobject = g
    24.             Me.managedtype = DCSource.Graphics
    25.             Me.hdc = g.GetHdc
    26.         End Sub
    27.         Sub New(ByVal hwnd As IntPtr, ByVal hdc As IntPtr)
    28.             Me.managedobject = hwnd
    29.             Me.managedtype = DCSource.Handle
    30.             Me.hdc = hdc
    31.         End Sub
    32.         Sub New()
    33.             Me.managedobject = Nothing
    34.             Me.managedtype = DCSource.None
    35.         End Sub
    36.         Public ReadOnly Property Source() As DCSource
    37.             Get
    38.                 Return Me.managedtype
    39.             End Get
    40.         End Property
    41.         Public Sub SetPixel(ByVal X As Integer, ByVal Y As Integer, ByVal C As Color)
    42.             SetPixel(Me.hdc, X, Y, C.ToArgb)
    43.         End Sub
    44.         Public Function GetPixel(ByVal X As Integer, ByVal Y As Integer) As Color
    45.             Return ColorTranslator.FromOle(GetPixel(Me.hdc, X, Y))
    46.         End Function
    47.         Public Property Pixel(ByVal X As Integer, ByVal Y As Integer) As Color
    48.             Get
    49.                 Return GetPixel(X, Y)
    50.             End Get
    51.             Set(ByVal value As Color)
    52.                 SetPixel(X, Y, value)
    53.             End Set
    54.         End Property
    55.  
    56.         Public ReadOnly Property ClipBox() As Rectangle
    57.             Get
    58.                 Dim w As WRECT
    59.                 GetClipBox(Me.hdc, w)
    60.                 Return w.Value
    61.             End Get
    62.         End Property
    63.         Public ReadOnly Property ClipSize() As Size
    64.             Get
    65.                 Return Me.ClipBox.Size
    66.             End Get
    67.         End Property
    68.  
    69.         Public Property Handle() As IntPtr
    70.             Get
    71.                 Return Me.hdc
    72.             End Get
    73.             Set(ByVal value As IntPtr)
    74.                 Me.hdc = value
    75.             End Set
    76.         End Property
    77.  
    78.         Public ReadOnly Property Disposed() As Boolean
    79.             Get
    80.                 Return Me._disposed
    81.             End Get
    82.         End Property
    83.  
    84.         Public Sub Draw(ByVal source As Graphics, ByVal destrect As Rectangle, ByVal sourceoffset As Point, ByVal operation As CopyPixelOperation)
    85.             Dim hdc As IntPtr = source.GetHdc
    86.             Draw(hdc, destrect, sourceoffset, operation)
    87.             source.ReleaseHdc(hdc)
    88.         End Sub
    89.         Public Sub Draw(ByVal source As DC, ByVal destrect As Rectangle, ByVal sourceoffset As Point, ByVal operation As CopyPixelOperation)
    90.             Draw(source.hdc, destrect, sourceoffset, operation)
    91.         End Sub
    92.         Public Sub Draw(ByVal sourcehdc As IntPtr, ByVal destrect As Rectangle, ByVal sourceoffset As Point, ByVal operation As CopyPixelOperation)
    93.             BitBlt(Me.hdc, destrect.X, destrect.Y, destrect.Width, destrect.Height, sourcehdc, sourceoffset.X, sourceoffset.Y, operation)
    94.         End Sub
    95.  
    96.         Public Sub CopyTo(ByVal destination As Graphics, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    97.             CopyTo(destination, Me.ClipBox, operation)
    98.         End Sub
    99.         Public Sub CopyTo(ByVal destination As Graphics, ByVal destrect As Rectangle, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    100.             CopyTo(destination, destrect, New Point(0, 0), operation)
    101.         End Sub
    102.         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)
    103.             Dim hdc As IntPtr = destination.GetHdc
    104.             CopyTo(hdc, destrect, sourceoffset, operation)
    105.             destination.ReleaseHdc(hdc)
    106.         End Sub
    107.         Public Sub CopyTo(ByVal destination As DC, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    108.             CopyTo(destination.hdc, Me.ClipBox, New Point(0, 0), operation)
    109.         End Sub
    110.         Public Sub CopyTo(ByVal destination As DC, ByVal destrect As Rectangle, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    111.             CopyTo(destination.hdc, destrect, New Point(0, 0), operation)
    112.         End Sub
    113.         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)
    114.             CopyTo(destination.hdc, destrect, sourceoffset, operation)
    115.         End Sub
    116.         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)
    117.             BitBlt(desthdc, destrect.X, destrect.Y, destrect.Width, destrect.Height, Me.hdc, sourceoffset.X, sourceoffset.Y, operation)
    118.         End Sub
    119.  
    120.         Public Function ToBitmap(Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) As Bitmap
    121.             Return ToBitmap(Me.ClipSize, operation)
    122.         End Function
    123.         Public Function ToBitmap(ByVal Resolution As Size, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) As Bitmap
    124.             ToBitmap = New Bitmap(Resolution.Width, Resolution.Height)
    125.             Dim g As Graphics = Graphics.FromImage(ToBitmap)
    126.             Dim ghdc As IntPtr = g.GetHdc
    127.             BitBlt(ghdc, 0, 0, Resolution.Width, Resolution.Height, Me.hdc, 0, 0, operation)
    128.             g.ReleaseHdc(ghdc)
    129.             g.Dispose()
    130.         End Function
    131.  
    132.         Public ReadOnly Property Graphics() As Graphics
    133.             Get
    134.                 If Me.managedgraphics Is Nothing Then Me.managedgraphics = Graphics.FromHdc(Me.hdc)
    135.                 Return Me.managedgraphics
    136.             End Get
    137.         End Property
    138.         Public Shared Function FromHandle(ByVal handle As IntPtr) As DC
    139.             FromHandle = New DC()
    140.             FromHandle.hdc = handle
    141.         End Function
    142.  
    143.         Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
    144.             If Me._disposed = False Then
    145.                 Select Case managedtype
    146.                     Case DCSource.Handle
    147.                         ReleaseDC(CType(Me.managedobject, IntPtr), Me.hdc)
    148.                     Case DCSource.Graphics
    149.                         CType(Me.managedobject, Graphics).ReleaseHdc(Me.hdc)
    150.                 End Select
    151.                 If managedgraphics IsNot Nothing Then managedgraphics.Dispose()
    152.                 Me.managedgraphics = Nothing
    153.                 Me.managedobject = Nothing
    154.                 Me.managedtype = Nothing
    155.                 Me.hdc = Nothing
    156.                 Me._disposed = True
    157.             End If
    158.         End Sub
    159.         Public Overloads Sub Dispose() Implements IDisposable.Dispose
    160.             Dispose(True)
    161.             GC.SuppressFinalize(Me)
    162.         End Sub
    163.     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.

  12. #12
    Fanatic Member BlindSniper's Avatar
    Join Date
    Jan 2011
    Location
    South Africa
    Posts
    865

    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.

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    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
  •  



Click Here to Expand Forum to Full Width