Getting external application minimize and maximize status. Cannot figure out error - vb.net

I am trying to get the status of my application when is maximized or minimized. I rewrote the script so that its specific for Excel application. However, I am getting an error on this line:
Private Sub GetWindowStats(Process.GetProcessesByName("Excel")(0).MainWindowHandle)
It says that it needs a comma or ")" is expected. I can't see why it would need one and even if I put one, still get a compile error. Here is my entire code:
'Handle the minimize and maximize events on Excel.
Private Const SW_SHOWMAXIMIZED As Integer = 3
Private Const SW_SHOWMINIMIZED As Integer = 2
Private Const SW_SHOWNORMAL As Integer = 1
Private Structure POINTAPI
Public x As Integer
Public y As Integer
End Structure
Private Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
Private Structure WINDOWPLACEMENT
Public Length As Integer
Public flags As Integer
Public showCmd As Integer
Public ptMinPosition As POINTAPI
Public ptMaxPosition As POINTAPI
Public rcNormalPosition As RECT
End Structure
Private Declare Function GetWindowPlacement Lib "user32" (ByVal hwnd As IntPtr, ByRef lpwndpl As WINDOWPLACEMENT) As Integer
Private Declare Function GetForegroundWindow Lib "user32" Alias "GetForegroundWindow" () As IntPtr
Private Sub GetWindowStats(Process.GetProcessesByName("Excel")(0).MainWindowHandle)
Dim wp As WINDOWPLACEMENT
wp.Length = System.Runtime.InteropServices.Marshal.SizeOf(wp)
GetWindowPlacement(Handle, wp)
If wp.showCmd = SW_SHOWMAXIMIZED Then ' is window maximized?
If Handle = GetForegroundWindow Then ' is the window foreground?
MessageBox.Show("Maximized and forground")
Else
MessageBox.Show("Maximized")
End If
ElseIf wp.showCmd = SW_SHOWNORMAL Then
If Handle = GetForegroundWindow Then
MessageBox.Show("Normal size and forground")
Else
MessageBox.Show("Normal")
End If
ElseIf wp.showCmd = SW_SHOWMINIMIZED Then
MessageBox.Show("Window is Minimized")
End If
End Sub

That is because it need the type for the parameter for this sub routine not the value.
Private Sub GetWindowStats(Handle As IntPtr)
Dim wp As WINDOWPLACEMENT
wp.Length = System.Runtime.InteropServices.Marshal.SizeOf(wp)
GetWindowPlacement(Handle, wp)
If wp.showCmd = SW_SHOWMAXIMIZED Then ' is window maximized?
If Handle = GetForegroundWindow Then ' is the window foreground?
MessageBox.Show("Maximized and forground")
Else
MessageBox.Show("Maximized")
End If
ElseIf wp.showCmd = SW_SHOWNORMAL Then
If Handle = GetForegroundWindow Then
MessageBox.Show("Normal size and forground")
Else
MessageBox.Show("Normal")
End If
ElseIf wp.showCmd = SW_SHOWMINIMIZED Then
MessageBox.Show("Window is Minimized")
End If
End Sub
To Call it:
GetWindowStats(Process.GetProcessesByName("Excel")(0).MainWindowHandle)
Remember if there are no Excel processes this will throw an error.

Related

Check internet connection from Excel VBA

