Screen Capture implementation using Magnification api

  • Thread starter Thread starter FL4SHC0D3R
  • Start date Start date
F

FL4SHC0D3R

Guest
I'm trying translate this project to VB.NET of a way more clear and easy possible. But in this moment have appears some troubles and doubts that are:


1 - In this line have a exception (i'm not able to exclude the specific window):

If Not MagSetWindowFilterList(hwndMag, FilterMode.MW_FILTERMODE_EXCLUDE, 1, hwndArray(0)) Then
MessageBox.Show("Fail to set WindowFilterList.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End If

2 - Based on example of CodeProject site, i want know why on VC++ was possible hide Magnifier window (MFC hostDlg form on example of CodeProject) and works fine the screen capture and on my following code if i do this, screen capture fails?

Form2.Show()

SetWindowPos(Form2.Handle, New IntPtr(-1), 0, R.Right, R.Bottom, 0, SWP_HIDEWINDOW)
SetWindowLong(Form2.Handle, WindowLongFlags.GWL_EXSTYLE, WindowLongFlags.GWL_EXSTYLE Or WS_EX_LAYERED)
SetLayeredWindowAttributes(Form2.Handle, 0, 255, LWA_ALPHA)

3 - On my callback routine i always have:

bih.biSizeImage < 1


  • Here is complete code:

Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.IO

Public Class Form1

Private Const SWP_HIDEWINDOW As Integer = &H80
Private Const SWP_SHOWWINDOW = &H40

Private Const WS_EX_LAYERED = &H80000
Private Const LWA_ALPHA = &H2

Public Structure RECT
Public Left As Int32
Public Top As Int32
Public Right As Int32
Public Bottom As Int32
End Structure

Public Structure BITMAPINFOHEADER
Dim biSize As Int32
Dim biWidth As Int32
Dim biHeight As Int32
Dim biPlanes As Int16
Dim biBitCount As Int16
Dim biCompression As Int32
Dim biSizeImage As Int32
Dim biXPelsPerMeter As Int32
Dim biYPelsPerMeter As Int32
Dim biClrUsed As Int32
Dim biClrImportant As Int32
End Structure

Private Const BI_RGB As Integer = 0
Private Const BI_BITFIELDS As Integer = 3
Private Const BI_RLE8 As Integer = 1
Private Const BI_RLE4 As Integer = 2

Public Structure BITMAPFILEHEADER
Dim bfType As Short
Dim bfSize As Integer
Dim bfReserved1 As Short
Dim bfReserved2 As Short
Dim bfOffBits As Integer
End Structure

Private Enum ShowWindowStyles As Short
SW_HIDE = 0
SW_SHOWNORMAL = 1
SW_NORMAL = 1
SW_SHOWMINIMIZED = 2
SW_SHOWMAXIMIZED = 3
SW_MAXIMIZE = 3
SW_SHOWNOACTIVATE = 4
SW_SHOW = 5
SW_MINIMIZE = 6
SW_SHOWMINNOACTIVE = 7
SW_SHOWNA = 8
SW_RESTORE = 9
SW_SHOWDEFAULT = 10
SW_FORCEMINIMIZE = 11
SW_MAX = 11
End Enum

Public Enum WindowLongFlags As Integer
GWL_EXSTYLE = -20
GWLP_HINSTANCE = -6
GWLP_HWNDPARENT = -8
GWL_ID = -12
GWL_STYLE = -16
GWL_USERDATA = -21
GWL_WNDPROC = -4
DWLP_USER = &H8
DWLP_MSGRESULT = &H0
DWLP_DLGPROC = &H4
End Enum

Private Const WS_OVERLAPPED As Integer = &H0
Private Const WS_MAXIMIZEBOX As Integer = &H10000
Private Const WS_MINIMIZEBOX As Integer = &H20000
Private Const WS_THICKFRAME As Integer = &H40000
Private Const WS_SYSMENU As Integer = &H80000
Private Const WS_HSCROLL As Integer = &H100000
Private Const WS_VSCROLL As Integer = &H200000
Private Const WS_DLGFRAME As Integer = &H400000
Private Const WS_BORDER As Integer = &H800000
Private Const WS_CAPTION As Integer = &HC00000
Private Const WS_MAXIMIZE As Integer = &H1000000
Private Const WS_CLIPCHILDREN As Integer = &H2000000
Private Const WS_CLIPSIBLINGS As Integer = &H4000000
Private Const WS_DISABLED As Integer = &H8000000
Private Const WS_VISIBLE As Integer = &H10000000
Private Const WS_MINIMIZE As Integer = &H20000000
Private Const WS_CHILD As Integer = &H40000000
Private Const WS_POPUP As Integer = &H80000000
Private Const WS_TABSTOP As Integer = WS_MAXIMIZEBOX
Private Const WS_GROUP As Integer = WS_MINIMIZEBOX
Private Const WS_OVERLAPPEDWINDOW As Integer = WS_OVERLAPPED Or WS_CAPTION Or WS_SYSMENU Or WS_THICKFRAME Or WS_MINIMIZEBOX Or WS_MAXIMIZEBOX
Private Const WS_POPUPWINDOW As Integer = WS_POPUP Or WS_BORDER Or WS_SYSMENU

<DllImport("user32.dll", SetLastError:=False)>
Private Shared Function GetDesktopWindow() As IntPtr
End Function

<DllImport("user32.dll", SetLastError:=False)>
Private Shared Function GetWindowRect(ByVal hwnd As Int32, ByRef lpRect As RECT) As Int32
End Function

<DllImport("user32.dll", EntryPoint:="CreateWindowExW", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.StdCall)>
Private Shared Function CreateWindowExW(ByVal dwExStyle As Integer, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hWndParent As IntPtr, ByVal hMenu As IntPtr, ByVal hInstance As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function

<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Public Shared Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr
End Function

<DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)>
Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Int32, ByVal Y As Int32, ByVal cx As Int32, ByVal cy As Int32, ByVal uFlags As Int32) As Boolean
End Function

<DllImport("user32.dll", EntryPoint:="SetWindowLong")>
Private Shared Function SetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer, ByVal dwNewLong As Integer) As Integer
End Function

