Declaring API functions for 64 bit Office (and Mac Office)
Content
Introduction
If you develop VBA code for multiple versions of Office, you may face
a challenge: ensuring your code works on both 32 bit and 64 bit platforms.
This page is meant to be the first stop for anyone who needs the proper
syntax for his API declaration statement in Office VBA.
Many of the declarations were figured out by Charles Williams of
www.decisionmodels.com
when he created the 64 bit version of our
Name Manager.
All of these are Windows API calls. Some have Mac equivalents however
(like the CopyMemory one). I'll try to add those
as I find them.
Links
Of course Microsoft documents how to do this. There is an introductory
article on Microsoft MSDN:
Compatibility Between the 32-bit and 64-bit Versions of Office 2010
That article describes the how-to's to properly write the declarations.
What is missing is which type declarations go with which API function or
sub.
Microsoft has provided an updated version of the Win32API.txt with all
proper declarations available for download here:
Office 2010 Help Files: Win32API_PtrSafe with 64-bit Support
When you run the installer after downloading the file form
the link above, it does not tell you where it installed the information.
Look in this -new- folder on your C drive:
C:\Office 2010 Developer Resources\Documents\Office2010Win32API_PtrSafe
You can find a list of the old Win32 API declarations here:
Visual Basic Win32 API Declarations
Microsoft also published a tool to check your code for 64 bit related
problems, called the
Microsoft Office Code Compatibility inspector addin.
API functions that were added/modified in 64-bit Windows:
http://msdn.microsoft.com/en-us/library/aa383663(VS.85).aspx
API Functions by Windows release:
http://msdn.microsoft.com/en-us/library/aa383687(VS.85).aspx
Utter Access API declarations (a comprehensive list of many declarations)
Last, but certainly not least: Dennis Walentin has built an API viewer
that is really helpful. You can
find the API viewer here.
Declarations by API function
#If VBA7 Then
Declare PtrSafe Function
CloseClipboard Lib "User32" ()
As LongPtr
#Else
Declare Function
CloseClipboard Lib "User32" ()
As Long
#End If
#If Mac Then
Private Declare
PtrSafe Function CopyMemory_byVar
Lib "libc.dylib" Alias "memmove" (ByRef
dest As Any, ByRef
src As Any, ByVal
size As Long)
As LongPtr
#Else
#If VBA7 Then
Public
Declare PtrSafe Sub
CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
_
(ByRef destination As
Any, ByRef SOURCE As
Any, ByVal Length As
LongPtr)
#Else
Public
Declare Sub CopyMemory
Lib "kernel32" Alias "RtlMoveMemory" _
(ByRef
destination As Any, ByRef
SOURCE As Any, ByVal
Length As Long)
#End If
#End If
This is a complicated one because it has a lot of arguments. A fully
functional example is included below the example declaration lines.
Courtesy:
The example code was taken from this page
'Full example shown below, including the necessary
structures
#If VBA7 Then
Declare PtrSafe
Function CreateProcess Lib "kernel32"
_
Alias "CreateProcessA" (ByVal lpApplicationName
As String, _
ByVal lpCommandLine As
String, _
lpProcessAttributes As SECURITY_ATTRIBUTES,
_
lpThreadAttributes As SECURITY_ATTRIBUTES,
_
ByVal bInheritHandles As
Long, _
ByVal dwCreationFlags As
Long, _
lpEnvironment As Any, _
ByVal lpCurrentDriectory
As String, _
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION)
As LongPtr
Const INFINITE = &HFFFF
Const STARTF_USESHOWWINDOW = &H1
Private Enum enSW
SW_HIDE = 0
SW_NORMAL = 1
SW_MAXIMIZE = 3
SW_MINIMIZE = 6
End Enum
Private Type PROCESS_INFORMATION
hProcess As LongPtr
hThread As LongPtr
dwProcessId As Long
dwThreadId As Long
End Type
Private Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As
Long
dwYCountChars As
Long
dwFillAttribute As
Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Byte
hStdInput As LongPtr
hStdOutput As LongPtr
hStdError As LongPtr
End Type
Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As
LongPtr
bInheritHandle As
Long
End Type
Private Enum enPriority_Class
NORMAL_PRIORITY_CLASS = &H20
IDLE_PRIORITY_CLASS = &H40
HIGH_PRIORITY_CLASS = &H80
End Enum
#Else
Declare Function
CreateProcess Lib "kernel32" _
Alias "CreateProcessA" (ByVal lpApplicationName
As String, _
ByVal lpCommandLine As
String, _
lpProcessAttributes As SECURITY_ATTRIBUTES,
_
lpThreadAttributes As SECURITY_ATTRIBUTES,
_
ByVal bInheritHandles As
Long, _
ByVal dwCreationFlags As
Long, _
lpEnvironment As Any, _
ByVal lpCurrentDriectory
As String, _
lpStartupInfo As STARTUPINFO, _
lpProcessInformation As PROCESS_INFORMATION)
As Long
Const INFINITE = &HFFFF
Const STARTF_USESHOWWINDOW = &H1
Private Enum enSW
SW_HIDE = 0
SW_NORMAL = 1
SW_MAXIMIZE = 3
SW_MINIMIZE = 6
End Enum
Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End Type
Private Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As
Long
dwYCountChars As
Long
dwFillAttribute As
Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Byte
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As
Long
bInheritHandle As Long
End Type
Private Enum enPriority_Class
NORMAL_PRIORITY_CLASS = &H20
IDLE_PRIORITY_CLASS = &H40
HIGH_PRIORITY_CLASS = &H80
End Enum
#End If
Private Function
SuperShell(ByVal App As
String, ByVal WorkDir
As String, dwMilliseconds
As Long, _
ByVal start_size As
enSW, ByVal Priority_Class
As enPriority_Class) As
Boolean
Dim pclass As
Long
Dim sinfo As
STARTUPINFO
Dim pinfo As
PROCESS_INFORMATION
'Not used, but needed
Dim sec1 As
SECURITY_ATTRIBUTES
Dim sec2 As
SECURITY_ATTRIBUTES
'Set the structure size
sec1.nLength = Len(sec1)
sec2.nLength = Len(sec2)
sinfo.cb = Len(sinfo)
'Set the flags
sinfo.dwFlags = STARTF_USESHOWWINDOW
'Set the window's startup position
sinfo.wShowWindow = start_size
'Set the priority class
pclass = Priority_Class
'Start the program
If CreateProcess(vbNullString, App,
sec1, sec2, False, pclass, _
0&, WorkDir, sinfo, pinfo) Then
'Wait
' WaitForSingleObject pinfo.hProcess,
dwMilliseconds
SuperShell = True
Else
SuperShell = False
End If
End Function
Sub Test()
Dim sFile As
String
'Set the dialog's title
sFile = Application.GetOpenFilename("Executables (*.exe), *.exe",
, "")
SuperShell sFile, Left(sFile, InStrRev(sFile, "\")), 0, SW_NORMAL,
HIGH_PRIORITY_CLASS
End Sub
#If VBA7 Then
Private Declare
PtrSafe Function DrawMenuBar
Lib "user32" (ByVal
hWnd As LongPtr) As
Long
#Else
Private Declare
Function DrawMenuBar Lib
"user32" (ByVal hWnd As
Long) As Long
#End If
#If VBA7 Then
Declare PtrSafe
Function EmptyClipboard
Lib "User32" () As
LongPtr
#Else
Declare Function
EmptyClipboard Lib "User32" ()
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function FindWindow
Lib "USER32" Alias "FindWindowA" (ByVal
lpClassName As String,
ByVal lpWindowName As
String) As LongPtr
#Else
Private Declare Function FindWindow
Lib "USER32" Alias "FindWindowA" (ByVal lpClassName
As String, ByVal
lpWindowName As String) As Long
#End If
#If VBA7 Then
Private
Declare PtrSafe Function
FindWindowEx Lib "USER32" _
Alias "FindWindowExA" (ByVal hWnd1
As LongPtr, ByVal
hWnd2 As LongPtr, _
ByVal lpsz1 As
String, ByVal lpsz2
As String)
As LongPtr
#Else
Private
Declare Function
FindWindowEx Lib "USER32" _
Alias "FindWindowExA" (ByVal hWnd1
As Long,
ByVal hWnd2 As
Long, _
ByVal lpsz1 As
String, ByVal lpsz2
As String)
As Long
#End If
GdipCreateBitmapFromFile
#If VBA7 Then
Private Declare
PtrSafe Function GdipCreateBitmapFromFile
Lib "GDIPlus" (ByVal
filename As LongPtr, bitmap
As LongPtr) As
LongPtr
#Else
Private Declare
Function GdipCreateBitmapFromFile
Lib "GDIPlus" (ByVal
filename As Long,
bitmap As Long)
As Long
#End If
GdipCreateHBITMAPFromBitmap
#If VBA7 Then
Private Declare
PtrSafe Function GdipCreateHBITMAPFromBitmap
Lib "GDIPlus" (ByVal
bitmap As LongPtr, hbmReturn
As LongPtr,
ByVal background As
Long) As LongPtr
#Else
Private Declare
Function GdipCreateHBITMAPFromBitmap
Lib "GDIPlus" (ByVal
bitmap As Long,
hbmReturn As Long,
ByVal background As
Long) As Long
#End If
GdipDisposeImage
#If VBA7 Then
Private Declare
PtrSafe Function GdipDisposeImage
Lib "GDIPlus" (ByVal
image As LongPtr) As
LongPtr
#Else
Private Declare
Function GdipDisposeImage
Lib "GDIPlus" (ByVal
image As Long)
As Long
#End If
GdiplusShutdown
#If VBA7 Then
Private Declare
PtrSafe Function GdiplusShutdown
Lib "GDIPlus" (ByVal
token As LongPtr) As
LongPtr
#Else
Private Declare
Function GdiplusShutdown
Lib "GDIPlus" (ByVal
token As Long)
As Long
#End If
GdiplusStartup
#If VBA7 Then
Private Declare
PtrSafe Function GdiplusStartup
Lib "GDIPlus" (token As
LongPtr, inputbuf As GdiplusStartupInput,
Optional ByVal outputbuf
As LongPtr = 0) As
LongPtr
Private Type
GdiplusStartupInput
GdiplusVersion
As Long
DebugEventCallback
As LongPtr
SuppressBackgroundThread
As Long
SuppressExternalCodecs
As Long
End Type
#Else
Private Declare
Function GdiplusStartup
Lib "GDIPlus" (token As
Long, inputbuf As
GdiplusStartupInput, Optional
ByVal outputbuf As
Long = 0) As
Long
Private Type
GdiplusStartupInput
GdiplusVersion
As Long
DebugEventCallback
As Long
SuppressBackgroundThread
As Long
SuppressExternalCodecs
As Long
End Type
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetClassName
Lib "user32" Alias "GetClassNameA" _
(ByVal
hWnd As LongPtr, ByVal
lpClassName As String,
_
ByVal
nMaxCount As LongPtr) As
Long
#Else
Private Declare
Function GetClassName Lib
"user32" Alias "GetClassNameA" _
(ByVal hWnd As
Long, ByVal lpClassName
As String, _
ByVal
nMaxCount As Long)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetDiskFreeSpaceEx
Lib "kernel32" Alias _
"GetDiskFreeSpaceExA"
(ByVal lpDirectoryName
As String, _
lpFreeBytesAvailableToCaller As
Currency, lpTotalNumberOfBytes As _
Currency, lpTotalNumberOfFreeBytes
As Currency)
As LongPtr
#Else
Private Declare
Function GetDiskFreeSpaceEx
Lib "kernel32" _
Alias
"GetDiskFreeSpaceExA" (ByVal lpDirectoryName
As String, _
lpFreeBytesAvailableToCaller As
Currency, _
lpTotalNumberOfBytes As
Currency, _
lpTotalNumberOfFreeBytes As
Currency) As
Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetDC
Lib "user32" (ByVal hWnd
As LongPtr) As
LongPtr
#Else
Private Declare
Function GetDC Lib
"user32" (ByVal hWnd As
Long) As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetDesktopWindow
Lib "user32" () As
LongPtr
#Else
Private Declare
Function GetDesktopWindow
Lib "user32" () As
Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetDeviceCaps
Lib "gdi32" (ByVal
hDC As LongPtr, ByVal
nIndex As Long)
As Long
#Else
Private Declare
Function GetDeviceCaps
Lib "gdi32" (ByVal hDC
As Long,
ByVal nIndex As
Long) As
Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetDriveType
Lib "kernel32" Alias _
"GetDriveTypeA"
(ByVal sDrive As
String) As LongPtr
#Else
Private Declare
Function GetDriveType Lib
"kernel32" Alias _
"GetDriveTypeA"
(ByVal sDrive As
String) As
Long
#End If
GetExitCodeProcess
#If VBA7 Then
Declare PtrSafe
Function GetExitCodeProcess
Lib "kernel32" (ByVal _
hProcess As
LongPtr, lpExitCode As
Long) As Long
#Else
Declare Function
GetExitCodeProcess Lib "kernel32" (ByVal _
hProcess As
Long, lpExitCode As
Long) As Long
#End If
#If VBA7 Then
Declare PtrSafe
Function GetForegroundWindow
Lib "user32.dll" () As
LongPtr
#Else
Declare Function
GetForegroundWindow Lib "user32.dll" ()
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetFrequency
Lib "kernel32" Alias "QueryPerformanceFrequency"
(cyFrequency As Currency)
As Long
#Else
Private Declare
Function GetFrequency Lib
"kernel32" Alias "QueryPerformanceFrequency" (cyFrequency
As Currency)
As Long
#End If
#If VBA7 Then
Declare PtrSafe
Function GetKeyState Lib
"USER32" (ByVal vKey As
Long) As
Integer
#Else
Declare Function
GetKeyState Lib "USER32" (ByVal
vKey As Long)
As Integer
#End If
#If VBA7 Then
Private Type
LASTINPUTINFO
cbSize As LongPtr
dwTime As LongPtr
End Type
Private Declare
PtrSafe Sub GetLastInputInfo
Lib "USER32" (ByRef
plii As LASTINPUTINFO)
#Else
Private Type
LASTINPUTINFO
cbSize As
Long
dwTime As
Long
End Type
Private Declare
Sub GetLastInputInfo Lib
"USER32" (ByRef plii As
LASTINPUTINFO)
#End If
Option Explicit
#If VBA7 Then
Private Declare
PtrSafe Function GetOpenFileName
Lib "comdlg32.dll" Alias _
"GetOpenFileNameA"
(pOpenfilename As OPENFILENAME)
As Long
Private Type
OPENFILENAME
lStructSize As
Long
hwndOwner As
LongPtr
hInstance As
LongPtr
lpstrFilter As
String
lpstrCustomFilter
As String
nMaxCustFilter
As Long
nFilterIndex
As Long
lpstrFile As
String
nMaxFile As
Long
lpstrFileTitle
As String
nMaxFileTitle
As Long
lpstrInitialDir
As String
lpstrTitle As
String
flags As
Long
nFileOffset As
Integer
nFileExtension
As Integer
lpstrDefExt As
String
lCustData As
LongPtr
lpfnHook As
LongPtr
lpTemplateName
As String
End Type
#Else
Private Declare
Function GetOpenFileName
Lib "comdlg32.dll" Alias _
"GetOpenFileNameA"
(pOpenfilename As OPENFILENAME)
As Long
Private Type
OPENFILENAME
lStructSize As
Long
hwndOwner As
Long
hInstance As
Long
lpstrFilter As
String
lpstrCustomFilter
As String
nMaxCustFilter
As Long
nFilterIndex
As Long
lpstrFile As
String
nMaxFile As
Long
lpstrFileTitle
As String
nMaxFileTitle
As Long
lpstrInitialDir
As String
lpstrTitle As
String
flags As
Long
nFileOffset As
Integer
nFileExtension
As Integer
lpstrDefExt As
String
lCustData As
Long
lpfnHook As
Long
lpTemplateName
As String
End Type
#End If
'/////////////////////////////////
'// End code GetOpenFileName //
'/////////////////////////////////
Private Function
GetMyFile(strTitle As String)
As String
Dim OpenFile As
OPENFILENAME
Dim lReturn
As Long
OpenFile.lpstrFilter = ""
OpenFile.nFilterIndex = 1
OpenFile.hwndOwner = 0
OpenFile.lpstrFile = String(257,
0)
#If VBA7 Then
OpenFile.nMaxFile = LenB(OpenFile.lpstrFile)
- 1
OpenFile.lStructSize = LenB(OpenFile)
#Else
OpenFile.nMaxFile = Len(OpenFile.lpstrFile)
- 1
OpenFile.lStructSize = Len(OpenFile)
#End If
OpenFile.lpstrFileTitle = OpenFile.lpstrFile
OpenFile.nMaxFileTitle = OpenFile.nMaxFile
OpenFile.lpstrInitialDir = "C:\"
OpenFile.lpstrTitle = strTitle
OpenFile.flags = 0
lReturn = GetOpenFileName(OpenFile)
If lReturn = 0
Then
GetMyFile = ""
Else
GetMyFile = Trim(Left(OpenFile.lpstrFile,
InStr(1, OpenFile.lpstrFile, vbNullChar) - 1))
End If
End Function
#If VBA7 Then
Private Declare
PtrSafe Function GetSystemMetrics
Lib "user32" (ByVal
nIndex As Long)
As Long
#Else
Private Declare
Function GetSystemMetrics
Lib "user32" (ByVal
nIndex As Long)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetTempPath
Lib "kernel32" _
Alias "GetTempPathA"
(ByVal nBufferLength As
LongPtr, _
ByVal
lpbuffer As String)
As Long
#Else
Private Declare
Function GetTempPath Lib
"kernel32" _
Alias "GetTempPathA" (ByVal nBufferLength
As Long, _
ByVal lpbuffer As
String) As
Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function getTickCount
Lib "kernel32" Alias "QueryPerformanceCounter"
(cyTickCount As Currency)
As Long
#Else
Private Declare
Function getTickCount Lib
"kernel32" Alias "QueryPerformanceCounter" (cyTickCount
As Currency)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function timeGetTime
Lib "winmm.dll" () As
Long
#Else
Private Declare
Function timeGetTime Lib
"winmm.dll" () As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetWindow
Lib "user32" _
(ByVal
hWnd As LongPtr, ByVal
wCmd As Long)
As LongPtr
#Else
Private Declare
Function GetWindow Lib
"user32" _
(ByVal hWnd As
Long, ByVal wCmd
As Long)
As Long
#End If
This is one of the few API functions that requires the Win64 compile
constant:
#If VBA7 Then
#If Win64 Then
Private
Declare PtrSafe Function
GetWindowLongPtr Lib "USER32" Alias "GetWindowLongPtrA"
(ByVal hWnd As LongPtr,
ByVal nIndex As
Long) As LongPtr
#Else
Private
Declare PtrSafe Function
GetWindowLongPtr Lib "USER32" Alias "GetWindowLongA"
(ByVal hWnd As LongPtr,
ByVal nIndex As Long)
As LongPtr
#End If
#Else
Private Declare
Function GetWindowLong
Lib "USER32" Alias "GetWindowLongA" (ByVal
hWnd As Long, ByVal
nIndex As Long)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetWindowsDirectory&
Lib "kernel32" Alias _
"GetWindowsDirectoryA"
(ByVal lpbuffer As
String, _
ByVal
nSize As LongPtr)
#Else
Private Declare
Function GetWindowsDirectory&
Lib "kernel32" Alias _
"GetWindowsDirectoryA"
(ByVal lpbuffer As
String, _
ByVal
nSize As Long)
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetWindowText
Lib "user32" Alias "GetWindowTextA" _
(ByVal
hWnd As LongPtr, ByVal
lpString As String, _
ByVal cch As LongPtr)
As Long
#Else
Private Declare
Function GetWindowText
Lib "user32" Alias "GetWindowTextA" _
(ByVal hWnd As
Long, ByVal lpString
As String, _
ByVal
cch As Long)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GetWindowTextLength
Lib "user32" Alias "GetWindowTextLengthA"
_
(ByVal
hWnd As LongPtr) As
Long
#Else
Private Declare
Function GetWindowTextLength
Lib "user32" Alias "GetWindowTextLengthA"
_
(ByVal hWnd As
Long) As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GlobalAlloc
Lib "kernel32" (ByVal
wFlags As Long,
ByVal dwBytes As
LongPtr) As LongPtr
#Else
Private Declare
Function GlobalAlloc Lib
"kernel32" (ByVal wFlags
As Long,
ByVal dwBytes As
Long) As
Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function GlobalLock
Lib "kernel32" (ByVal
hMem As LongPtr) As
LongPtr
#Else
Private Declare
Function GlobalLock Lib
"kernel32" (ByVal hMem
As Long) As
Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function InternetGetConnectedState
_
Lib
"wininet.dll" (lpdwFlags As LongPtr, _
ByVal dwReserved As
Long) As
Boolean
#Else
Private Declare
Function InternetGetConnectedState _
Lib
"wininet.dll" (lpdwFlags As
Long, _
ByVal dwReserved As
Long) As
Boolean
#End If
#If VBA7 Then
Private Declare
PtrSafe Function IsCharAlphaNumericA
Lib "user32" (ByVal
byChar As Byte)
As Long
#Else
Private Declare
Function IsCharAlphaNumericA
Lib "user32" (ByVal
byChar As Byte)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function lstrcpy
Lib "kernel32" (ByVal
lpString1 As Any, ByVal
lpString2 As Any) As
LongPtr
#Else
Private Declare
Function lstrcpy Lib
"kernel32" (ByVal lpString1
As Any, ByVal lpString2
As Any) As
Long
#End If
#If VBA7 Then
Private Declare PtrSafe
Sub mouse_event Lib
"user32" (ByVal dwFlags
As Long, ByVal
dx As Long, _
ByVal
dy As Long,
ByVal cButtons As
Long, _
ByVal
dwExtraInfo As LongPtr)
#Else
Private Declare
Sub mouse_event Lib
"user32" (ByVal dwFlags
As Long, ByVal
dx As Long, _
ByVal
dy As Long,
ByVal cButtons As
Long, _
ByVal
dwExtraInfo As Long)
#End If
Private Const MOUSEEVENTF_MOVE
= &H1
' mouse move
OleCreatePictureIndirect
#If VBA7 Then
Private Declare
PtrSafe Function OleCreatePictureIndirect
Lib "oleaut32.dll" (PicDesc
As PICTDESC, RefIID As
GUID, ByVal fPictureOwnsHandle
As LongPtr, IPic As
IPicture) As LongPtr
Private Type
PICTDESC
Size As
Long
Type
As Long
hPic As
LongPtr
hPal As
LongPtr
End Type
#Else
Private Declare
Function OleCreatePictureIndirect
Lib "oleaut32.dll" (PicDesc
As PICTDESC, RefIID As
GUID, ByVal fPictureOwnsHandle
As Long, IPic
As IPicture) As
Long
Private Type
PICTDESC
Size As
Long
Type
As Long
hPic As
Long
hPal As
Long
End Type
#End If
#If VBA7 Then
Private Declare
PtrSafe Function OleTranslateColor
Lib "oleaut32.dll" (ByVal
lOleColor As Long,
_
ByVal lHPalette As
Long, lColorRef As
Long) As
Long
#Else
Private Declare
Function OleTranslateColor
Lib "olepro32.dll" (ByVal
lOleColor As Long,
_
ByVal lHPalette As
Long, ByRef lColorRef
As Long)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function OpenClipboard
Lib "user32" (ByVal
hWnd As LongPtr) As
LongPtr
#Else
Private Declare
Function OpenClipboard
Lib "user32" (ByVal hWnd
As Long)
As Long
#End If
OpenProcess
#If VBA7 Then
Declare PtrSafe
Function OpenProcess Lib
"kernel32" (ByVal _
dwDesiredAccess
As Long,
ByVal bInheritHandle As
Long, ByVal _
dwProcessId As
Long) As LongPtr
#Else
Declare Function
OpenProcess Lib "kernel32" (ByVal _
dwDesiredAccess
As Long,
ByVal bInheritHandle As
Long, ByVal _
dwProcessId As
Long) As
Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function ReleaseDC
Lib "user32" (ByVal
hWnd As LongPtr, ByVal
hDC As LongPtr) As
Long
#Else
Private Declare
Function ReleaseDC Lib
"user32" (ByVal hWnd As
Long, ByVal hDC
As Long)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function SendMessageA
Lib "user32" (ByVal
hWnd As LongPtr, ByVal
wMsg As Long, _
ByVal
wParam As LongPtr, lParam
As Any) As LongPtr
#Else
Private Declare
Function SendMessageA Lib
"user32" (ByVal hWnd As
Long, ByVal wMsg
As Long, _
ByVal
wParam As Long,
lParam As Any) As
Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function SetActiveWindow
Lib "user32.dll" (ByVal
hWnd As LongPtr) As
LongPtr
#Else
Private Declare
Function SetActiveWindow
Lib "user32.dll" (ByVal
hWnd As Long)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function SetClipboardData
Lib "user32" (ByVal
wFormat As LongPtr, ByVal
hMem As LongPtr) As
LongPtr
#Else
Private Declare
Function SetClipboardData
Lib "user32" (ByVal
wFormat As Long,
ByVal hMem As
Long) As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function SetCurrentDirectoryA
Lib "kernel32" (ByVal
lpPathName As String)
As Long
#Else
Private Declare
Function SetCurrentDirectoryA
Lib "kernel32" (ByVal
lpPathName As String)
As Long
#End If
This is another one of the few API functions that require the Win64 compile
constant:
#If VBA7 Then
#If Win64 Then
Private
Declare PtrSafe Function
SetWindowLongPtr Lib "USER32" Alias "SetWindowLongPtrA"
(ByVal hWnd As LongPtr,
ByVal nIndex As
Long, ByVal dwNewLong
As LongPtr) As LongPtr
#Else
Private
Declare Function
SetWindowLongPtr Lib "USER32" Alias "SetWindowLongA"
(ByVal hWnd As LongPtr,
ByVal nIndex As Long,
ByVal dwNewLong As LongPtr)
As LongPtr
#End If
#Else
Private Declare
Function SetWindowLong
Lib "USER32" Alias "SetWindowLongA" (ByVal
hWnd As Long, ByVal
nIndex As Long,
ByVal dwNewLong As Long)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function SetWindowPos _
Lib
"user32" (ByVal hwnd As
LongPtr, ByVal hWndInsertAfter
As LongPtr, _
ByVal
X As Long,
ByVal Y As
Long, ByVal cx
As Long, _
ByVal
cy As Long,
ByVal wFlags As
Long) As
Long
#Else
Private Declare
Function SetWindowPos _
Lib
"user32" (ByVal hwnd As
Long, _
ByVal
hWndInsertAfter As Long,
_
ByVal
X As Long,
ByVal Y As
Long, _
ByVal
cx As Long, _
ByVal
cy As Long, _
ByVal
wFlags As Long)
As Long
#End If
#If VBA7 Then
Private Type
BROWSEINFO
hOwner As LongPtr
pidlRoot As
LongPtr
pszDisplayName As
String
lpszTitle As
String
ulFlags As
Long
lpfn As LongPtr
lParam As LongPtr
iImage As
Long
End Type
Private Declare
PtrSafe Function SHBrowseForFolder
Lib "shell32.dll" Alias "SHBrowseForFolderA"
_
(lpBrowseInfo As
BROWSEINFO) As LongPtr
#Else
Private Type
BROWSEINFO
hOwner As
Long
pidlRoot As
Long
pszDisplayName As
String
lpszTitle As
String
ulFlags As
Long
lpfn As
Long
lParam As
Long
iImage As
Long
End Type
Private Declare
Function SHBrowseForFolder
Lib "shell32.dll" Alias "SHBrowseForFolderA"
_
(lpBrowseInfo As
BROWSEINFO) As Long
#End If
Private Const BIF_RETURNONLYFSDIRS
= &H1
#If VBA7 Then
Private Declare
PtrSafe Function ShellExecute
Lib "shell32.dll" Alias "ShellExecuteA" (
_
ByVal
hWnd As LongPtr, ByVal
lpOperation As String,
ByVal lpFile As
String, _
ByVal
lpParameters As String,
ByVal lpDirectory As
String, ByVal nShowCmd
As Long)
As LongPtr
#Else
Private Declare
Function ShellExecute Lib
"shell32.dll" Alias "ShellExecuteA" ( _
ByVal
hWnd As Long,
ByVal lpOperation As
String, ByVal lpFile
As String, _
ByVal
lpParameters As String,
ByVal lpDirectory As
String, ByVal nShowCmd
As Long)
As Long
#End If
#If VBA7 Then
Type SHFILEOPSTRUCT
hWnd As LongPtr
wFunc As Long
pFrom As
String
pTo As
String
fFlags As
Integer
fAborted As
Boolean
hNameMaps As
Longptr
sProgress As
String
End Type
Declare PtrSafe
Function SHFileOperation Lib "shell32.dll"
Alias "SHFileOperationA" _
(lpFileOp As SHFILEOPSTRUCT)
As LongPtr
#Else
Type SHFILEOPSTRUCT
hWnd As
Long
wFunc As
Long
pFrom As
String
pTo As
String
fFlags As
Integer
fAborted As
Boolean
hNameMaps As
Long
sProgress As
String
End Type
Declare Function
SHFileOperation Lib "shell32.dll" Alias "SHFileOperationA"
_
(lpFileOp As SHFILEOPSTRUCT)
As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function SHGetPathFromIDList
Lib "shell32.dll" Alias "SHGetPathFromIDListA"
_
(ByVal
pidl As LongPtr, ByVal
pszPath As String)
As Boolean
#Else
Private Declare
Function SHGetPathFromIDList
Lib "shell32.dll" Alias "SHGetPathFromIDListA"
_
(ByVal pidl As
Long, ByVal pszPath
As String)
As Boolean
#End If
#If VBA7 Then
Private Declare
PtrSafe Function SHGetSpecialFolderLocation
Lib _
"shell32.dll"
(ByVal hwndOwner As
LongPtr, ByVal nFolder
As Long, _
pidl As ITEMIDLIST) As
LongPtr
Private Type
SHITEMID
cb As
LongPtr
abID As
Byte
End Type
#Else
Private Declare
Function SHGetSpecialFolderLocation Lib _
"shell32.dll"
(ByVal hwndOwner As
Long, ByVal nFolder
As Long, _
pidl As ITEMIDLIST) As
Long
Private Type
SHITEMID
cb As
Long
abID As
Byte
End Type
#End If
Private Type ITEMIDLIST
mkid As SHITEMID
End Type
#If VBA7 Then
Private Declare
PtrSafe Function timeGetTime
Lib "winmm.dll" () As
Long
#Else
Private Declare
Function timeGetTime Lib
"winmm.dll" () As Long
#End If
#If VBA7 Then
Private Declare
PtrSafe Function URLDownloadToFile
Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal
pCaller As LongPtr,
_
ByVal
szURL As String,
ByVal szFileName As
String, _
ByVal
dwReserved As LongPtr,
ByVal lpfnCB As
LongPtr) As
Long
#Else
Private Declare
Function URLDownloadToFile
Lib "urlmon" _
Alias "URLDownloadToFileA" (ByVal
pCaller As Long,
_
ByVal
szURL As String,
ByVal szFileName As
String, _
ByVal
dwReserved As Long,
ByVal lpfnCB As
Long) As
Long
#End If
Which Longs should become LongPtr?
It's actually pretty easy to determine what requires LongPtr and what
can stay as Long. The only things that require LongPtr are function arguments
or return values that represent addresses in memory. This is because a 64-bit
OS has a memory space that is too large to hold in a Long data type variable.
Arguments or return values that represent data will still be declared Long
even in 64-bit.
The SendMessage API is a good example because it uses both types:
32-bit:
Private Declare
Function SendMessageA Lib
"user32" (ByVal hWnd As
Long, ByVal wMsg
As Long, _
ByVal wParam As
Long, lParam As
Any) As Long
64 bit:
Private Declare
PtrSafe Function SendMessageA
Lib "user32" (ByVal
hWnd As LongPtr, ByVal
wMsg As Long, _
ByVal wParam As
LongPtr, lParam As
Any) As LongPtr
The first argument -hWnd- is a window handle, which is an address in
memory. The return value is a pointer to a function, which is also an address
in memory. Both of these must be declared LongPtr in 64-bit VBA. The argument
wMsg is used to pass data, so can be Long in both 32-bit and 64-bit.
How to determine what is a memory address and what is data? You just
have to read
the MSDN documentation for the API functions (the C++ version) and it
will tell you. Anything called a handle, pointer, brush or any other object
type will require a LongPtr in 64-bit. Anything that is strictly data can
stay as Long.
Conditional compiling
If your code needs to run on both 32 bit and 64 bit Excel, then another
thing to do is add conditional compilation to your VBA.
Microsoft devised two compile constants to handle this:
VBA7: True if you're using Office 2010, False for older versions
WIN64: True if your Office installation is 64 bit, false for 32 bit.
Since the 64 bit declarations also work on 32 bit Office 2010, all you
have to test for is VBA7:
#If VBA7 Then
Private Declare
PtrSafe Function GetDeviceCaps
Lib "gdi32" (ByVal
hDC As LongPtr, ByVal
nIndex As Long)
As Long
#Else
Private Declare
Function GetDeviceCaps
Lib "gdi32" (ByVal hDC
As Long,
ByVal nIndex As
Long) As
Long
#End If
And then in the routine where this function is put to use:
#If VBA7 Then
Dim hDC As
LongPtr
#Else
Dim hDC As
Long
#End If
Dim lDotsPerInch As
Long
'Get the user's DPI setting
lDotsPerInch = GetDeviceCaps(hDC, LOGPIXELSX)
Other API functions
Have a function declaration which is not on this list? I invite you to
send me your (working and tested!!!) declarations so I can add them here.
I also welcome comments and suggestions on improvements!
Sorry for the truncations into 3 messages
George
Comment by: Jan Karel Pieterse (8-8-2013 21:03:19) deeplink to this comment
Hi George,
Thanks!!
Comment by: Jan Karel Pieterse (8-8-2013 21:04:11) deeplink to this comment
Hi George,
The best way is to find womeone with 64 bit Excel to test this.
Comment by: Daniel Isoje (29-12-2013 20:33:10) deeplink to this comment
Your post makes it all easy for me now. Before now the 32/64bit issues have been troubling my mind as an access developer.
Many thanks.
Comment by: Erwin Kalvelagen (19-3-2014 16:54:16) deeplink to this comment
Just as a warning: I believe the file Win32API_PtrSafe.TXT contains some errors wrt Excel 64 bit. I got a few "Microsoft Excel has stopped working errors". Most are related to strings.
Here are some details:
http://social.msdn.microsoft.com/Forums/office/en-US/9ad49156-0d29-4c0c-ae30-8e7c11ccd8cf/win32apiptrsafetxt-better-version-available?forum=exceldev
Comment by: Thomas Dette (30-7-2014 10:44:41) deeplink to this comment
Hi,
do you have a "64bit translation" for following APIs
Declare Function SleepEx Lib "kernel32" (ByVal dwMilliseconds As Long, ByVal bAlertable As Long) As Long
Declare Function MoveFileEx Lib "kernel32" Alias "MoveFileExA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String, ByVal dwFlags As Long) As Long
Declare Function sndPlaySound Lib "winmm.dll" snd dPlaySoundA" ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
Declare Function WritePrivateProfileString& Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, _
ByVal lplFileName As String)
Declare Function GetPrivateProfileString& Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String)
Using ACCESS 2010 64bit.
Thanks for helping.
Thomas.
Comment by: Frank Barsnick (1-9-2014 13:37:24) deeplink to this comment
Hi,
do you have a "64bit translation" for following APIs for reading an writing INI-files:
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer
Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, lpKeyName As Any, lpString As Any, ByVal lplFileName As String) As Integer
Private Declare Function DeletePrivateProfileSection Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal Section As String, ByVal NoKey As Long, ByVal NoSetting As Long, ByVal FileName As String) As Long
Thx for your help,
Frank
Comment by: Jan Karel Pieterse (1-9-2014 14:29:45) deeplink to this comment
Hi Frank,
Sure:
Declare PtrSafe Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
Declare PtrSafe Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long
I was unable to find the Delete one though!
Comment by: Alexander (29-9-2014 12:32:47) deeplink to this comment
Error in declaration SHBrowseForFolder. To 64-bit returned type must be LongPtr:
Private Declare PtrSafe Function SHBrowseForFolder Lib "shell32.dll" Alias "SHBrowseForFolderA" _
(lpBrowseInfo As BROWSEINFO) As LongPtr
Comment by: Jan Karel Pieterse (29-9-2014 13:09:12) deeplink to this comment
Hi Alexander,
Thanks for pointing that out!
I have edited the page accordingly.
Comment by: LHEN (20-10-2014 10:20:12) deeplink to this comment
Hi,
do you have a "64bit translation" for following APIs?
Public Declare Function WSAGetLastError Lib "WSOCK32.DLL" () As Long
'Returns the socket error
Public Declare Function WSAStartup Lib "WSOCK32.DLL" _
(ByVal wVersionRequired As Long, lpWSADATA As WSADATA) As Long
'Initialize sockets
Public Declare Function WSACleanup Lib "WSOCK32.DLL" () As Long
'Clean up sockets
Public Declare Function gethostname Lib "WSOCK32.DLL" _
(ByVal szHost As String, ByVal dwHostLen As Long) As Long
'Get Host Name
Public Declare Function gethostbyname Lib "WSOCK32.DLL" _
(ByVal szHost As String) As Long
Many thanks :)
Comment by: Jan Karel Pieterse (20-10-2014 10:26:56) deeplink to this comment
Hi LHEN,
I'm sorry, but I don't.
Best to search MSDN for the functions and try to translate them yourself.
Comment by: Dave (14-11-2014 04:35:26) deeplink to this comment
Nice Work Jan!
Comment by: Nigel Heffernan (14-11-2014 16:41:48) deeplink to this comment
OpenProcess and GetExitCodeProcess would be useful: both are required for the widely-used ShellAndWait() function.
Note that they are quite tricky: while the handles and pointers are clearly LongPtr in the 64-bit environment, it's not clear whether the Process ID and the exit codes are Long or LongLong integers.
Comment by: Jan Karel Pieterse (17-11-2014 09:46:08) deeplink to this comment
Hi Nigel,
Added!
Comment by: Zak (19-11-2014 11:08:33) deeplink to this comment
Hi,
Hi to All,
Can anyone help me regarding my problem?
This is the scenario.
I have a .mdb file generated using Access 2010.
I tried to open the file using Access 2013.
After some modifications in the connections, I have a problem.
I have a browse button that when I click, resulted to this error.
Run-time Error '452'
Can't find DLL entry point 59 in msaccess.exe
When I debug, I think this portion have problem.
Declare PtrSafe Sub ms_accSplitPath Lib "msaccess.exe" Alias "#59" _
(ByVal strPath As String, ByVal strDrive As String, _
ByVal strDir As String, ByVal strFName As String, ByVal strExt As String)
*I just added the PtrSafe for 64-bit.
I will surely appreciate all your feedbacks.
Thank you very much.
Comment by: Dan (27-11-2014 13:18:44) deeplink to this comment
Hi,
I need to make my code available to 32-Bit & 64-Bit Excel users, with both VBA7 and earlier verisons.
Can I not just use the
#if VBA7
statement to replace all Long with LongPtr for VBA7 environments? Surely this will just evaluate to long in 32-bit and longlong in 64-bit?
I'm failing to see how this could be detrimental. Why should I be only converting certain Longs to LongPtr?
Any guidance is appreciated.
Comment by: Jan Karel Pieterse (27-11-2014 14:31:29) deeplink to this comment
Hi Dan,
To be honest, I'm not entirely sure what to answer here. My gut feeling says that the arguments you pass to a Win API need to be of the right type. I am not convinced LongPtr would be equally good as Long when the argument is supposed to be a Long. My gut feeling also whispers to me that this is the type of thing that lets vulnerabilities creep into software, but perhaps I'm paranoid :-) .
Comment by: Nigel Heffernan (21-1-2015 18:10:05) deeplink to this comment
Hi Jan -
Thanks for the code for OpenProcess and GetExitCodeProcess.
I notice that you're not using LongLong anywhere in these declarations: do you have examples of Win64 API functions that do require them?
This isn't a matter of idle curiosity: other VBA Gurus are peppering their API declarations with LongLong and I think that they are occasionally wrong - but I think they are safer doing that than taking the risk of receiving a LongLong resource identifier or parameter into a Long integer, and passing the truncated result into another API call. Windows might throw an exception that VBA can handle as an error; it might crash Excel; or it might truncate the value silently and perform some arcane API function on the wrong resource.
Also, there are environments where LongPtr is available, but LongLong isn't.
This means that GetWindowLong isn't the only API declaration that needs three separate segments of conditional compilation; take a look at this, and consider what it means if the only place I can put a breakpoint is
'lParam = 6432'
Public Sub TestEnv()
#If VBA7 And Win64 Then
' 64 bit Excel under 64-bit windows
' We can use LongPtr and LongLong
Dim hWnd As LongPtr
Dim lParam As LongLong
lParam = 6464
#ElseIf VBA7 Then
' 64 bit Excel in all environments
' We can use LongPtr
Dim hWnd As LongPtr
Dim lParam As Long
lParam = 6432
#Else
' 32 bit Excel
' Any length you like, as long as it's Long
Dim hWnd As Long
Dim lParam As Long
lParam = 32
#End If
End Sub
I think we've all underestimated the complexity of the task we face in upgrading VBA code to 64-bit.
Comment by: Nigel Heffernan (21-1-2015 19:41:16) deeplink to this comment
Dan,
You need to do some reading on Pointers, and why 'PtrSafe' matters. Google for 'Dangling Pointer' and see what you get.
What follows is my own understanding, in the language we use as VBA developers; and I am well aware that it contains oversimplifications that push it beyond mere errors and into the logical abyss that philosophers refer to as 'Not Even Wrong'.
A Pointer is the memory address of a resource - maybe the address of the Long integer you're using right now; maybe the address of an object which needs to be in memory when you need it, or a window handle; or, maybe, the address of a function that an API Timer has been told to call in sixty seconds' time.
When that address is incorrect, or when the resource at that address isn't what you expected, things can go badly wrong; so Microsoft have introduced new functions labelled 'Pointer-Safe', which use a special type of integer called 'LongPtr' for memory addresses; and a compiler that reads 'PtrSafe' and 'LongPtr' will create runtime code with new, improved, error-tolerant logic to manage these pointers and the resources in the memory addresses they point to.
You can still store addresses in a LongLong integer: a pointer is just a number. But the compiler won't do that new, improved pointer management on any old integer: you need to declare it as 'LongPtr'.
I do not know what will happen if you declare an everyday integer as a LongPtr, and use it in your code as (say) a loop counter.
My best guess is that things will run very slowly - every time the integer is changed, there will be a series of uneccessary checks to see if there's a memory address with a pointer already using 'your' number - and I would guess that an error-handler (or a complicated redirection and reallocation routine) will be called whenever your integer-declared-as-LngPtr is changed to a value that represents a pointer to memory that's already in use.
Let me know how your application works when you try that.
Comment by: John (19-3-2015 22:38:51) deeplink to this comment
Hello, I have a problem with system tray icon. Icon cannot show and after minimized nothing happened. Do you know how to update vba code to win7 64bit?
Best regards
Comment by: Jan Karel Pieterse (20-3-2015 13:42:45) deeplink to this comment
Hi John,
What code?
Comment by: Randy (28-4-2015 05:58:08) deeplink to this comment
How do you get VBA to recognize the VBA7 constant? I'm running Office 2010 64-bit Excel. I declared a DLL function as follows:
#IF VBA7 then
Declare PtrSafe Function ...
#ELSE
Declare Function ...
#END IF
The compiler flags the statement after the #ELSE as incorrect and won't compile.
Comment by: Jan Karel Pieterse (28-4-2015 08:39:36) deeplink to this comment
Hi Randy,
The VBA7 compile constant should be recognized "out of the box". When precisely do you get the compile error?
Comment by: Randy (28-4-2015 20:45:19) deeplink to this comment
Here's an example
#If VBA7 Then
Declare PtrSafe Function Foo Lib "Mylib" () As Double
#Else
Declare Function Foo lib "Mylib" () as Double
#End If
I can't move past the declaration following the #Else. A message box pops up saying "Compile error: The code in this project must be updated for use on 64-bit systems. Please review and update Declare statements and then mark them with the PtrSafe Attribute."
Comment by: Jan Karel Pieterse (29-4-2015 07:40:28) deeplink to this comment
Hi Randy,
You can igonre those messages as far as I know (though you should not be getting them). You can avoid these silly compile error messages during editing by turning them off in the Editor options:
Tools, Options, uncheck "Auto syntax check".
Comment by: wareko (9-5-2015 04:02:32) deeplink to this comment
Hi, I have a question.
In the above API functios list, there are two declarations for each function.
For example,
GetWindow has two declarations.
Public Declare Function GetWindow Lib "USER32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Public Declare PtrSafe Function GetWindow Lib "USER32" (ByVal hWnd As LongPtr, ByVal wCmd As LongPtr) As LongPtr
My question is,
Which constant VBA7 or WIn64 I should use?
For example of the two declarations below, which declaration is good?
I am confusing...
'Declaration using VBA7
#If VBA7 Then
Public Declare PtrSafe Function GetWindow Lib "USER32" (ByVal hWnd As LongPtr, ByVal wCmd As LongPtr) As LongPtr
#Else
Public Declare Function GetWindow Lib "USER32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
#End If
'Declaration using Win64
#If Win64 Then
Public Declare PtrSafe Function GetWindow Lib "USER32" (ByVal hWnd As LongPtr, ByVal wCmd As LongPtr) As LongPtr
#Else
Public Declare Function GetWindow Lib "USER32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
#End If
Comment by: Jan Karel Pieterse (9-5-2015 11:45:20) deeplink to this comment
Hi Wareko,
VBA7 suffices in almost all cases. In case there is an exception it is mentioned in the sample code above.
Comment by: wareko (9-5-2015 12:29:43) deeplink to this comment
Thank you for your quick reply!
Comment by: Frank (28-5-2015 14:11:31) deeplink to this comment
Hi,
I'm certainly out of my element here, and I hope you can help. I'm using Excel 2010, and I was trying to create a macro whereby a user would click a link, and it would pass the product number to a Windows Explorer search function. I found the code below online that opens the search dialogue box.
It worked to open the search dialogue window, but it wasn't quite what I was looking for, so I removed the code and module. However, the code is still there somewhere, because when I try to step through any other module, the search dialogue window pops back up, and I can't get rid of it.
I'm on a network, and when I undocked my computer and went home last night and worked, all was fine. But when I came back to work today and redocked the computer, the issue was back.
Can you give me an idea of what I've done and how to fix it, please? Thank you!
=====================================
Option Explicit
'API declaration for the windows "Search Results" dialog
Private Declare Function ShellSearch& Lib "shell32.dll" _
Alias "ShellExecuteA" (ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long)
Private Const SW_SHOWNORMAL = 1
Sub ShowWindowsSearchDialog_API()
' Specified drive to Search
Const szSDrive As String = "C:\"
ShellSearch 0, "find", szSDrive, "", "", SW_SHOWNORMAL
End Sub
Comment by: Jan Karel Pieterse (28-5-2015 14:57:31) deeplink to this comment
Hi Frank,
Probably the code is in a file that loads when you start Excel. You should be able to locate the code by looking at all open projects in the Project explorer of the VBA editor and doing a find on each of them?
Comment by: Frank (28-5-2015 15:35:52) deeplink to this comment
Hi Jan,
Thank you for getting back to me, and so quickly! Part of my conundrum is that there are NO files open. The only thing visible in the Project Explorer is the Personal.xlsb, and I've made sure that even that is empty (including Sheet1 and ThisWorkbook).
And why would this be happening when my computer is docked to the network, but when I undock it and take it home, everything is fine?
Thank you very much for considering my issue - it's VERY frustrating.
Frank
Comment by: Jan Karel Pieterse (28-5-2015 16:06:34) deeplink to this comment
Hi Frank,
Does it also do this when you open Excel in safe mode (press and hold control key during Excel's startup)?
Comment by: Frank (28-5-2015 22:12:56) deeplink to this comment
Hi again Jan,
I'm really at a loss for what happened, but I ended up restarting my computer this afternoon for an IT update, and when it booted back up, all was well with Excel. I had completely shut down my computer yesterday when I undocked, and I was glad it was ok when I got home. And I shut down again before coming back into work and redocking. And I was very surprised to see the issue had returned after redocking and booting back up. So I'm again surprised that it went away after restarting the computer this afternoon.
In the end, I'm glad things are back to normal, but I'd like to know what caused that.
Again, thank you very much for taking the time and interest in trying to help me resolve this issue.
Best regards,
Frank
Comment by: Alan Elston (23-6-2015 00:14:59) deeplink to this comment
Hi,
. I have only basic VBA Knowledge.
. I have a code that is working for me in 32 Bit Vista XL 2010
. The code does not work in an identical system but XL 2007
. Initially the problem appears to be these lines, which error in XL 2007 but not XL 2010
Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Declare PtrSafe Function CloseClipboard Lib "User32" () As Long
Declare PtrSafe Function OpenClipboard Lib "User32" (ByVal hwnd As Long) As Long
Declare PtrSafe Function EmptyClipboard Lib "User32" () As Long
Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
Declare PtrSafe Function SetClipboardData Lib "User32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
.
. Sorry I cannot give more detail but my knowledge of VBA is limited.
. Is there any obvious reason for my problem?
. Thanks
Alan
Comment by: Jan Karel Pieterse (23-6-2015 07:35:14) deeplink to this comment
Hi Alan,
The quick and dirty way to make this work on Excel 2007 is this:
#If VBA7 Then
Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Declare PtrSafe Function CloseClipboard Lib "User32" () As Long
Declare PtrSafe Function OpenClipboard Lib "User32" (ByVal hwnd As Long) As Long
Declare PtrSafe Function EmptyClipboard Lib "User32" () As Long
Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
Declare PtrSafe Function SetClipboardData Lib "User32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
#Else
Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Declare Function CloseClipboard Lib "User32" () As Long
Declare Function OpenClipboard Lib "User32" (ByVal hwnd As Long) As Long
Declare Function EmptyClipboard Lib "User32" () As Long
Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long
Declare Function SetClipboardData Lib "User32" (ByVal wFormat As Long, ByVal hMem As Long) As Long
#End If
I haven't tried whether these are correct for 64 bit Office however!
Comment by: Alan Elston (23-6-2015 12:52:48) deeplink to this comment
Hi.
. Many thanks Jan Karel Pieterse. With your Mod the code works for me now in both XL 2007 and XL 2010. I was googling similar things but was way out of my depth to apply them. Thanks for giving me the final full solution. I note that in XL 2007 the first Declare PtrSafe lines still come up Red, indicating error, but the code works , by virtue , I think of the # which somehow works so that that code is done prior to the compiling.
. I cannot check if the code works in 64 bit. But I highly expect it as the original author has the original code working in 64 bit:
http://www.excelforum.com/tips-and-tutorials/1089404-posting-an-html-table-in-a-thread.html
Comment by: Alan Elston (23-6-2015 12:57:22) deeplink to this comment
. FYI. Jan, I have posted your modified code version and referenced you.
http://www.excelforum.com/tips-and-tutorials/1089404-posting-an-html-table-in-a-thread-2.html
…..and
Comment by: Alan Elston (23-6-2015 12:58:11) deeplink to this comment
…..and here
http://www.excelforum.com/the-water-cooler/1068075-just-testing-img-cannot-do-it-in-test-forum-as-img-is-off-there-no-reply-needed-2.html#post4110298
Hope that is OK.
Alan.
Comment by: Alan Elston (23-6-2015 17:06:35) deeplink to this comment
Hi
. Very sorry to mess up your site with my many replies here.
. Hope you catch them all and can edit them before you include them in your site:
- I was keen to acknowledge your help..
. The administrator has deleted the Posts where I acknowledged your help
. Hopefully they are still acknowledged here
http://www.excelforum.com/tips-and-tutorials/1089404-posting-an-html-table-in-a-forum-thread.html
Comment by: Alan Elston (23-6-2015 17:07:11) deeplink to this comment
......and here:
http://www.excelforum.com/the-water-cooler/1068075-just-testing-img-cannot-do-it-in-test-forum-as-img-is-off-there-no-reply-needed-2.html#post4110298
. Sorry for any confusion. Thanks again for the help
. Alan
Comment by: Tawn (6-8-2015 20:10:14) deeplink to this comment
I've downloaded the Microsoft Office Code Compatibility inspector add-in. I have MC Office Pro Plus 2010. The directions for use say to add the Developer Tab. I don't see the tab at File>Options>Customize Ribbon>Popular Commands>Main Tab.
I found one MVP that states there is not a Developer Tab for Access 2010.
Does the program need to be installed differently?
I have to get IT out to change installation and it would be helpful to know what I need to be able to see the Developer tab.
Thank you,
Tawn
Comment by: Jan Karel Pieterse (7-8-2015 14:20:54) deeplink to this comment
Hi Tawn,
I have googled for a bit, but probably found the same information you already found.
AFAIK, all you need to do to check for 64 bit compliance is:
1. search your code for windows API declarations (those all start with the keyword "Declare", so they are easily found using a project-wide Find in the VBA editor)
2. Check whether or not you have used any external activeX controls in your project, because those may be unavailable in 64 bit (e.g. from the Common Controls library comclt.ocx). Mostly these should be shown in your VBA projects list of references.
Comment by: les (17-12-2015 19:19:49) deeplink to this comment
I have a 32 bit version of Excel but have a client that has a 64 bit version. Where do I put the code to use the 64 bit if needed
Comment by: Jan Karel Pieterse (18-12-2015 11:52:08) deeplink to this comment
Hi Les,
Does your code have any API calls (Declare statements)?
If not, chances are quite good that your file works on 64 bit without any changes.
Comment by: Vladimir Nazarov (9-2-2016 21:24:48) deeplink to this comment
Dear Mr. Jan Karel Pieterse,
Could you please help me which Long becomes PtrLong in the following Type code in VBA7? Many thanks in advance.
Private Type KBDLLHOOKSTRUCT
vkCode As Long
scanCode As Long
Flags As Long
time As Long
dwExtraInfo As Long
End Type
Comment by: Jan Karel Pieterse (10-2-2016 07:27:11) deeplink to this comment
Hi Vladimir,
Which API funtion are you using?
Comment by: Jan Karel Pieterse (10-2-2016 07:28:54) deeplink to this comment
Hi Vladimir,
I expect:
Private Type KBDLLHOOKSTRUCT
vkCode As Long
scanCode As Long
Flags As Long
time As Long
dwExtraInfo As LongPtr
End Type
Comment by: Vladimir Nazarov (10-2-2016 14:07:28) deeplink to this comment
Dear Mr. Jan Karl Pieterse,
I have just found a very interesting text document containing a lot of API declarations in VBA7 format however without an older version of VBA (295 pages of A4 format):
http://www.cadsharp.com/docs/Win32API_PtrSafe.txt
' ----------------------------------------------------------
'
'Win32API_PtrSafe.TXT -- Declare statements for
'Visual Basic for Applications and Microsoft Office 2010
Comment by: Jan Karel Pieterse (10-2-2016 14:28:49) deeplink to this comment
Hi Vladimir,
Isn't that the same file as the one I refer to near the top of this article? (links section)
Comment by: Vladimir Nazarov (10-2-2016 15:38:20) deeplink to this comment
Dear Mr. Jan Karel Pieterse,
Could you recommend any websites / links to convert old Excel VBA code into the code for VBA7 for the following API declarations and corresponding Type statements?
Can MAPI32.DLL used for 64-bit Excel or another DLL should be used instead and which one and how to change the code?
============================================================
Declare Function MAPILogon Lib "MAPI32.DLL" (ByVal UIParam&, ByVal User$, ByVal Password$, ByVal flags&, ByVal Reserved&, Session&) As Long
Declare Function MAPILogoff Lib "MAPI32.DLL" (ByVal Session&, ByVal UIParam&, ByVal flags&, ByVal Reserved&) As Long
Declare Function RAWMAPISendMail Lib "MAPI32.DLL" Alias "MAPISendMail" (ByVal Session&, ByVal UIParam&, Message As RAWMAPIMessage, ByVal flags&, ByVal Reserved&) As Long
Comment by: Jan Karel Pieterse (10-2-2016 16:02:28) deeplink to this comment
Hi Vladimir,
It seems my page is one of the few that actually addresses this I'm afraid. And if a function is not in the winAPI.txt, then all you can do is try to find its definition on MSDN and then figure out what are the longptr's
Comment by: Elek (16-2-2016 16:30:21) deeplink to this comment
Hi,
do you have a "64bit translation" for following APIs?
Public Function SetFileDateTime(FileName As String, _
FileDateTime As Double, WhichDateToChange As FileDateToProcess, _
Optional NoGMTConvert As Boolean = False) As Boolean
Thanks,
Elek
Comment by: Jan Karel Pieterse (16-2-2016 17:44:24) deeplink to this comment
Hi elek,
I don't think that function is an API function so no 64 bit translation is needed. API functions are always declared using the "Declare" keyword. Any functuion NOT using that keyword is NOT a Windows API function and does not need 64 bit changes.
Comment by: Vladimir Nazarov (25-2-2016 16:52:28) deeplink to this comment
Dear Mr. Jan K. Pieterse,
How to make the following function LowLevelKeyboardProc to work both in VBA6 and in VBA7?
In VBA6 it looks like follows and it works OK for Excel VBA6:
Public Function LowLevelKeyboardProc(ByVal nCode As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
In VBA7 it this function should looks like shown below:
Public Function LowLevelKeyboardProc(ByVal nCode As LongPtr, _
ByVal wParam As LongPtr, _
ByVal lParam As LongPtr) As LongPtr
If I remove both Long and LongPtr as shown below hoping to make it work with both Excel VBA6 and Excel VBA7, then Excel VBA6 crashes.
In VBA6 it looks like follows:
Public Function LowLevelKeyboardProc(ByVal nCode, _
ByVal wParam, _
ByVal lParam) As Long
Please note, that all API functions have been declared properly using #If VBA7 Then … #Else … #End If construction.
Thanks in advance for your help.
Vladimir Nazarov
Comment by: Jan Karel Pieterse (26-2-2016 14:26:37) deeplink to this comment
Hi Vladimir,
Can you please show the relevant declaration including the conditional compile stuff and the relevant pieces in your routine?
Comment by: Ramavatar (11-3-2016 07:47:17) deeplink to this comment
Thanks for information shared but i wanted to know which references lib to be selected in excel vba for handling windowsfind api. or similar kind.
Comment by: Jan Karel Pieterse (11-3-2016 10:26:35) deeplink to this comment
Hi Ramavatar,
Do you mean the FindWindow API? You can simply look it up in the table on this page. Windows API's do not need references, they only need the declare statement.
Comment by: Lorin Rowe (18-3-2016 21:30:22) deeplink to this comment
in 32 bit I called:
Set tdConnection = CreateObject("tdapiole80.tdconnection")
how should I reference "CreateObject" in a 64bit world? This is a 32 bit DLL.
Comment by: Jan Karel Pieterse (20-3-2016 19:03:52) deeplink to this comment
Hi Lorin,
I strongly suspect you simply cannot call a 32 bit dll form 64 bit VBA.
Comment by: Chris (20-3-2016 23:49:24) deeplink to this comment
Having some trouble with hooking a window proc in Access on 64-bit Office 2016, Windows 10. Still VBA 7, and I have 64-bit declarations, but every time I latch the window proc below, Access crashes after a few messages.
Thoughts?
#If VBA7 Then
Public Function sDragDropAttach(ByVal hwnd As LongPtr, _
ByVal Msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As LongPtr
#Else
Public Function sDragDropAttach(ByVal hwnd As Long, _
ByVal Msg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
#End If
Dim lngRet As Long, strTmp As String, intLen As Integer
Dim lngCount As Long, i As Long, strOut As String
Const cMAX_SIZE = 255
On Error Resume Next
If Msg = WM_DROPFILES Then
strTmp = String(255, vbNullChar)
lngCount = DragQueryFile(wParam, _
&HFFFFFFFF, _
StrPtr(strTmp), _
Len(strTmp))
For i = 0 To lngCount - 1
strTmp = String(cMAX_SIZE, vbNullChar)
intLen = DragQueryFile(wParam, _
i, _
StrPtr(strTmp), _
cMAX_SIZE)
strOut = strOut & left(StrConv(strTmp, vbUnicode), intLen) & "|"
Next i
Call DragFinish(wParam)
'I do my file processing here
Else
lngRet = CallWindowProc(ByVal lpPrevWndProc, _
ByVal hwnd, _
ByVal Msg, _
ByVal wParam, _
ByVal lParam)
End If
End Function
Comment by: Jan Karel Pieterse (21-3-2016 07:11:43) deeplink to this comment
Hi Chris,
I haven't used that function before, so I'm just making wild stabs here...
If you are creating hooks from API functions into your VBA code, are you properly releasing those hooks?
Are you sure there are no errors in your code, the on error resume next hides them.
Comment by: hilmi (2-6-2016 05:09:41) deeplink to this comment
i'm still not understand how to solve it. beginner user. should we copy all and save it in module?
Comment by: Jan Karel Pieterse (7-6-2016 13:43:34) deeplink to this comment
Hi Hilmi,
This is by far not something for a beginner user I'm afraid. I think it is best if you seek help from a more experienced VBA developer for this task.
Comment by: M Simms (23-6-2016 11:26:05) deeplink to this comment
This is from the Microsoft MSDN portal:
Existing 32-bit ActiveX controls, both third-party and Microsoft-supplied, are not compatible with the 64-bit version of Office 2010. For ActiveX controls and COM objects, there are three possible solutions:
If you have the source code, you can generate a 64-bit version yourself,
You can contact the vendor for an updated version,
You can search for an alternative solution.
Comment by: Jan Karel Pieterse (23-6-2016 12:27:30) deeplink to this comment
Hi M,
Yes correct. Another alternative is to build your own ActiveX-like control (if it is to be used on a userform) like this one:
www.jkp-ads.com/articles/treeview.asp
Comment by: M Simms (25-6-2016 15:14:15) deeplink to this comment
Can ALL "Long" references both parameters as well as return values be converted to "LongPtr"....or are there exceptions ?
This assumes Office 2011, 2013, and 2016.
Comment by: M Simms (25-6-2016 15:29:53) deeplink to this comment
Is the conversion below correct ?
I am worried about when to keep it Long vs. convert to LongPtr.
I take it that all handles and pointers should convert to LongPtr, correct ? Thanks for your help !!
--------------------------------------------------------
Private Declare Ptrsafe Function FtpCommand Lib "wininet.dll" Alias "FtpCommandA" _
(ByVal hConnect As LongPtr, _
ByVal fExpectResponse As Boolean, _
ByVal dwFlags As Long, _
ByVal lpszCommand As String, _
dwContext As LongPtr, phFtpCommand As LongPtr) As Boolean
' From the API documentation:
'BOOL FtpCommand(
' _In_ HINTERNET hConnect,
' _In_ BOOL fExpectResponse,
' _In_ DWORD dwFlags,
' _In_ LPCTSTR lpszCommand,
' _In_ DWORD_PTR dwContext,
' _Out_ HINTERNET *phFtpCommand
');
Comment by: Jan Karel Pieterse (27-6-2016 09:43:02) deeplink to this comment
Hi M Simmons,
No, you cannot simply replace all Longs woth LongPtrs, that will cause problems.
Have a look at the API viewer built by Dennis Walentin: http://www.rondebruin.nl/win/dennis/index.htm
Comment by: Jan Karel Pieterse (27-6-2016 09:45:33) deeplink to this comment
Hi M Simms,
The FtpCommand declaration looks correct to me. Best to test it thoroughly on both 32 and 64 bit Office systems.
Comment by: M Simms (28-6-2016 19:52:29) deeplink to this comment
Oh wow, that API Viewer looks terrific !!!
Does it also handle those "other" libraries like the FTP library ?
Comment by: gfmgin (22-8-2016 04:22:35) deeplink to this comment
I presume this would also helpful for me have less knowledge on MS Office compatibility in programming MS Access from 32bit to 64.
Thank U Very Much!
Comment by: Peter Straton (24-8-2016 00:13:38) deeplink to this comment
Shouldn't the last argument to the 64-bit declaration for GetWindow, wCmd, be a Long rather than a LongPtr since it is a numeric bit-code, consistent between both 32-bit and 64-bit Office, not a "pointer"?
Comment by: Jan Karel Pieterse (24-8-2016 09:18:14) deeplink to this comment
Hi Peter,
You're right and I've corrected the declaration. Thanks!
Comment by: Mick Webb (6-9-2016 18:16:37) deeplink to this comment
I assume that any wrappers where the result was Long but could now be either Long or LongPtr will have to have their return changed to Variant.
Comment by: Jan Karel Pieterse (7-9-2016 08:48:52) deeplink to this comment
Hi Mick,
I don't really know to be honest. Do you have any specific function in mind?
Comment by: Mick Webb (7-9-2016 13:18:22) deeplink to this comment
Hi,
For instance I have the FindWindow api in a wrapper to give me the handle of a MS UserForm.
Comment by: Jan Karel Pieterse (7-9-2016 16:47:46) deeplink to this comment
Hi Mick,
In such a case (e.g. when you're returning a value from a function), wrap the function header in a conditional compilation statement:
#IF VBA7 Then
Function ReturnSomeValue() As LongPtr
#Else
Function ReturnSomeValue() As Long
#End If
'Code here which either assigns a Long or a LongPtr:
ReturnSomeValue = FindWindow(...)
End Function
Comment by: Mick Webb (9-9-2016 18:22:47) deeplink to this comment
Simples - thank you
Mick
Comment by: Marcos Ferreira (10-10-2016 19:20:49) deeplink to this comment
Esta línea de da error en vba power point 64 bits
Private Declare Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Cómo debería corregir para usar el comando sleep en Power Point?
Comment by: Jan Karel Pieterse (11-10-2016 07:05:54) deeplink to this comment
Buenos dias Marcos,
Yo no hablo Espanol, pero:
Private PtrSafe Declare Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Comment by: atr (4-11-2016 08:10:18) deeplink to this comment
Hello.
I have a question.
Why do you use the "LongPtr" in "ByVal nBufferLength As longptr"?
In the "Long" is it bad?
Declare PtrSafe Function GetTempPath Lib "kernel32" _
Alias "GetTempPathA" (ByVal nBufferLength As longptr, _
ByVal lpbuffer As String) As Long
Comment by: Jan Karel Pieterse (14-11-2016 16:32:30) deeplink to this comment
Hi atr,
I must admit I don't know!
Comment by: Ramakrishnan S (29-11-2016 21:04:15) deeplink to this comment
I have a 64 bit machine & have my VBscript (.vbs) that is for mouse automation and mouse click events.
I am using sendkeys to get a specific cursor position, but unable to click at that location.
Let me know how to use the API calls on 64 bit?
Thanks
Ram.S
Comment by: Jan Karel Pieterse (30-11-2016 13:42:48) deeplink to this comment
Hi Ram,
You haven't mentioned which API functions you are using?
Comment by: Alan Elston (30-11-2016 16:09:05) deeplink to this comment
Hi Jan Karel Pieterse
Is it possible to get a URL Link to a particular Comment placed here?
I ask as I find it useful to referrence some of your answers here
Thanks
Alan
Comment by: Jan Karel Pieterse (30-11-2016 18:10:43) deeplink to this comment
Hi Alan,
That is actually a great idea! It will take me some time though, too much things going on right now.
Comment by: Alan Elston (30-11-2016 18:21:30) deeplink to this comment
Thanks ! :)
Alan
Comment by: Brett Bourg (30-11-2016 18:22:45) deeplink to this comment
Thank you for this page! It keeps helping me!
Comment by: Ram S (30-11-2016 19:54:00) deeplink to this comment
Hi Jan Karel,
Greetings!. Thanks for asking the question.
As of now i just have the Win32 APIs. Am researching to see if there are mouse APIs related to getCursorPos and setCursorPos and click at that position om Win 64.
Thanks
Ram.S
Comment by: Alan Elston (1-12-2016 15:08:21) deeplink to this comment
The new Comment direct URL links are working great, thanks again
Alan
Comment by: Jan Karel Pieterse (6-12-2016 10:09:12) deeplink to this comment
Hi Alan,
Please post your current declarations.
Comment by: loquat (29-12-2016 13:48:46) deeplink to this comment
how to use CallWindowProc in Win6 x64 office 32?
Comment by: Jan Karel Pieterse (30-12-2016 15:06:48) deeplink to this comment
Hi loquat,
I suggest you to do a google search for that API adding VBA to the search words.
Comment by: Richard Bates (1-3-2017 09:24:42) deeplink to this comment
'****************** N.B. I had to change the PtrSafe ReportEvent as it doesn't work at all ******************
Public Declare PtrSafe Function ReportEvent Lib "advapi32.dll" Alias "ReportEventA" (ByVal hEventLog As LongPtr, _
ByVal wType As Integer, ByVal wCategory As Integer, ByVal dwEventID As Long, ByVal lpUserSid As Any, _
ByVal wNumStrings As Integer, ByVal dwDataSize As Long, plpStrings As LongPtr, lpRawData As Any) As Long
'Public Declare PtrSafe Function ReportEvent Lib "advapi32.dll" Alias "ReportEventA" (ByVal hEventLog As LongPtr, _
ByVal wType As Long, ByVal wCategory As Long, ByVal dwEventID As Long, lpUserSid As Any, _
ByVal wNumStrings As Long, ByVal dwDataSize As Long, ByVal lpStrings As LongPtr, lpRawData As Any) As Long
'******************* N.B. This old code will work but it isn't PtrSafe **************************************
'Declare Function ReportEvent Lib "advapi32.dll" Alias "ReportEventA" (ByVal hEventLog As Long, _
ByVal wType As Integer, ByVal wCategory As Integer, ByVal dwEventID As Long, ByVal lpUserSid As Any, _
ByVal wNumStrings As Integer, ByVal dwDataSize As Long, plpStrings As Long, lpRawData As Any) As Boolean
'************************************************************************************************************
Comment by: Jan Karel Pieterse (1-3-2017 10:04:22) deeplink to this comment
Hi Richard,
Thanks for those!
Comment by: Bill (2-3-2017 20:15:29) deeplink to this comment
I'm having a problem with code to hide access behind forms. I'm in Access 2013 on Windows 7 64-bit. The code seems to work for others in different forums, but mine can't fine the function apiShowWindow even though I changed to ptrsafe. It compiles, so the syntax is right, but burps at execution. You clearly understand this stuff, but I'm out of my area of expertise - do I need to add some reference in the VBA window? Thanks in advance for any help/ideas you can share.
Option Compare Database
Option Explicit
Global Const SW_HIDE = 0
Global Const SW_SHOWNORMAL = 1
Global Const SW_SHOWMINIMIZED = 2
Global Const SW_SHOWMAXIMIZED = 3
Private Declare PtrSafe Function apiShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Function fSetAccessWindow(nCmdShow As Long)
Dim loX As Long
Dim loForm As Form
On Error Resume Next
Set loForm = Screen.ActiveForm
If Err <> 0 Then
loX = apiShowWindow(hWndAccessApp, nCmdShow)
Err.Clear
End If
If nCmdShow = SW_SHOWMINIMIZED And loForm.Modal = True Then
MsgBox "Cannot minimize Access with " _
& (loForm.Caption + " ") _
& "form on screen"
ElseIf nCmdShow = SW_HIDE And loForm.PopUp <> True Then
MsgBox "Cannot hide Access with " _
& (loForm.Caption + " ") _
& "form on screen"
Else
loX = apiShowWindow(hWndAccessApp, nCmdShow)
End If
fSetAccessWindow = (loX <> 0)
End Function
Comment by: Jan Karel Pieterse (3-3-2017 11:17:51) deeplink to this comment
Hi Bill,
Try whether this declaration works:
Private Declare PtrSafe Function apiShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Comment by: jay (16-3-2017 23:09:11) deeplink to this comment
Just noticed, That in the List SendMessage wParam is LonpPtr.
Luckly I read "Which Longs should become LongPtr?"
and noticed this error.
Great site thanks and thanks to microsoft for all the new work.
Comment by: Charltsing (31-5-2017 17:57:47) deeplink to this comment
I developed a free tool for automatic conversion of windows api in vbe. (office,autocad,etc)
http://www.cnblogs.com/Charltsing/p/SmartIndenter64.html
this vbe addins support windows API convert (Declare <--> PtrSafe),the number of supported api functions is about 1550.
thank you for your test!
Charltsing@gmail.com
Comment by: Luis Cardenas (3-7-2017 02:51:30) deeplink to this comment
I'm having a problem with code to get a ciphered string from a C++ .dll I'm in Excel 2016 on Windows 10 64-bit. The code seems to work for strings no longer than 16 characters, because VB receives the result string as a LongPointer. Thanks in advance for any help/ideas you can share:
Option Explicit
Private Declare PtrSafe Function EncryptDecrypt Lib "F:\XLS\SegCrypt64.dll" (ByVal fEncrypt As Boolean, ByVal lpszInBuffer As String, ByRef lpszOutBuffer As LongPtr, ByRef dwOutBufferLen As Long) As Boolean
Function EncryptXLS(ByVal fEncrypt As Boolean, ByVal lpszInBuffer As String, ByRef lpszOutBuffer As LongPtr, ByRef dwOutBufferLen As Long) As Boolean
EncryptXLS = EncryptDecrypt(fEncrypt, lpszInBuffer, lpszOutBuffer, dwOutBufferLen)
End Function
Sub TestDll()
Dim Result As Variant ' Result
Dim StrIn As String 'String to Cipher
Dim strOut As LongPtr 'Ciphered String
Dim lOut As Long 'Lenght of StrCr
StrIn = "1234567890123456"
lOut = Len(StrIn)
strOut = StrPtr(String(lOut, " "))
Result = EncryptXLS(1, StrIn, strOut, lOut)
Result = Trim(CStr(strOut))
MsgBox (Hex(Result))
End Sub
Comment by: Jan Karel Pieterse (3-7-2017 10:32:30) deeplink to this comment
Hi Luis,
This is a problem related to how C++ handles strings and how VBA handles strings and how to ensure you get the information accross between them. I googled a bit and found this article on stacj exchange. Hope it helps:
https://stackoverflow.com/questions/39404028/passing-strings-from-vba-to-c-dll
Comment by: J. W. Raper (27-9-2017 23:40:05) deeplink to this comment
I am a novice trying to learn Excel VBA; you have personally helped me before and this web page continues that help. Above is the statement WIN64: True if your Office installation is 64 bit, false for 32 bit. I am confused because everywhere I look the compiler constant Win64 has little or nothing to do with the active office version, it simply indicates whether or not the office installation platform environment is 64-bit compatible. It would assist me if an Excel VBA professional would help me understand. Thank you in advance for your assistance.
Comment by: Jan Karel Pieterse (28-9-2017 07:36:02) deeplink to this comment
Hi JW,
I agree the WIN64 compile constant is confusing, it should have read OFF64 if you ask me. This little routine returns TRUE *only* if your Office innstallation is 64 bit:
Function AmI64()
#If Win64 Then
AmI64 = True
#End If
End Function
Comment by: Chris B (19-10-2017 17:20:54) deeplink to this comment
Thanks for the excellent documentation.
In your example for GetOpenFileName you have
#If VBA7 Then
...
Public Type OPENFILENAME
...
lCustData As Long
But the Microsoft documentation in file "Win32API_PtrSafe.TXT" has
Type OPENFILENAME
lCustData As LongPtr
Comment by: Jan Karel Pieterse (19-10-2017 17:44:09) deeplink to this comment
Hi Chris,
Thanks!
Well spotted and I have corrected the error now.
Comment by: Martin L (2-11-2017 06:18:28) deeplink to this comment
Working and tested function that could be added:
#If VBA7 Then
Public Declare PtrSafe Function DrawMenuBar Lib "user32" (ByVal hWnd As LongPtr) As Long
#Else
Public Declare Function DrawMenuBar Lib "user32" (ByVal hWnd As Long) As Long
#End If
Comment by: Jan Karel Pieterse (2-11-2017 10:33:06) deeplink to this comment
Thank you Martin, I have added it to the list.
Comment by: Manuel (19-12-2017 12:29:05) deeplink to this comment
sConnect = "ODBC;UID=ADM124;PWD=ADM124;DATABASE="
If Base_Abierta = False Then
Set GdbCurrentDB = OpenDatabase("adm124", False, False, sConnect)
Error: Run-time error '429'
ActiveX component can't créate object.
How to solve this problem or error?
atte.
Manuel Araya Peña
Comment by: Jan Karel Pieterse (19-12-2017 13:01:25) deeplink to this comment
Hi Araya,
In what application are you programming? MSAccess?
Comment by: Manuel (19-12-2017 13:04:39) deeplink to this comment
No, with ODBD connection to Oracle.
atte.
Map
Comment by: Jan Karel Pieterse (19-12-2017 14:06:23) deeplink to this comment
Hi Manuel,
I suggest you ask your question at www.eileenslounge.com
Comment by: Roy (26-12-2017 08:39:58) deeplink to this comment
Hi, i cant seem to fix my Occupancy calculator. it works fine on office 2010, but its not working on office 2013. i already declared it safe but cant make it work. Appreciate your help.
below is the VBA code under module 1. let me know if you need the actual file that im having trouble with.
------------------------------------
Option Explicit
#If Win64 Then
Private Declare PtrSafe Function Erlcf Lib "erl32.dll" Alias "_Erlcf@16" _
(ByRef hours As Double, ByRef hold As Double, ByRef fract As Double, slsec As Double) As Double
#Else
Private Declare Function Erlcf Lib "erl32.dll" Alias "_Erlcf@16" _
(ByRef hours As Double, ByRef hold As Double, ByRef fract As Double, slsec As Double) As Double
#End If
Comment by: Jan Karel Pieterse (27-12-2017 11:27:42) deeplink to this comment
Hi Roy,
Are you using 64 bit Office?
Is this dll a third-party dll by any chance? I cannot find any reference to it when I Google for it. If so, get hold of its maker, ask if there is a 64 bit version.
Comment by: Roy (27-12-2017 16:10:18) deeplink to this comment
Hi there!
Thanks for your reply.
Yes it is 64bit Ms Excel. And yes, its a third party Dll file.
Comment by: Jan Karel Pieterse (28-12-2017 12:21:16) deeplink to this comment
Hi Roy,
In that case you will need to find a 64 bit version of that dll. 32 bit dll's cannot be accessed by a 64 bit Office installation.
ALternatively, uninstall 64 bit Office and install the 32 bit version (the dafault).
Comment by: Roy (28-12-2017 14:16:33) deeplink to this comment
Thanks for your response. I appreciate it.
Comment by: Andrija Vrcan (8-1-2018 20:50:28) deeplink to this comment
Which way i can open folder using Shell API in 64 bit win,similar to:
Shell "C:\WINDOWS\EXPLORER.EXE " & FolderPath, vbNormalNoFocus
Thank you in advance.
Comment by: Jan Karel Pieterse (9-1-2018 08:09:15) deeplink to this comment
Hi Andrija,
No need for a Windows API, there is a built-in method for it:
Application.FileDialog:
https://msdn.microsoft.com/en-us/vba/excel-vba/articles/application-filedialog-property-excel
Comment by: Andrija Vrcan (9-1-2018 10:04:31) deeplink to this comment
Thank you Jan, but I don't need 'select' folder to be display, but only display specified folder. Cheers
Comment by: Jan Karel Pieterse (9-1-2018 10:53:17) deeplink to this comment
Hi Andrija,
Apologies, I misunderstood!
What is wrong with the Shell method you already showed?
Comment by: Andrija Vrcan (9-1-2018 11:05:53) deeplink to this comment
Shell "C:\WINDOWS\EXPLORER.EXE " & FolderPath, vbNormalNoFocus
works only in 32 bit win.
Comment by: Jan Karel Pieterse (9-1-2018 12:50:47) deeplink to this comment
Hi Andrijja,
The code works just fine on my 64 bit Excel 2010.
Comment by: Andrija Vrcan (10-1-2018 09:38:39) deeplink to this comment
Thank you Jan! The code did not work for my mistake (I accidentally commented part of the previous code).
Comment by: Chuck Minarik (19-1-2018 13:20:33) deeplink to this comment
Thanks! This is just what I needed after converting from Office 32 to Office 64.
Comment by: Martin L (7-2-2018 23:05:38) deeplink to this comment
I've seen the function SetWindowPos a lot in some forum posts that don't always use the appropriate declaration method,so I thought it would be good to add it here. I've made the adjustment myself and and tested the version below on my computer.
#If VBA7 Then
Private Declare PtrSafe Function SetWindowPos Lib "user32" ( _
ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
#Else
Private Declare Function SetWindowPos Lib "user32" ( _
ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long
#End If
Comment by: Jan Karel Pieterse (8-2-2018 06:49:41) deeplink to this comment
Hi Martin,
Thanks, I've added it to the list!
Comment by: Lorne (3-3-2018 14:14:55) deeplink to this comment
Thanks for an valuable reference resource.
Why is the SendMessage function referred to by the alias of SEndMessageA? Also, the same example declaration at he foot of this page declares the wParam as Long instead of LongPtr. The Declaration returns LongPtr but the MS Win32API_PtrSafe.Txt states it is a Long. The same text file states that the GetClassName declaration for nMaxCount should be a Long, Not LongPtr.
Comment by: Jan Karel Pieterse (5-3-2018 10:24:24) deeplink to this comment
Hi Lorne,
Good catch, I have updated the page to match the declaration in the txt file.
Comment by: Martin L (22-3-2018 06:08:48) deeplink to this comment
I'm afraid that Lorne's comment was not completely right regarding SendMessage. I double checked in Win32API_PtrSafe.Txt and the return value for SendMessage actually requires LongPtr.
However, the comment was right regarding wParam which means that the following sentence: "The arguments wMsg and wParam are used to pass data, so they can be Long in both 32-bit and 64-bit."
should exclude the mention of wParam.
Comment by: Jan Karel Pieterse (22-3-2018 08:12:55) deeplink to this comment
Hi Martin,
I have changed the declaration, thanks!
Comment by: Vishal kirve (9-4-2018 13:08:09) deeplink to this comment
I want click on open button of notification bar of ie11 using vba code
Comment by: Jan Karel Pieterse (9-4-2018 16:36:39) deeplink to this comment
Hi Vishal,
If you know the URL of the download, perhaps you can use the URLDownloadTofile function?
Comment by: Arjun (1-6-2018 20:33:40) deeplink to this comment
Hi All,
i am missing something here
can anyone please edit the below 32 bit code for 64 bit excel
Option Explicit
Private Declare PtrSafe Sub mouse_event Lib "user32" (ByVal dwFlags As LongPtr, _
ByVal dx As Long, _
ByVal dy As Long, _
ByVal cButtons As Long, _
ByVal dwExtraInfo As Long)
Private Const MOUSEEVENTF_MOVE = &H1 ' mouse move
Private Const MOUSEEVENTF_LEFTDOWN = &H2 ' left button down
Private Const MOUSEEVENTF_LEFTUP = &H4 ' left button up
Private Const MOUSEEVENTF_RIGHTDOWN = &H8 ' right button down
Private Const MOUSEEVENTF_RIGHTUP = &H10 ' right button up
Private Const MOUSEEVENTF_MIDDLEDOWN = &H20 ' middle button down
Private Const MOUSEEVENTF_MIDDLEUP = &H40 ' middle button up
Private Const MOUSEEVENTF_WHEEL = &H800 ' wheel button rolled
Private Const MOUSEEVENTF_ABSOLUTE = &H8000 ' absolute move
Private Type POINTAPI
X As Long
Y As Long
End Type
Sub Click()
Dim pt As POINTAPI
Dim X As Long
Dim Y As Long
'(0,0) = top left
'(65535,65535) = bottom right
X = 29000 / 2
Y = 29000 / 2
LeftClick X, Y
End Sub
Sub LeftClick(X As Long, Y As Long)
'Move mouse
mouse_event MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_MOVE, X, Y, 0, 0
'Press left click
mouse_event MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
'Release left click
mouse_event MOUSEEVENTF_ABSOLUTE + MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
End Sub
Comment by: Jan Karel Pieterse (8-6-2018 19:40:30) deeplink to this comment
Hi Arjun,
I have added it to the list.
Comment by: Jan Karel Pieterse (3-7-2018 14:34:40) deeplink to this comment
Hi Giancarlo,
Thanks. But the txt file which I refer to at the start of this article says:
' Provided for reference only. Please use the LongPtr versions instead.
Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As Long
Comment by: Jamie (22-8-2018 16:12:40) deeplink to this comment
This is a great page! The declaration for GetWindowLong has two errors as it's shown as GetWindowLongPtr in two places. Here are a few more:
Public Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As LongPtr) As Long
Public Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpFn As LongPtr, ByVal hmod As LongPtr, ByVal dwThreadId As Long) As LongPtr
Public Declare PtrSafe Function CallNextHookEx Lib "user32" (ByVal hHook As LongPtr, ByVal nCode As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Public Declare PtrSafe Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As LongPtr
Public Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long
Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" (ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long, ByVal wMsg As Long, ByVal wParam As LongPtr, ByVal lParam As LongPtr) As LongPtr
Comment by: Jan Karel Pieterse (23-8-2018 14:50:29) deeplink to this comment
Hi Jamie,
Thanks. What you posted, do you think those are the correct declarations?
Comment by: 123hemanth.singh@gmail.com (14-9-2018 22:56:34) deeplink to this comment
Public Declare PtrSafe Function Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As LongPtr)
Not able to run this module.
Comment by: Jan Karel Pieterse (17-9-2018 10:40:21) deeplink to this comment
Hi Hemanth (?),
When do you get this error?
Comment by: Tony Matyas (23-10-2018 13:25:19) deeplink to this comment
Just a hint to avoid possible confusion after corrected code line: In the section "Which Longs should become LongPtr?" (after the declaration list block)
you corrected the SendMessageA argument's wParam type to LongPtr due to comments, but left the 3rd line in the following paragraph unchanged:
"The arguments wMsg and wParam (!) are used to pass data, so they can be Long in both (!) 32-bit and 64-bit."
Comment by: Jan Karel Pieterse (23-10-2018 17:18:30) deeplink to this comment
Hi Tony,
Corrected, thanks!
Comment by: Tony Matyas (23-10-2018 19:42:50) deeplink to this comment
ad) 1. GetWindowLong: Suppose the last #Else statement (AFTER WIN64/Win32 differentiation), i.e. referring to >VBA6< should be
Private Declare Function GetWindowLong Lib "USER32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
as IMO the GetWindowLongPtr replacement has been introduced later for Office 2010 and higher.
2. Similarly the last SetWindowLong declaration referring to elder Office Versions:
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Comment by: Jan Karel Pieterse (24-10-2018 09:42:21) deeplink to this comment
Hi Tony,
Corrected, thanks!
Comment by: Joe (29-10-2018 07:13:00) deeplink to this comment
Thanks to the information on this page, I've had some success in getting a personal application working in a mix of 32/64 worlds. The Windows API calls are all working...
I'm still stuck though: I have a third party 32bit DLL which just contain math and file functions.
On my Win7(x64) with Excel 2010 (32bit) it all works as it should. On a Win10(x64) with Excel 2016 (64bit) even using Public Declare PtrSafe... I get cannot find entry point, or sometimes a DLL not found error!
#If VBA7 Then
Private Declare PtrSafe Function LearningRate Lib "crunch.dll" (ByVal nIndex As Long, ByVal nWeight As Long, ByVal nFocus as Long) As Double
#Else
Private Declare Function LearningRate Lib "crunch.dll" (ByVal nIndex As Long, ByVal nWeight As Long, ByVal nFocus as Long) As Double
#End If
I have copies of the .dll file in both C:\Windows\System32 and C:\Windows\SysWOW64 although I'm not sure if the file needs to be in both locations? (My understanding is that System32 is (confusingly) for the 64bit DLLs and SysWOW64 is where the 32bit DLLs are kept?)
Can I call the functions from a "simple" 32bit DLL from 64bit VBA?
Any help would really be appreciated.
Joe.
Comment by: Jan Karel Pieterse (29-10-2018 11:10:27) deeplink to this comment
Hi Joe,
In theory you cannot call 32 bit dll's from 64 bit VBA. But I seem to recall there is a convoluted win API work-around for it. Unfortunately I was not able to locate the demo file I thought I had on my system somewhere :-(
Comment by: A K (9-11-2018 03:17:12) deeplink to this comment
Thank you for the great compilation. However, please note that most of the 64 bit declarations in the table are incorrect. Most of the declarations only need PtrSafe added to them. Only when actual pointers are being passed as an argument, they will need to be converted from Long to LongPtr or other pointer type. Otherwise, ByRef Long types (eventhough they are defined as pointers in the function documentation) still need to be declared as Long, not LongPtr. Also, Long returned values remain Long, and should not be converted to LongPtr. If you have access to 64 bit Office, please test these declarations and update accordingly, since apparently they have not been tested. I have tested the above information in this comment and they are correct.
Comment by: Jan Karel Pieterse (9-11-2018 11:30:00) deeplink to this comment
Hi A K,
Most of these have been tested. Many of them come directly from the mentioned documentation by Microsoft.
I'm afraid I must disagree with your comment that most of them are wrong, I think they are correct. If any of these actually fail on 64 bit Office I'd like to know.
Comment by: Daniel (29-4-2019 20:11:00) deeplink to this comment
Your link to 'Visual Basic Win32 API Declarations' no longer works
Comment by: Jan Karel Pieterse (30-4-2019 09:08:00) deeplink to this comment
Hi Daniel,
Thanks for letting me know, I have replaced the link to point to an alternative source.
Comment by: Ryan (6-6-2019 19:37:00) deeplink to this comment
Hello,
I have a situation where users have a 64 bit machine, and they have office 365 64 bit installed for excel.
The following code is what i changed to based on the great walk through above...my question to you is, do you see any issues with the code not working on a 64 x 64 computer?
#If VBA7 Then
'Declare a function to get the data within the INI file
Public Declare PtrSafe Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As LongPtr, ByVal lpFileName As String) As LongPtr
#Else
'Declare a function to get the data within the INI file
Public Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
#End If
Comment by: Jan Karel Pieterse (7-6-2019 10:27:00) deeplink to this comment
Hi Ryan,
Accoring to the Win32API_PtrSafe.TXT file this is the correct declaration for 64 bit (the part in the True part of your #If statement):
Declare PtrSafe Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
Comment by: Marek (11-6-2019 13:59:00) deeplink to this comment
Hello,
I have also used the following code:
#If VBA7 Then
'Declare a function to get the data within the INI file
Public Declare PtrSafe Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As LongPtr, ByVal lpFileName As String) As LongPtr
#Else
'Declare a function to get the data within the INI file
Public Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
#End If
However it still shows an error in the Else clause (highlights in red and won't work). Any idea why?
thanks!
Comment by: Jan Karel Pieterse (11-6-2019 15:27:00) deeplink to this comment
Hi Marek,
You can simply ignore the fact that part of the declaration becomes red, as long as t is the part that is irrelevant to the bit-ness of your Excel. So if the Else part is red, but you are using 64 bit Excel, there is no problem with the Else part of the API declaration as it is ignored by the compiler.
Comment by: Jayan (19-6-2019 08:05:00) deeplink to this comment
Hello,
I'm trying to make a moving bubble chart.
I have a 64 bit machine with office 365 64 bit installed and using VBA7.1version.
However, when I run the macro no movements happening to the bubble. Would you help me to get the correct code.
----------
Public Declare PtrSafe Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As LongPtr)
Declare PtrSafe Function GetActiveWindow Lib "user64" () As Long
Sub Button1_Click()
Dim i As Integer
For i = 0 To 10:
Range("C1").Value = i
Application.Calculate
Sleep (1200)
Next
End Sub
Comment by: Jan Karel Pieterse (19-6-2019 09:29:00) deeplink to this comment
Hi Jayan,
Try adding DoEvents immediately after the Sleep statement.
Comment by: William Brennan (24-7-2019 13:46:00) deeplink to this comment
I cannot use ShellExecute in my MS Access code. I've tried everything suggested. After one of our recent Windows 10 Updates, ShellExecute doesn't work.
Any suggestions?
Thank you.
Comment by: Jan Karel Pieterse (24-7-2019 13:51:00) deeplink to this comment
Hi William,
Can you please share some sample code which should normally work stand-alone (doesn't require any other code or data)?
Comment by: Taka Yoshida (6-8-2019 18:08:00) deeplink to this comment
Do you have 64bit version of the below?
Public Declare Function ShowWindow Lib "USER32" (ByVal hWnd As Long, ByVal nCmdSHow As Long) As Long
Thank you.
Comment by: Jan Karel Pieterse (7-8-2019 09:56:00) deeplink to this comment
Hi Taka,
As shown in the document I link to above (http://www.microsoft.com/en-us/download/confirmation.aspx?id=9970):
Declare PtrSafe Function ShowWindow Lib "user32" Alias "ShowWindow" (ByVal hwnd As LongPtr, ByVal nCmdShow As Long) As Long
Comment by: Andy Barfknecht (19-8-2019 22:03:00) deeplink to this comment
I do not understand the example URLDownloadToFile. Why are not pCaller and lpfnCB required to be type LongPtr for 64bit? They are pointers to locations in memory, are they not?
Comment by: Jan Karel Pieterse (27-8-2019 10:45:00) deeplink to this comment
Hi Andy,
Fair question. Reading the docs does make me think both should be LongPtr as they are pointers. However, I'v ebeen using this version of them without any complaints for over 5 years now :-)
Comment by: Mhlanga (3-9-2019 06:38:00) deeplink to this comment
Can you please help me with an API that removes the Title bar of the userform (i.e. the portion where we display the userform caption together with the close button).
The API should work on both 64 and 32 bit.
I have seen some posting similar APIs which are hard to decode. Most of them don't work. I'm using excel 365 and would like to remove the title bar without distorting the shape of the userform. This is very important.
By shape I mean special effect. My userform has a special effect flat. I would like to retain the smooth flat userform after applying the API, not raised or bump special effect. What I have seen is that most of the API out there result in a doomed or raised userform and that affects the outlook of my userform.
Can you help with this?
Comment by: Jan Karel Pieterse (3-9-2019 10:27:00) deeplink to this comment
Hi Mhlanga,
I'd like to refer you to this utility for which I've tried to mimick precisely that behaviour: https://jkp-ads.com/download.asp#Compare2Tables
Does that come close: Note that I haven't got round to making it 64 bit compatible yet.
Comment by: Eduardo Becerra (13-10-2019 05:27:00) deeplink to this comment
I have an old dll named MexCurves.dll
I made a Macro and is not running in new WIndows. Tried to fix it using "PtrSafe"
Declare PtrSafe Sub setTIIECurve Lib "C:\MexCurves12.dll" _
(ByVal priceDateSerial As Long, ByVal overnightRate As Double, ByVal spotTIIE As Double, ratesArray())
When running it from Excel I get error:
"C:\MexCurves12.dll" not found. Can you help please. Thanks Eduardo
Comment by: Jan Karel Pieterse (14-10-2019 10:03:00) deeplink to this comment
Hi Eduardo,
I'm afraid that will not make a difference. Your dll is clearly a 32 bit dll so it will only work on 32 MS Office. I suspect you installed 64 bit Office instead. To use your dll you must uninstall you 64 bit Office and install the 32 bit version.
Comment by: Frederick (16-10-2019 15:53:00) deeplink to this comment
Do you have 64bit version of the below?
Private Declare Sub Sleep Lib "kernel32" Alias "sleep" (ByVal dwMilliseconds As Long)
Declare Function CloseHandle Lib "kernel32" Alias "Closehandle" (ByVal hObject As Long) As Long
Comment by: Jan Karel Pieterse (16-10-2019 18:20:00) deeplink to this comment
Sure:
Declare PtrSafe Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
Declare PtrSafe Function CloseHandle Lib "kernel32" Alias "CloseHandle" (ByVal hObject As LongPtr) As Long
Comment by: Romain (20-10-2019 01:31:00) deeplink to this comment
Hi,
Would you happen to have the 64bit version for the below?
Declare PtrSafe Function ChooseColorA Lib "Comdlg32" (lpChooseColor As udtCColor) As Long
Declare PtrSafe Function FindWindowA Lib "User32" _
(ByVal lpClassName As Any, ByVal lpWindowName As String) As Long
Comment by: Jan Karel Pieterse (21-10-2019 17:00:00) deeplink to this comment
Hi Romain,
Accoring to the link provided at the top it is:
Type CHOOSECOLOR
lStructSize As Long
hwndOwner As LongPtr
hInstance As LongPtr
rgbResult As Long
lpCustColors As LongPtr
flags As Long
lCustData As LongPtr
lpfnHook As LongPtr
lpTemplateName As String
End Type
Declare PtrSafe Function ChooseColor Lib "comdlg32.dll" Alias "ChooseColorA" (pChoosecolor As CHOOSECOLOR) As Long
Comment by: Dutch (25-2-2020 09:45:00) deeplink to this comment
I believe this could be the full list, including proper type declarations:
https://www.cadsharp.com/docs/Win32API_PtrSafe.txt
Comment by: Jan Karel Pieterse (25-2-2020 10:02:00) deeplink to this comment
Hi Dutch,
Thanks, that is exactly the same file as the one I point to at the top of the article, linked under "Office 2010 Help Files: Win32API_PtrSafe with 64-bit Support" with this link:
http://www.microsoft.com/en-us/download/confirmation.aspx?id=9970
Comment by: Mario Bérubé (25-3-2020 00:53:00) deeplink to this comment
In the table «Declarations by API function» above, I think the right column title should be:
Declarations (64 bit followed by 32 bit)
Comment by: Jan Karel Pieterse (25-3-2020 09:50:00) deeplink to this comment
Hi Mario,
I agree the table caption is confusing as I have not been consistent in the order of the declarations. I have updated the column title accordingly :-)
Comment by: Antonio Elinon (31-5-2020 15:48:00) deeplink to this comment
For VBA7 & not Win64, can you confirm "GetWindowLongA() as LongPtr" above.
Other websites say it is only Long-
https://answers.microsoft.com/en-us/msoffice/forum/all/office-64-bit-code-compatibility/f6ae23f2-2610-4887-a7f4-21b52c1c1323
Comment by: Jan Karel Pieterse (2-6-2020 11:29:00) deeplink to this comment
Hi Antonio,
I have several add-ins all using the declaration shown here, without issues.
Comment by: Martin L (9-7-2020 19:29:00) deeplink to this comment
Regarding Antonio's comment, it doesn't matter if LongPtr or Long is used because LongPtr will always compile to Long when Win64 is "False" (since we would be under a 32-bit environment in that case).
Comment by: Jim Meehan (28-7-2020 18:20:00) deeplink to this comment
In GlobalAlloc, you've got the wflags as longptr. Wouldn't these just be small indicators (Long)?
Comment by: Jan Karel Pieterse (28-7-2020 18:58:00) deeplink to this comment
Hi Jim,
Having read the documentation once more I expect you are correct.
Comment by: yongZhen Li (22-8-2020 05:42:00) deeplink to this comment
Declaring API functions in 64 bit Office:
GetWindow
GetWindowText
GetForegroundWindow
FindWindowLike
Comment by: Robert Marshall (22-8-2020 19:38:00) deeplink to this comment
Is the code for GetWindowLong correct? The second declaration seems to be incorrect and should be identical to the third declaration.
Comment by: Jan Karel Pieterse (24-8-2020 10:26:00) deeplink to this comment
Hi Robert,
The declarations for GetWindowLong were taken directly from the Microsoft documents as available for download here:
http://www.microsoft.com/en-us/download/confirmation.aspx?id=9970
Are you saying the docs are wrong?
Comment by: Jan Karel Pieterse (24-8-2020 10:27:00) deeplink to this comment
Hi yongZhen,
Did you mean to ask a question about those declarations?
Comment by: Jim Meehan (30-11-2020 23:05:00) deeplink to this comment
Occasionally I see something like:
"lpEnvironment As Any"
What does ANY mean in this context? If it seems like a pointer, should I change it to LongPtr, when doing 64-bit?
The program I inherited has it too, and I never learned that wording...
Thanks.
Comment by: Jan Karel Pieterse (1-12-2020 10:56:00) deeplink to this comment
Hi Jim,
The Any keyword is similar to declaring a variable as Variant; it accepts data of any type. That does not mean it is necessarily the correct declaration, each argument of an API function usually is of a specific type. So in my view, using Any is the lazy approach you can often get away with in VBA :-)
Comment by: andy (22-12-2020 06:10:00) deeplink to this comment
Private Declare Function _
CoRegisterMessageFilter Lib "OLE32.DLL" _
(ByVal lFilterIn As Long, _
ByRef lPreviousFilter) As Long
-i need to edit make it work for 64bit. can someone help me pleae?
Comment by: Jan Karel Pieterse (22-12-2020 14:49:00) deeplink to this comment
Hi Andy,
I expect this:
#If VBA7 Then
Private Declare PtrSafe Function _
CoRegisterMessageFilter Lib "OLE32.DLL" _
(ByVal lFilterIn As LongPtr, _
ByRef lPreviousFilter As LongPtr) As Long
#Else
Private Declare Function _
CoRegisterMessageFilter Lib "OLE32.DLL" _
(ByVal lFilterIn As Long, _
ByRef lPreviousFilter As Long) As Long
#End If
Comment by: Andrii (26-12-2020 14:55:00) deeplink to this comment
Hello Jan Karel Pieterse
Please 32 bit code -> 64 bit code
(TYPE and DECLARE FUNCTION)
Const VK_H = 72
Const VK_E = 69
Const VK_L = 76
Const VK_O = 79
Const VK_ENTER = &HD
Const KEYEVENTF_KEYUP = &H2
Const INPUT_MOUSE = 0
Const INPUT_KEYBOARD = 1
Const INPUT_HARDWARE = 2
Private Type MOUSEINPUT
dx As Long
dy As Long
mouseData As Long
dwFlags As Long
time As Long
dwExtraInfo As Long
End Type
Private Type KEYBDINPUT
wVk As Integer
wScan As Integer
dwFlags As Long
time As Long
dwExtraInfo As Long
End Type
Private Type HARDWAREINPUT
uMsg As Long
wParamL As Integer
wParamH As Integer
End Type
Private Type GENERALINPUT
dwType As Long
xi(0 To 23) As Byte
End Type
Private Declare PtrSafe Function SendInput Lib "user32.dll" (ByVal nInputs As Long, pInputs As GENERALINPUT, ByVal cbSize As Long) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Sub Test()
Shell "NotePad.EXE", 1
SendKey VK_H
SendKey VK_E
SendKey VK_L
SendKey VK_L
SendKey VK_O
SendKey VK_ENTER
SendKey VK_H
SendKey VK_E
SendKey VK_L
SendKey VK_L
SendKey VK_O
End Sub
Private Sub SendKey(bKey As Byte)
Dim GInput(0 To 1) As GENERALINPUT, KInput As KEYBDINPUT
KInput.wVk = bKey
KInput.dwFlags = 0
GInput(0).dwType = INPUT_KEYBOARD
CopyMemory GInput(0).xi(0), KInput, Len(KInput)
KInput.wVk = bKey
KInput.dwFlags = KEYEVENTF_KEYUP
GInput(1).dwType = INPUT_KEYBOARD
CopyMemory GInput(1).xi(0), KInput, Len(KInput)
Call SendInput(2, GInput(0), Len(GInput(0)))
End Sub
Thank you very much !
Comment by: Jan Karel Pieterse (28-12-2020 11:45:00) deeplink to this comment
Hi Andrii,
You should be able to decide what the declaration looks like from the Microsoft dcoumentation:
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/aa366535%28v=vs.85%29
Comment by: Luis Moraga (6-7-2021 18:20:00) deeplink to this comment
Very useful page! Solved my problem.
(I just spotted a typo in your "I give permission to process ...." line: says "accoring" where it should say "according").
Comment by: Jan Karel Pieterse (7-7-2021 10:58:00) deeplink to this comment
Hi Luis,
Well spotted, thank you!!!
Comment by: Dan Wallace (21-7-2021 17:20:00) deeplink to this comment
Hello
Thank you for this wonderful resource. I return to it regularly.
I wanted to ask if you knew of the 64bit declarations for the bcrypt and GDIPlus libraries. I am self-studying my way through VBA, and am currently working with alot of VB6 materials (which do not have to convert declarations into 64bit). As regards BCrypt, I am trying to convert the following into VBA: https://www.vbforums.com/showthread.php?862103-VB6-Simple-AES-256-bit-password-protected-encryption
And for GDIPlus, I have some declarations but cannot seem to find all of them.
Any guidance would be greatly appreciated.
Comment by: Jan Karel Pieterse (21-7-2021 17:44:00) deeplink to this comment
Hi Dan,
I'm afraid I don't have any of those!
What I have done for the ones that are not in the txt download that is mentioned near the top of this page, is simply google for the function's name and the string docs.microsoft.com.
That usually gets you a link to the documentation of the function which states the argument types. Here's an example:
https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptopenalgorithmprovider
You can see from the docs that the first three arguments are pointers, so those need to be LongPtr. The last one is a flag, which can be represented by a simple Long. Finally, that function returns a status code so I'm relatively confident that a Long return type suffices.
So that is the (hard) way to translate these from 32 to 64 bit I'm afraid.
Would be nice if you can share the ones you have tried and tested so far, so I might include them here.
Comment by: Dan (24-7-2021 23:54:00) deeplink to this comment
Hello
Thank you kindly for taking the time to respond to my query. I suspected that this might be the case. Thank you also for your guidance on how to go about converting the declarations. I will, of course, share with you / post on Github any declarations I manage to convert.
I am, separately, working on an add-in to parse code in a selected open workbook or a text file for any 32-bit declarations and either replace the code with the 64-bit equivalent or add it into a conditional declaration/compilation portion of the code. The brick wall I've come up against is making sure that any dimensioned variables are also converted. I'll share with you/all a beta version of where I'm up to once I've knocked it into some form that isn't too embarrassing.
I am, again, grateful to you for your help and indeed for this website.
Kind regards, Dan
Comment by: Jan Karel Pieterse (26-7-2021 10:16:00) deeplink to this comment
Hi Dan,
You're welcome! I'm certainly interested to see what your tool will look like.
Comment by: Ron Cook (13-8-2021 17:18:00) deeplink to this comment
Where are the updated virtual key codes listed?
-- Verify we are using the latest syntax
Best Regards...
Comment by: Jan Karel Pieterse (13-8-2021 17:36:00) deeplink to this comment
Hi Ron,
Which function are you referring to please?
Does this link help:
https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
Comment by: Dan Wallace (21-10-2021 23:09:00) deeplink to this comment
Hello, I left a message on this board back in July, and now I'm back partly to ask another question and partly to give an update!
Question: I understand that the where the entry point ends with a 'A' or a 'W', that designates the ANSI and Unicode versions of the API, and I've read somewhere that the W variant are to be preferred, but the MS document (Win32api.txt) is limited to the A variant. I'd appreciate it if you could let me know if it's simply a matter of swapping the A for the W when making the declaration - or might there also be differences in the parameters? The one W variant in my slowly growing list of declarations is
GetStringTypeW
- this appears to one more parameter than it's A counterpart. Any guidance would be appreciated.
Comment by: Jan Karel Pieterse (22-10-2021 14:24:00) deeplink to this comment
Hi Dan,
It looks like you only have to add the additional argument and figure out what the type of that argument needs to be, or remove an obsolete argument. For GetStringTypeA/W, the only difference is the first argument. LCID is in the A version and is missing from the W version.
To get the help information of a function, just google for the name of the function, followed by docs.microsoft. That usually gets you the most relevant hit.
Comment by: Vegard Leithe (2-11-2021 08:45:00) deeplink to this comment
Hello
I have tried to get out list items from a listbox from a 3rd party software. Are not able to figure it out. Have no issues controlling the software through edit windows, button windows etc. Have tried google for a week no. No success.
Are not able to figure it out. Was interesting to read about the LongPtr that need to be changed for a 64 bits. Tried that as well since I am sitting on a 64 bits win 10 machine.
Any hints for me?
I can share the code?
Regards
Vegard
Comment by: Jan Karel Pieterse (2-11-2021 09:42:00) deeplink to this comment
Hi Vegard,
You can share the code which is on this page if that is what you are asking?
But if you have a problem with your own code, feel free to post a question here, or consider asking on a dedicated forum, such as https://https://www.mrexcel.com/board/
Comment by: Diana (6-12-2021 21:34:00) deeplink to this comment
how can I fix this declaration to when running 64 bit
32-bit API declarations
Declare Function SHGetPathFromIDList Lib "shell32.dll" _
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long
Declare Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long
Comment by: Jan Karel Pieterse (7-12-2021 10:02:00) deeplink to this comment
Hi Diana,
Both functions are listed in the article, can you indicate what your issue is please?
Comment by: Belaki (3-3-2022 17:01:00) deeplink to this comment
O365 64-bit VBA Declarations for File Search API Calls:
Public Declare PtrSafe Function FindClose Lib "kernel32" ( _
ByVal hFindFile As LongPtr _
) As Long
Public Declare PtrSafe Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" ( _
ByVal lpFileName As String, _
lpFindFileData As WIN_32_FIND_DATA _
) As LongPtr
Public Declare PtrSafe Function FindNextFile Lib "kernel32" Alias "FindNextFileA" ( _
ByVal hFindFile As LongPtr, _
lpFindFileData As WIN_32_FIND_DATA _
) As LongPtr
Public Declare PtrSafe Function PathMatchSpec Lib "Shlwapi" Alias "PathMatchSpecW" ( _
ByVal pszFileParam As LongPtr, _
ByVal pszSpec As LongPtr _
) As Long
Comment by: Jan Karel Pieterse (3-3-2022 17:03:00) deeplink to this comment
Thanks Blake! Odd enough, the API docs have a different type for the FindNextFile function (it says it returns a Long). I'm inclined to think that is a typo and it should indeed be a LongPtr
Comment by: Belaki (3-3-2022 17:41:00) deeplink to this comment
Yup, I almost fell out of my chair when I got it to work, after several days of scratching my head...
Comment by: John Burger (5-4-2022 00:21:00) deeplink to this comment
It appears that GlobalAlloc has the VBA7 and Else declarations swapped. I believe it should be as below:
#If VBA7 Then
Private Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As LongPtr) As LongPtr
#Else
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long
#End If
If not and it's correct as-is, then I recommend an explanation for why it otherwise seems backwards.
Comment by: Jan Karel Pieterse (5-4-2022 09:52:00) deeplink to this comment
Hi John,
You're right of course, I'll update the page ASAP, thanks!
Comment by: PAUL H HOSSLER (10-5-2022 13:35:00) deeplink to this comment
https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/longptr-data-type
"LongPtr is not a true data type because it transforms to a Long in 32-bit environments, or a LongLong in 64-bit environments. Using LongPtr enables writing portable code that can run in both 32-bit and 64-bit environments. Use LongPtr for pointers and handles."
It would seem that using PtrSafe and LongPtr would eliminate the need to use conditional compilation for many API calls in 32 vs 64 bit office. Is this correct?
Comment by: Jan Karel Pieterse (10-5-2022 14:41:00) deeplink to this comment
Hi Paul,
I think you are correct, but I've never tried. But as long as Office 2007 is still being used, you risk (an ever smaller) group of users that get a compile error.
Comment by: Simon (10-10-2022 11:56:00) deeplink to this comment
Hi,
Why doesn't URLDownloadToFile use LongPtr for arguments and return type ?
I have found references where it has been used
e.g. https://stackoverflow.com/questions/59681699/download-file-from-url-in-excel-2019-it-works-on-excel-2007
Comment by: Jan Karel Pieterse (10-10-2022 13:17:00) deeplink to this comment
Hi Simon,
I suspect you are correct. I have updated this page.
Comment by: Axel de Valroger (6-1-2023 18:00:00) deeplink to this comment
Thx for this huge work !
I need win64 declaration of an API you don't have there :
GetWindowTextLengthA...
Looking for it elsewhere...
But if you find it before me, I'd appreciate the info...
Cheers
Axel
(France)
Comment by: Jan Karel Pieterse (9-1-2023 11:21:00) deeplink to this comment
Hi Axel,
I've added it:
https://jkp-ads.com/articles/apideclarations.asp#GetWindowTextLength
Comment by: Cristina Ghinea (30-1-2023 12:38:00) deeplink to this comment
It works to run the macro but I have the following error:
Compile error:User defined type not defined.
Do you know what can I do to not have this error?
Thank you!
Comment by: Jan Karel Pieterse (30-1-2023 14:48:00) deeplink to this comment
Hi Cristina,
Which macro are you referring to please?
Comment by: Thomas Rauner (27-3-2023 23:03:00) deeplink to this comment
Tested with Office 2010 x86 and Office 2019 x64:
#If VBA7 Then
Private Declare PtrSafe Function OleTranslateColor Lib "oleaut32.dll" _
(ByVal lOleColor As Long, ByVal lHPalette As Long, lColorRef As Long) As Long
#Else
Private Declare Function OleTranslateColor Lib "olepro32.dll" Alias "OleTranslateColor" _
(ByVal lOleColor As Long, ByVal lHPalette As Long, ByRef lColorRef As Long) As Long
#End If
Comment by: Jan Karel Pieterse (28-3-2023 10:32:00) deeplink to this comment
Hi Thomas,
Thanks, I've added it to this page:
https://jkp-ads.com/articles/apideclarations.asp#OleTranslateColor
Comment by: Will T (13-6-2023 22:12:00) deeplink to this comment
SetLayeredWindowAttributes for VBA7?
Comment by: Jan Karel Pieterse (14-6-2023 11:55:00) deeplink to this comment
Hi Will,
I think this should be the correct declaration:
#If VBA7 Then
Public Declare PtrSafe Function SetLayeredWindowAttributes Lib "user32" ( _
ByVal hWnd As LongPtr, _
ByVal crKey As LongPtr, _
ByVal bAlpha As Byte, _
ByVal dwFlags As Long) As Long
#Else
Public Declare Function SetLayeredWindowAttributes Lib "user32" ( _
ByVal hWnd As Long, _
ByVal crKey As Long, _
ByVal bAlpha As Byte, _
ByVal dwFlags As Long) As Long
#End If
Comment by: Dave (25-8-2023 05:06:00) deeplink to this comment
How about RegOpenKeyEx? I can't seem to find an example of how that should be declared for 64bit
Comment by: Jan Karel Pieterse (25-8-2023 16:50:00) deeplink to this comment
Hi Dave,
Perhaps this helps?
https://stackoverflow.com/questions/20479965/using-regopenkeyex-to-enumerate-through-registry-on-64bit-office-64-bit-windows
Comment by: GG (27-9-2023 09:59:00) deeplink to this comment
I want to know why MS document Win32api.txt is limited to the A variant.Doesn't need the W variant to change 32bit to 64bit migration.
Sorry for my bad question,please give me advice.Thanks you.
Comment by: Jan Karel Pieterse (27-9-2023 11:58:00) deeplink to this comment
Hi GG,
Whether to use the A or W variants depends whether you are using the Windows code page or Unicode, see:
https://learn.microsoft.com/en-us/windows/win32/intl/conventions-for-function-prototypes
I suspect the declarations can be easily translated from A to W simply by replacing the A with the W in the declaration line. It is best to read the documentation. Tip: To get to the docs of the w variant, simply replace the a with the w in the url of the documentation page.
If your question is not directly related to this web page, but rather a more
general "How do I do this" Excel question, then I advise you to ask
your question here: www.eileenslounge.com.