I need to check the Internet connection when an Excel workbook opens. For that, I'm trying the following code:
Private Declare PtrSafe Function InternetGetConnectedState _
Lib "wininet.dll" (ByRef dwflags As Long, _
ByVal dwReserved As Long) As Long
Private Const INTERNET_CONNECTION_MODEM As Long = &H1
Private Const INTERNET_CONNECTION_LAN As Long = &H2
Private Const INTERNET_CONNECTION_PROXY As Long = &H4
Private Const INTERNET_CONNECTION_OFFLINE As Long = &H20
Function IsInternetConnected() As Boolean
Dim L As Long
Dim R As Long
R = InternetGetConnectedState(L, 0&)
If R = 0 Then
IsInternetConnected = False
Else
If R <= 4 Then
IsInternetConnected = True
Else
IsInternetConnected = False
End If
End If
End Function
It works, but some users are reporting this is breaking Excel (it freezes Excel forever).
Is there a way to throw an error or somehow correct this code in order to find out what is the cause of the problem (Firewall, etc.)?
Thank you so much for helping!
Here are the proper imports with compiler directives.
Option Explicit
#If Win64 Then
Public Flg As LongPtr
Public Declare PtrSafe Function InternetGetConnectedState _
Lib "wininet.dll" (lpdwFlags As LongPtr, _
ByVal dwReserved As Long) As Boolean
#Else
Public Flg As Long
Public Declare Function InternetGetConnectedState _
Lib "wininet.dll" (lpdwFlags As Long, _
ByVal dwReserved As Long) As Boolean
#End If
Private Const INTERNET_CONNECTION_MODEM As Long = &H1
Private Const INTERNET_CONNECTION_LAN As Long = &H2
Private Const INTERNET_CONNECTION_PROXY As Long = &H4
Private Const INTERNET_CONNECTION_OFFLINE As Long = &H20
Function IsInternetConnected() As Boolean
Dim R As Long
R = InternetGetConnectedState(Flg, 0&)
If Flg >= INTERNET_CONNECTION_OFFLINE Then
Debug.Print "INTERNET_CONNECTION_OFFLINE"
End If
If CBool(R) Then
IsInternetConnected = True
Else
IsInternetConnected = False
End If
End Function
Sub main()
Dim mssg As String
If IsInternetConnected Then
mssg = "Connected"
Else
mssg = "Not connected"
End If
MsgBox mssg
End Sub
I believe at least one of the problems was failing to provide the correct var-type to receive the lpdwFlags. I've added a public var within the compiler directives. The Flg var receives the flags from the function. These can be parsed bitwise against your constants to determine the state. See InternetGetConnectedState for more information (and a full set of flags).
This has been tested on both 32-bit and 64-bit xl2010.

vshost32.exe has stopped working either debugging or myproject.exe

I'm trying to integrate a scanner to my code, in the sample solution they provided, they use DllImport, Delegate functions, callback procedures, etc...
This is just my first encounter with dllImport, delegates, callback procedures, everytime I debug the solution they gave me, starting from initializing, then button click and then suddenly I always get an error "vshost32.exe has stopped working".
Here's my the code:
Imported Functions from DLL:
Private Declare Function rdInit Lib "sb6lib" (ByVal tmo As Integer) As Integer
Private Declare Function rdStart Lib "sb6lib" () As Integer
Private Declare Function rdsConfig Lib "sb6lib" (ByVal Wnd As Integer, ByVal confile As String) As Integer
Private Declare Function rdConfigAPI Lib "sb6lib" (ByVal tmo As Integer, ByVal tmo As Integer) As Integer
Use of delegates to implement callback procedures.
Public Delegate Sub FeederEmptyDelegate(ByVal x As Integer)
Private Declare Function rdOnFeederEmpty Lib "sb6lib" (ByVal lpfeederempty As FeederEmptyDelegate) As Integer
Public Delegate Sub AllDoneDelegate(ByVal x As Integer)
Private Declare Function rdOnAllDone Lib "sb6lib" (ByVal lpx As AllDoneDelegate) As Integer
Delegate Function CodeLineVBDelegate(ByVal lpx As IntPtr) As Integer
Private Declare Function rdOnCodeLineVB Lib "sb6lib" (ByVal lpx As CodeLineVBDelegate) As Integer
Public Delegate Sub ErrorDelegate(ByVal x As Integer)
Private Declare Function rdOnError Lib "sb6lib" (ByVal lpx As ErrorDelegate) As Integer
Public Delegate Function DocumentDoneDelegate(ByVal lpx As Integer) As Integer
Private Declare Function rdOnDocumentDone Lib "sb6lib" (ByVal lpx As DocumentDoneDelegate) As Integer
On Command1_Click Event -Stands for Initialize Button
Public Sub Command1_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command1.Click
Dim rtnval As Object
' find the RDS and initialize the API
rtnval = rdInit(-1)
List1.Items.Add(("rdInit returns " & rtnval))
If rtnval > -1 Then
rtnval = rdConfigAPI(4101, 0)
rtnval = rdsConfig(Frame1.Handle.ToInt32, ".\\DOCDES0.DES")
List1.Items.Add(("rdsConfig returns " & rtnval))
'Callbacks
rtnval = rdOnFeederEmpty(AddressOf feederempty)
rtnval = rdOnAllDone(AddressOf alldone)
rtnval = rdOnCodeLineVB(AddressOf codeline)
rtnval = rdOnError(AddressOf onerror)
rtnval = rdOnDocumentDone(AddressOf docdone)
Command2.Enabled = True
Command1.Enabled = False
Command3.Enabled = True
ViewButton.Enabled = True
End If
End Sub
On Command2_Click Event -Stands for Start Scanning Button
Private Sub Command2_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command2.Click
Dim rtnval As Object
rtnval = rdStart()
List1.Items.Add(("rdStart returns " & rtnval))
End Sub
After the scanning (End Sub) it goes to the Callback function "codeline": (Debug Mode)
Private Function codeline(ByVal x As IntPtr) As Integer
' called when a codeline is available
Dim cl As String
cl = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(x) 'conversion necessary as passed argument is a BSTR type string in sb6lib
If Me.InvokeRequired Then
Me.Invoke(New WriteTextBoxDelegate(AddressOf codeline), New Object() {x})
Else
yval.Text = "CL: " & cl
End If
codeline = 1
End Function
and then the application stopped working ("vshost32.exe has stopped working").
Can sombebody tell me what causes the crashing of the application? Thanks!

