home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 7_2009-2012.ISO / data / zips / ArtDraw_v_2180655102010.psc / Class / cDIBSectionRegion.cls < prev    next >
Text File  |  2010-03-29  |  12KB  |  365 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "cDIBSectionRegion"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15.  
  16. ' ==================================================================
  17. ' FileName:    cDIBSectionRegion.cls
  18. ' Author:      Steve McMahon
  19. '
  20. ' Converts a cDIBSection object into a region which you can apply
  21. ' to a form, UserControl or PictureBox (in fact, anything with a
  22. ' hWnd property).
  23. '
  24. ' Also includes functions to Save a region to a file, and to Load
  25. ' a region either from a file or from a resource.  The resource
  26. ' loading code is useful because it demonstrates how to load
  27. ' arbitrary resource data from any external library.
  28. '
  29. ' ------------------------------------------------------------------
  30. ' Visit vbAccelerator - advanced, hardcore VB with full source code
  31. ' http://vbaccelerator.com/
  32. ' mailto:steve@vbaccelerator.com
  33. '
  34. ' ==================================================================
  35.  
  36. ' API for creating a region:
  37. Private Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
  38. Private Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
  39. Private Const RGN_AND = 1
  40. Private Const RGN_COPY = 5
  41. Private Const RGN_DIFF = 4
  42. Private Const RGN_OR = 2
  43. Private Const RGN_XOR = 3
  44. Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
  45. Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long
  46.  
  47.  
  48. ' API for saving and loading a region:
  49. Private Declare Function GetRegionData Lib "gdi32" (ByVal hRgn As Long, ByVal dwCount As Long, lpRgnData As Any) As Long
  50. Private Declare Function ExtCreateRegion Lib "gdi32" (lpXform As Any, ByVal nCount As Long, lpRgnData As Any) As Long
  51. ' API for getting data from an external library module:
  52. Private Declare Function LoadLibraryEx Lib "kernel32" Alias "LoadLibraryExA" (ByVal lpLibFileName As String, ByVal hFile As Long, ByVal dwFlags As Long) As Long
  53. Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
  54. Private Declare Function LoadResource Lib "kernel32" (ByVal hInstance As Long, ByVal hResInfo As Long) As Long
  55. Private Declare Function LockResource Lib "kernel32" (ByVal hResData As Long) As Long
  56. Private Declare Function FindResource Lib "kernel32" Alias "FindResourceA" (ByVal hInstance As Long, lpName As Any, lpType As Any) As Long
  57. Private Declare Function SizeofResource Lib "kernel32" (ByVal hInstance As Long, ByVal hResInfo As Long) As Long
  58. Private Declare Function FreeResource Lib "kernel32" (ByVal hResData As Long) As Long
  59. Private Const LOAD_LIBRARY_AS_DATAFILE = &H2&
  60. Private Const RT_RCDATA = 10&
  61.  
  62. ' API for reading cDIBSection bits:
  63. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
  64.     lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
  65. Private Type SAFEARRAYBOUND
  66.     cElements As Long
  67.     lLbound As Long
  68. End Type
  69. Private Type SAFEARRAY2D
  70.     cDims As Integer
  71.     fFeatures As Integer
  72.     cbElements As Long
  73.     cLocks As Long
  74.     pvData As Long
  75.     Bounds(0 To 1) As SAFEARRAYBOUND
  76. End Type
  77. Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
  78.  
  79. ' Implementation:
  80. Private m_hRgn As Long
  81. Private m_hWnd() As Long
  82. Private m_iCount As Long
  83.  
  84. Public Property Get Applied(ByVal hwnd As Long) As Boolean
  85.    Applied = Not (plIndex(hwnd) = 0)
  86. End Property
  87. Public Property Let Applied(ByVal hwnd As Long, ByVal bState As Boolean)
  88. Dim i As Long
  89. Dim lIndex As Long
  90.    lIndex = plIndex(hwnd)
  91.    If bState Then
  92.       If (lIndex = 0) Then
  93.          ' Apply to window:
  94.          m_iCount = m_iCount + 1
  95.          ReDim Preserve m_hWnd(1 To m_iCount) As Long
  96.          m_hWnd(m_iCount) = hwnd
  97.          SetWindowRgn m_hWnd(m_iCount), m_hRgn, True
  98.       Else
  99.          ' already applied, reset apply state jic
  100.          SetWindowRgn m_hWnd(m_iCount), m_hRgn, True
  101.       End If
  102.    Else
  103.       If (lIndex = 0) Then
  104.          ' Not applied, reset state jic
  105.          SetWindowRgn hwnd, 0, True
  106.       Else
  107.          ' Applied, reset:
  108.          SetWindowRgn hwnd, 0, True
  109.          If m_iCount > 1 Then
  110.             For i = lIndex To m_iCount - 1
  111.                m_hWnd(i) = m_hWnd(i + 1)
  112.             Next i
  113.             m_iCount = m_iCount - 1
  114.             ReDim Preserve m_hWnd(1 To m_iCount) As Long
  115.          Else
  116.             m_iCount = 0
  117.             Erase m_hWnd
  118.          End If
  119.       End If
  120.    End If
  121. End Property
  122. Private Property Get plIndex(ByVal hwnd As Long) As Long
  123. Dim i As Long
  124. Dim lIndex As Long
  125.    For i = 1 To m_iCount
  126.       If hwnd = m_hWnd(i) Then
  127.          plIndex = i
  128.          Exit For
  129.       End If
  130.    Next i
  131. End Property
  132. Public Property Get AppliedToCount() As Long
  133.    AppliedToCount = m_iCount
  134. End Property
  135. Public Property Get hWndForIndex(ByVal lIndex As Long) As Long
  136.    hWndForIndex = m_hWnd(lIndex)
  137. End Property
  138.  
  139. Private Sub UnApply()
  140. Dim i As Long
  141.    For i = 1 To m_iCount
  142.       If Not m_hWnd(i) = 0 Then
  143.          SetWindowRgn m_hWnd(i), 0, True
  144.          m_hWnd(i) = 0
  145.       End If
  146.    Next i
  147.    m_iCount = 0
  148. End Sub
  149. Public Sub Destroy()
  150.    UnApply
  151.    If Not m_hRgn = 0 Then
  152.       DeleteObject m_hRgn
  153.    End If
  154.    m_hRgn = 0
  155. End Sub
  156.  
  157. Public Sub Create( _
  158.       ByRef cDib As cDIBSection, _
  159.       Optional ByRef lTransColor As Long = 0 _
  160.    )
  161. Dim X As Long, Y As Long
  162. Dim lX As Long
  163. Dim yStart As Long
  164. Dim bStart As Boolean
  165. Dim hRgnTemp As Long
  166. Dim bR As Byte, bG As Byte, bB As Byte
  167. Dim lWidth As Long, lHeight As Long
  168. Dim bDib() As Byte
  169. Dim tSA As SAFEARRAY2D
  170.  
  171.    Destroy
  172.    
  173.    ' The transparent colour:
  174.    bR = (lTransColor And &HFF&)
  175.    bG = (lTransColor And &HFF00&) \ &H100&
  176.    bB = (lTransColor And &HFF0000) \ &H10000
  177.    
  178.    ' Create the base region
  179.    m_hRgn = CreateRectRgn(0, 0, cDib.Width, cDib.Height)
  180.    Debug.Assert (m_hRgn <> 0)
  181.    If m_hRgn <> 0 Then
  182.       ' Get the DIB into byte array:
  183.       With tSA
  184.           .cbElements = 1
  185.           .cDims = 2
  186.           .Bounds(0).lLbound = 0
  187.           .Bounds(0).cElements = cDib.Height
  188.           .Bounds(1).lLbound = 0
  189.           .Bounds(1).cElements = cDib.BytesPerScanLine()
  190.           .pvData = cDib.DIBSectionBitsPtr
  191.       End With
  192.       CopyMemory ByVal VarPtrArray(bDib()), VarPtr(tSA), 4
  193.                
  194.       lWidth = cDib.BytesPerScanLine \ 3
  195.       lHeight = cDib.Height
  196.       For X = 0 To (lWidth - 1) * 3 Step 3
  197.          ' DIB Sections are "upside down" :)
  198.          For Y = lHeight - 1 To 0 Step -1
  199.             If bDib(X, Y) = bB And bDib(X + 1, Y) = bG And bDib(X + 2, Y) = bR Then
  200.                If Not bStart Then
  201.                   yStart = lHeight - 1 - Y
  202.                   bStart = True
  203.                End If
  204.             Else
  205.                If bStart Then
  206.                   hRgnTemp = CreateRectRgn(lX, yStart, lX + 1, lHeight - 1 - Y)
  207.                   CombineRgn m_hRgn, hRgnTemp, m_hRgn, RGN_XOR
  208.                   DeleteObject hRgnTemp
  209.                   bStart = False
  210.                End If
  211.             End If
  212.          Next Y
  213.          If bStart Then
  214.             hRgnTemp = CreateRectRgn(lX, yStart, lX + 1, lHeight - 1 - Y)
  215.             CombineRgn m_hRgn, hRgnTemp, m_hRgn, RGN_XOR
  216.             DeleteObject hRgnTemp
  217.             bStart = False
  218.          End If
  219.          lX = lX + 1
  220.       Next X
  221.       
  222.       CopyMemory ByVal VarPtrArray(bDib), 0&, 4
  223.       
  224.    End If
  225. End Sub
  226.  
  227. Public Function Save(ByVal sPath As String) As Boolean
  228. Dim iFile As Long
  229. Dim nBytes As Long
  230. Dim b() As Byte
  231.  
  232. On Error GoTo ErrorHandler ' Out of memory
  233.  
  234.    If Not m_hRgn = 0 Then
  235.       
  236.       nBytes = GetRegionData(m_hRgn, 0, ByVal 0&)
  237.       If nBytes > 0 Then
  238.          ReDim b(0 To nBytes - 1) As Byte
  239.          If nBytes = GetRegionData(m_hRgn, nBytes, b(0)) Then
  240.             On Error Resume Next ' Attempt to kill file
  241.             Kill sPath
  242.             On Error GoTo ErrorHandler ' Error handler checks for file error
  243.             iFile = FreeFile
  244.             Open sPath For Binary Access Write Lock Read As #iFile
  245.             Put #iFile, , b
  246.             Close #iFile
  247.             Save = True
  248.          Else
  249.             Err.Raise 26012, App.EXEName & ".cDIBSectionRegion", "Unable to get region data"
  250.          End If
  251.       Else
  252.          Err.Raise 26011, App.EXEName & ".cDIBSectionRegion", "Unable to determine size of region"
  253.       End If
  254.    Else
  255.       Err.Raise 26010, App.EXEName & ".cDIBSectionRegion", "No region to save"
  256.    End If
  257.    Exit Function
  258.    
  259. ErrorHandler:
  260. Dim lErr As Long, sErr As String
  261.    lErr = Err.Number: sErr = Err.Description
  262.    If iFile > 0 Then
  263.       Close #iFile
  264.    End If
  265.    Err.Raise lErr, App.EXEName & ".cDIBSectionRegion", sErr
  266.    Exit Function
  267. End Function
  268.  
  269. Public Function LoadFromFile(ByVal sFileName As String) As Boolean
  270. Dim iFile As Long
  271. Dim b() As Byte
  272. On Error GoTo ErrorHandler
  273.  
  274.    iFile = FreeFile
  275.    Open sFileName For Binary Access Read Lock Write As #iFile
  276.    ReDim b(0 To LOF(iFile) - 1) As Byte
  277.    Get #iFile, , b
  278.    Close #iFile
  279.  
  280.    LoadFromFile = pbLoadFromByteArray(b())
  281.    Exit Function
  282.  
  283. ErrorHandler:
  284. Dim lErr As Long, sErr As String
  285.    lErr = Err.Number: sErr = Err.Description
  286.    If iFile > 0 Then
  287.       Close #iFile
  288.    End If
  289.    Err.Raise lErr, App.EXEName & ".cDIBSectionRegion", sErr
  290.    Exit Function
  291. End Function
  292.  
  293. Public Function LoadFromResource(ByVal vID As Variant, Optional ByVal sDLL As String = "") As Boolean
  294. Dim b() As Byte
  295.  
  296.  
  297.    If sDLL = "" Then
  298.       ' Local data
  299.       b = LoadResData(vID, 10)
  300.       LoadFromResource = pbLoadFromByteArray(b())
  301.    Else
  302.       Dim hMod As Long, hRes As Long, hGlobal As Long, lPtr As Long, lSize As Long
  303.       Dim lId As Long, sID As String, lR As Long
  304.       
  305.       ' Load from external module, for data only:
  306.       hMod = LoadLibraryEx(sDLL, ByVal 0&, LOAD_LIBRARY_AS_DATAFILE)
  307.       If Not hMod = 0 Then
  308.          If IsNumeric(vID) Then
  309.             sID = "#" & CStr(vID)
  310.          End If
  311.          hRes = FindResource(hMod, ByVal sID, ByVal RT_RCDATA)
  312.          If Not hRes = 0 Then
  313.             lSize = SizeofResource(hMod, hRes)
  314.             hGlobal = LoadResource(hMod, hRes)
  315.             If Not hGlobal = 0 Then
  316.                lPtr = LockResource(hGlobal)
  317.                If Not lPtr = 0 Then
  318.                   ReDim b(0 To lSize - 1) As Byte
  319.                   CopyMemory b(0), ByVal lPtr, lSize
  320.                   LoadFromResource = pbLoadFromByteArray(b())
  321.                End If
  322.             Else
  323.                Err.Raise 26014, App.EXEName & ".cDIBSectionRegion", "Cannot access data for resource with ID " & vID & " could not be found"
  324.             End If
  325.          Else
  326.             Err.Raise 26014, App.EXEName & ".cDIBSectionRegion", "Resource with ID " & vID & " could not be found"
  327.          End If
  328.          lR = FreeLibrary(hMod)
  329.          Debug.Assert Not (lR = 0)
  330.          If Not lR = 0 Then
  331.             hMod = 0
  332.          End If
  333.       Else
  334.          Err.Raise 26013, App.EXEName & ".cDIBSectionRegion", "Can't open DLL for Resource Access"
  335.       End If
  336.    End If
  337.    Exit Function
  338.  
  339. ErrorHandler:
  340. Dim lErr As Long, sErr As String
  341.    lErr = Err.Number: sErr = Err.Description
  342.    If Not hMod = 0 Then
  343.       lR = FreeLibrary(hMod)
  344.       Debug.Assert Not (lR = 0)
  345.    End If
  346.    Err.Raise lErr, App.EXEName & ".cDIBSectionRegion", sErr
  347.    Exit Function
  348. End Function
  349.  
  350. Private Function pbLoadFromByteArray(ByRef b() As Byte) As Boolean
  351. Dim dwCount As Long
  352.    
  353.    Destroy
  354.    dwCount = UBound(b) - LBound(b) + 1
  355.    m_hRgn = ExtCreateRegion(ByVal 0&, dwCount, b(0))
  356.    pbLoadFromByteArray = Not (m_hRgn = 0)
  357.    
  358. End Function
  359.  
  360. Private Sub Class_Terminate()
  361.    Destroy
  362. End Sub
  363.  
  364.  
  365.