<DllImport("user32.dll")>
Private Shared Function SetLayeredWindowAttributes(ByVal hwnd As IntPtr, ByVal crKey As UInteger, ByVal bAlpha As Byte, ByVal dwFlags As UInteger) As Boolean
End Function

'======================================================== Magnification api ==================================================================

Private Enum MagnifierStyle As Integer
MS_SHOWMAGNIFIEDCURSOR = 1
MS_CLIPAROUNDCURSOR = 2
MS_INVERTCOLORS = 4
End Enum

Private Enum FilterMode
MW_FILTERMODE_EXCLUDE = 0
MW_FILTERMODE_INCLUDE = 1
End Enum

Public Const WC_MAGNIFIER As String = "Magnifier"

Public Structure MAGIMAGEHEADER
Public width As UInteger
Public height As UInteger
Public format As Guid
Public stride As UInteger
Public offset As UInteger
Public cbSize As UInteger
End Structure

Private Delegate Function MagImageScalingCallback(ByVal hwnd As IntPtr, ByVal srcdata As IntPtr, ByVal srcheader As MAGIMAGEHEADER, ByRef destdata As IntPtr, ByVal destheader As MAGIMAGEHEADER, ByVal unclipped As RECT, ByVal clipped As RECT, ByVal dirty As IntPtr) As Boolean

<DllImport("Magnification.dll", CallingConvention:=CallingConvention.StdCall)>
Private Shared Function MagInitialize() As Boolean
End Function

<DllImport("Magnification.dll", CallingConvention:=CallingConvention.StdCall)>
Private Shared Function MagUninitialize() As Boolean
End Function

<DllImport("Magnification.dll", CallingConvention:=CallingConvention.StdCall)>
Private Shared Function MagSetWindowSource(ByVal hwnd As IntPtr, ByVal rect As RECT) As Boolean
End Function

<DllImport("Magnification.dll", CallingConvention:=CallingConvention.StdCall)>
Private Shared Function MagSetWindowFilterList(ByVal hwnd As IntPtr, ByVal dwFilterMode As Integer, ByVal count As Integer, ByVal pHWND As IntPtr) As Boolean
End Function

<DllImport("Magnification.dll", CallingConvention:=CallingConvention.StdCall)>
Private Shared Function MagSetImageScalingCallback(ByVal hwnd As IntPtr, ByVal callback As MagImageScalingCallback) As Boolean
End Function

'===============================================================================================================================================

Private hwndMag As IntPtr
Private initialized As Boolean
Private hwndArray(1) As IntPtr
Private R As RECT