How to activate, move and resize a window in VB.NET

I have a window of which I know only the title (e.g. Notepad) that I need to activate, resize and place in the top-left corner of my screen.
So after some research on MSDN and forums I found some functions that should achieve this. I use FindWindow to get the handle by title, then I use GetWindowPlacement to see if notepad is minimized or not (if not, then I just use AppActivate, only need to activate it if it's not minimized). If the window is minimized however, I then try to use SetWindowPlacement to activate, resize and move it in one command.
Here is my code:
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll")> _
Private Shared Function GetWindowPlacement(ByVal hWnd As IntPtr, ByRef lpwndpl As WINDOWPLACEMENT) As Boolean
End Function
<DllImport("user32.dll")> _
Private Shared Function SetWindowPlacement(ByVal hWnd As IntPtr, ByRef lpwndpl As WINDOWPLACEMENT) As Boolean
End Function
Private Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
Public Sub New(ByVal X As Integer, ByVal Y As Integer, ByVal X2 As Integer, ByVal Y2 As Integer)
Me.Left = X
Me.Top = Y
Me.Right = X2
Me.Bottom = Y2
End Sub
End Structure
Private Structure WINDOWPLACEMENT
Public Length As Integer
Public flags As Integer
Public showCmd As ShowWindowCommands
Public ptMinPosition As POINTAPI
Public ptMaxPosition As POINTAPI
Public rcNormalPosition As RECT
End Structure
Enum ShowWindowCommands As Integer
Hide = 0
Normal = 1
ShowMinimized = 2
Maximize = 3
ShowMaximized = 3
ShowNoActivate = 4
Show = 5
Minimize = 6
ShowMinNoActive = 7
ShowNA = 8
Restore = 9
ShowDefault = 10
ForceMinimize = 11
End Enum
Public Structure POINTAPI
Public X As Integer
Public Y As Integer
Public Sub New(ByVal X As Integer, ByVal Y As Integer)
Me.X = X
Me.Y = Y
End Sub
End Structure
With the actual execution being here:
Dim wp As WINDOWPLACEMENT
wp.Length = Marshal.SizeOf(wp)
GetWindowPlacement(FindWindow(Nothing, "Notepad"), wp)
If wp.showCmd = ShowWindowCommands.ShowMinimized Then
Dim wp2 As WINDOWPLACEMENT
wp2.showCmd = ShowWindowCommands.ShowMaximized
wp2.ptMinPosition = wp.ptMinPosition
wp2.ptMaxPosition = New POINTAPI(0, 0)
wp2.rcNormalPosition = New RECT(0, 0, 816, 639) 'this is the size I want
wp2.flags = wp.flags
wp2.Length = Marshal.SizeOf(wp2)
SetWindowPlacement(FindWindow(Nothing, "Notepad"), wp2)
Else
AppActivate("Notepad")
So I try running this but it just activates the window, while the rectangle is supposed to also resize it. So what am I doing wrong? Is there an easier way to achieve all of this? Sorry for the lengthy post
I had to do a similar thing, and used the SetWindowPos function from user32.dll
Here's a vb.net implementation:
Imports System
Imports System.Runtime.InteropServices
Imports System.Diagnostics
Public Class HookUtil
Public Const SWP_NOMOVE As Short = &H2
Public Const SWP_NOSIZE As Short = 1
Public Const SWP_NOZORDER As Short = &H4
Public Const SWP_SHOWWINDOW As Short = &H40
Shared ReadOnly HWND_BOTTOM As IntPtr = New IntPtr(1)
<DllImport("user32.dll", EntryPoint:="SetWindowPos")> _
Public Shared Function SetWindowPos( _
hWnd As IntPtr, _
hWndInsertAfter As IntPtr, _
x As Int32, y As Int32, cx As Int32, cy As Int32, wFlags As Int32) As IntPtr
End Function
Public Shared Sub HookWindow()
Dim Processes As Process() = Process.GetProcessesByName("Notepad")
For Each p As Process In Processes
Dim handle As IntPtr = p.MainWindowHandle
If handle <> IntPtr.Zero Then
SetWindowPos(handle, HWND_BOTTOM, 200, 200, 0, 0, SWP_NOZORDER Or SWP_NOSIZE Or SWP_SHOWWINDOW)
End If
Next
End Sub
End Class
You call it with:
HookUtil.HookWindow()
Here's a C# implementation:
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace csharpsandbox
{
public class HookUtil
{
// hooks window handle and repositions to specified coords
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
[DllImport("kernel32.dll")]
static extern IntPtr LoadLibrary(string lpFileName);
const short SWP_NOMOVE = 0X2;
const short SWP_NOSIZE = 1;
const short SWP_NOZORDER = 0X4;
const int SWP_SHOWWINDOW = 0x0040;
static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
public static void HookWindow()
{
Process[] parray = System.Diagnostics.Process.GetProcessesByName("Notepad");
foreach (Process p in parray)
{
IntPtr handle = p.MainWindowHandle;
if (handle != IntPtr.Zero)
{
SetWindowPos(handle, HWND_BOTTOM, 200, 200, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
}
}
}
}
}
You call it with:
HookUtil.HookWindow();
Obviously the values here (process name, x,y coordinates) are hard-coded. To make this more useful you'd want to make those settable.

How can I show a ToolTip for a TextBox only under certain conditions

In VB6 I could easily create a balloon message that would be shown next to the textbox.
It would automatically disappear as soon as the text is changed.
I could use this balloon tooltip for messages like "Enter a valid eMail address!".
I used the Windows API to create this balloon. I have attached the code below.
Is there no framework solution for this?
Thank you for the help!
Option Explicit
Private Const ECM_FIRST = &H1500 '// Edit control messages
Private Const EM_SETCUEBANNER = (ECM_FIRST + 1)
Private Const EM_GETCUEBANNER = (ECM_FIRST + 2) '// Set the cue banner with the lParm = LPCWSTR
Private Type EDITBALLOONTIP
cbStruct As Long
pszTitle As Long
pszText As Long
ttiIcon As Long ' ; // From TTI_*
End Type
Private Const EM_SHOWBALLOONTIP = (ECM_FIRST + 3) '// Show a balloon tip associated to the edit control
Private Const EM_HIDEBALLOONTIP = (ECM_FIRST + 4) '// Hide any balloon tip associated with the edit control
Private Declare Function SendMessageW Lib "user32" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Declare Function LocalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal wBytes As Long) As Long
Private Declare Function LocalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function LocalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function LocalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Const GMEM_FIXED = &H0
Private Const GMEM_ZEROINIT = &H40
Private Const GPTR = (GMEM_FIXED Or GMEM_ZEROINIT)
Private m_hWnd As Long
Private m_sCueBanner As String
Private m_sTitle As String
Private m_sText As String
Private m_eIcon As BalloonTipIconConstants
Public Property Let TextBox(txtThis As TextBox)
m_hWnd = txtThis.hwnd
End Property
Public Property Let CueBanner(ByVal value As String)
m_sCueBanner = value
setCueBanner
End Property
Public Property Get CueBanner() As String
CueBanner = m_sCueBanner
End Property
Public Property Let BalloonTipTitle(ByVal value As String)
m_sTitle = value
End Property
Public Property Get BalloonTipTitle() As String
BalloonTipTitle = m_sTitle
End Property
Public Property Let BalloonTipText(ByVal value As String)
m_sText = value
End Property
Public Property Get BalloonTipText() As String
BalloonTipText = m_sText
End Property
Public Property Let BalloonTipIcon(ByVal value As BalloonTipIconConstants)
m_eIcon = value
End Property
Public Property Get BalloonTipIcon() As BalloonTipIconConstants
BalloonTipIcon = m_eIcon
End Property
Public Sub ShowBalloonTip()
Dim lR As Long
Dim tEBT As EDITBALLOONTIP
tEBT.cbStruct = LenB(tEBT)
tEBT.pszText = StrPtr(m_sText)
tEBT.pszTitle = StrPtr(m_sTitle)
tEBT.ttiIcon = m_eIcon
lR = SendMessageW(m_hWnd, EM_SHOWBALLOONTIP, 0, tEBT)
End Sub
Public Sub HideBalloonTip()
Dim lR As Long
lR = SendMessageLongW(m_hWnd, EM_HIDEBALLOONTIP, 0, 0)
Debug.Print lR
End Sub
Private Sub setCueBanner()
Dim lR As Long
' Reports success, but doesn'/t actually work...
' (is this because the VB text box is ANSI?)
lR = SendMessageLongW(m_hWnd, EM_SETCUEBANNER, 0, StrPtr(m_sCueBanner))
Debug.Print lR
End Sub
You can set a tooltip like this
Dim toolTip1 As New ToolTip()
toolTip1.SetToolTip(Me.textbox1, "Hello World")
and hide the tooltip with
toolTip1.SetToolTip(Me.textbox1, "")
Note that you can also add a ToolTip-Control to the form the toolbox instead of creating it programmatically. It magically adds a ToolTip-property to all controls in the properties window where you can enter a tooltip message. The controls themselves, however, will not aquire a ToolTip property and you can only set or remove the tooltip through the ToolTip.SetToolTip method in code.
I think it can only be done in the way I want it using the API way.
I found a perfect migration of my VB6 sample here:
http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=7109&lngWId=10

Error PInvoking Function

I have the following code as part of my control. SetReaderMode function creates the structure and calls the function explained here, http://msdn.microsoft.com/en-us/library/bb775599(VS.85).aspx
When I run this code, i get the error
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I'm not sure what the issue may be. What am I doing wrong?
<DllImport("Comctl32.dll", EntryPoint:="#383", _
CallingConvention:=CallingConvention.StdCall)> _
Private Shared Sub DoReaderMode(prmi As READERMODEINFO)
End Sub
<StructLayout(LayoutKind.Sequential)>
Private Structure READERMODEINFO
Dim cbSize As UInt32
Dim hwnd As IntPtr
Dim fFlags As UInt32
Dim prc As IntPtr
Dim pfnScroll As ReaderScrollCallbackDelegate
Dim fFlags2 As TranslateDispatchCallbackDelegate
Dim lParam As IntPtr
End Structure
Private Sub SetReaderMode()
Dim Info As New READERMODEINFO
Info.hwnd = Me.Handle
Info.fFlags = 0
Info.prc = IntPtr.Zero
Info.pfnScroll = New ReaderScrollCallbackDelegate(AddressOf ReaderScrollCallback)
Info.fFlags2 = New TranslateDispatchCallbackDelegate(AddressOf TranslateDispatchCallback)
Info.lParam = IntPtr.Zero
Info.cbSize = Marshal.SizeOf(Info)
DoReaderMode(Info)
End Sub
Private Delegate Function ReaderScrollCallbackDelegate(ByVal prmi As READERMODEINFO, dx As Integer, dy As Integer) As Boolean
Private Delegate Function TranslateDispatchCallbackDelegate(lpmsg As IntPtr) As Boolean
<AllowReversePInvokeCalls()>
Private Function TranslateDispatchCallback(lpmsg As IntPtr) As Boolean
Return True
End Function
<AllowReversePInvokeCalls()>
Private Function ReaderScrollCallback(ByVal prmi As READERMODEINFO, dx As Int32, dy As Int32) As Boolean
Return True
End Function
Is not an easy nut to crack. Assuming the callback are correct in term of signature/calling convention, a problem can be that since the carbage collector collect Info at the end of the function SetReaderMode, the callback address becames invalid. So try to declare Info as a member variable. If the error remain callback signature has something wrong, but as I said, not so easy to see the error at a glance.
I've figured it out. After reviewing the documentation more closely, I've added a ByRef to the DoReaderMode definition and to the ReaderScrollCallback definition, since the arguments where defined as pointers to structures, not just structures. I also added some other code to pass the rectangle in the ReaderModeInfo structure.
Below is the working code. Interestingly, the documentation states that you click to exit ReaderMode, however when testing it looks like you have to hold the button down and release to exit.
<DllImport("Comctl32.dll", EntryPoint:="#383", _
CallingConvention:=CallingConvention.StdCall)> _
Private Shared Sub DoReaderMode(ByRef prmi As READERMODEINFO)
End Sub
<StructLayout(LayoutKind.Sequential)>
Private Structure READERMODEINFO
Dim cbSize As UInt32
Dim hwnd As IntPtr
Dim fFlags As UInt32
Dim prc As IntPtr
Dim pfnScroll As ReaderScrollCallbackDelegate
Dim fFlags2 As TranslateDispatchCallbackDelegate
Dim lParam As IntPtr
End Structure
Private Sub SetReaderMode()
Dim SetReaderModeInfo As READERMODEINFO
Dim rect As New Interop.RECT(Me.Width / 2 - 20, Me.Height / 2 - 20, Me.Width / 2 + 20, Me.Height / 2 + 20)
Dim pnt As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(rect))
Marshal.StructureToPtr(rect, pnt, True)
SetReaderModeInfo = New READERMODEINFO
SetReaderModeInfo.hwnd = Me.Handle
SetReaderModeInfo.fFlags = 1
SetReaderModeInfo.prc = pnt
SetReaderModeInfo.pfnScroll = New ReaderScrollCallbackDelegate(AddressOf ReaderScrollCallback)
SetReaderModeInfo.fFlags2 = New TranslateDispatchCallbackDelegate(AddressOf TranslateDispatchCallback)
SetReaderModeInfo.lParam = IntPtr.Zero
SetReaderModeInfo.cbSize = Marshal.SizeOf(SetReaderModeInfo)
DoReaderMode(SetReaderModeInfo)
Marshal.FreeHGlobal(pnt)
End Sub
Private Delegate Function ReaderScrollCallbackDelegate(ByRef prmi As READERMODEINFO, dx As Integer, dy As Integer) As Boolean
Private Delegate Function TranslateDispatchCallbackDelegate(ByRef lpmsg As Interop.MSG) As Boolean
Private Function TranslateDispatchCallback(ByRef lpmsg As Interop.MSG) As Boolean
Return False
End Function
Private Function ReaderScrollCallback(ByRef prmi As READERMODEINFO, dx As Int32, dy As Int32) As Boolean
Return True
End Function