Private Function RoutineImageScalingCallback(ByVal hwnd As IntPtr, ByVal srcdata As IntPtr, ByVal srcheader As MAGIMAGEHEADER, ByRef destdata As IntPtr, ByVal destheader As MAGIMAGEHEADER, ByVal unclipped As RECT, ByVal clipped As RECT, ByVal dirty As IntPtr) As Boolean

Dim bih As BITMAPINFOHEADER

bih = CType(Marshal.PtrToStructure(srcdata, bih.GetType), BITMAPINFOHEADER)
If bih.biSizeImage < 1 Then
MessageBox.Show("biSizeImage is 0.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End If

Dim bitmapData(bih.biSizeImage) As Byte
Dim address As Integer = srcdata + Marshal.SizeOf(bih)

For offset As Integer = 0 To bitmapData.Length - 1
bitmapData(offset) = Marshal.ReadByte(New IntPtr(address))
address += 1
Next offset

Dim bitmapInfo(Marshal.SizeOf(bih)) As Byte
Dim ptr As IntPtr = Marshal.AllocHGlobal(bitmapInfo.Length)

Marshal.StructureToPtr(bih, ptr, False)
address = ptr.ToInt32

For offset As Integer = 0 To bitmapInfo.Length - 1
bitmapInfo(offset) = Marshal.ReadByte(New IntPtr(address))
address += 1
Next offset

Marshal.FreeHGlobal(ptr)

Dim bfh As BITMAPFILEHEADER
bfh.bfType = &H4D42 ' "BM"
bfh.bfSize = 55 + bih.biSizeImage
bfh.bfReserved1 = 0
bfh.bfReserved2 = 0
bfh.bfOffBits = Marshal.SizeOf(bih) + Marshal.SizeOf(bfh)

Using fs As New FileStream("C:\MyScreen.bmp", System.IO.FileMode.Create)

Dim bw As New BinaryWriter(fs)

bw.Write(bfh.bfType)
bw.Write(bfh.bfSize)
bw.Write(bfh.bfReserved1)
bw.Write(bfh.bfReserved2)
bw.Write(bfh.bfOffBits)
bw.Write(bitmapInfo)
bw.Write(bitmapData)
bw.Close()
End Using

Return True

End Function

Private Sub BtnCapture_Click(sender As Object, e As EventArgs) Handles BtnCapture.Click

'If Not MagSetWindowFilterList(hwndMag, FilterMode.MW_FILTERMODE_EXCLUDE, 1, hwndArray(0)) Then
'MessageBox.Show("Fail to set WindowFilterList.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
'Exit Sub
'End If

R.Top = 0
R.Left = 0

If Not MagSetWindowSource(hwndMag, R) Then
MessageBox.Show("Fail to set WindowSource.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End If

End Sub

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

Dim MyImageScalingCallback As MagImageScalingCallback
Dim Desktop As IntPtr
Dim hInst As IntPtr

Desktop = GetDesktopWindow()
GetWindowRect(Desktop, R)

'-----------------------------------------------------------------------------------------------------

initialized = MagInitialize()

If Not initialized Then
MessageBox.Show("Magnification API not initialized.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End If

hwndArray(0) = Me.Handle

hInst = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly.GetModules()(0)).ToInt32()

Form2.Show()

'SetWindowPos(Form2.Handle, New IntPtr(-1), 0, R.Right, R.Bottom, 0, SWP_HIDEWINDOW)
'SetWindowLong(Form2.Handle, WindowLongFlags.GWL_EXSTYLE, WindowLongFlags.GWL_EXSTYLE Or WS_EX_LAYERED)
'SetLayeredWindowAttributes(Form2.Handle, 0, 255, LWA_ALPHA)

hwndMag = CreateWindowExW(0, WC_MAGNIFIER, "MagnifierWindow", WS_CHILD Or MagnifierStyle.MS_SHOWMAGNIFIEDCURSOR Or WS_VISIBLE, 0, 0, R.Right, R.Bottom, Form2.Handle, IntPtr.Zero, hInst, IntPtr.Zero)

If hwndMag.Equals(IntPtr.Zero) Then
MessageBox.Show("Fail to create MagnifierWindow.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End If

MyImageScalingCallback = AddressOf RoutineImageScalingCallback

If Not MagSetImageScalingCallback(hwndMag, MyImageScalingCallback) Then
MessageBox.Show("Fail to set RoutineImageScalingCallback.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End If

End Sub

Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing

If initialized Then
MagUninitialize()
End If

End Sub
End Class

Continue reading...
 
Back
Top