Home Article Index Links Newsletter

Deze pagina in het NederlandsHome > Article Index >

Declaring API functions in 64 bit Office

Introduction

With the introduction of Windows 7 and Office 2010 VBA developers face a new challenge: ensuring their applications work on both 32 bit and 64 bit platforms.

This page is meant to become 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.

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

CloseClipboard

  Declare PtrSafe Function CloseClipboard Lib "User32" () As LongPtr

  Declare Function CloseClipboard Lib "User32" () As Long

CreateProcess

 

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

     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


    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

'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

DrawMenuBar

 
#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

EmptyClipboard

 
  Declare PtrSafe Function EmptyClipboard Lib "User32" () As LongPtr

  Declare Function EmptyClipboard Lib "User32" () As Long

FindWindow

 
Private Declare Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private
Declare PtrSafe Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

FindWindowEx

 
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

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

GdipCreateBitmapFromFile

Private Declare Function GdipCreateBitmapFromFile Lib "GDIPlus" (ByVal filename As Long, bitmap As Long) As Long

Private Declare PtrSafe Function GdipCreateBitmapFromFile Lib "GDIPlus" (ByVal filename As LongPtr, bitmap As LongPtr) As LongPtr

GdipCreateHBITMAPFromBitmap

Private Declare Function GdipCreateHBITMAPFromBitmap Lib "GDIPlus" (ByVal bitmap As Long, hbmReturn As Long, ByVal background As Long) As Long

Private Declare PtrSafe Function GdipCreateHBITMAPFromBitmap Lib "GDIPlus" (ByVal bitmap As LongPtr, hbmReturn As LongPtr, ByVal background As Long) As LongPtr

GdipDisposeImage

Private Declare Function GdipDisposeImage Lib "GDIPlus" (ByVal image As Long) As Long

Private Declare PtrSafe Function GdipDisposeImage Lib "GDIPlus" (ByVal image As LongPtr) As LongPtr

GdiplusShutdown

Private Declare Function GdiplusShutdown Lib "GDIPlus" (ByVal token As Long) As Long

Private Declare PtrSafe Function GdiplusShutdown Lib "GDIPlus" (ByVal token As LongPtr) As LongPtr

GdiplusStartup

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

GetClassName

 
Public Declare Function GetClassName Lib "USER32" Alias "GetClassNameA" _
                                     (ByVal hWnd As Long, ByVal lpClassName As String, _
                                      ByVal nMaxCount As Long) As Long

Public Declare PtrSafe Function GetClassName Lib "USER32" Alias "GetClassNameA" _
                                     (ByVal hWnd As LongPtr, ByVal lpClassName As String, _
                                      ByVal nMaxCount As LongPtr) As Long

GetDiskFreeSpaceEx

 
Private Declare Function GetDiskFreeSpaceEx Lib "kernel32" _
    Alias "GetDiskFreeSpaceExA" (ByVal lpDirectoryName As String, _
    lpFreeBytesAvailableToCaller As Currency, _
    lpTotalNumberOfBytes As Currency, _
    lpTotalNumberOfFreeBytes As Currency) As Long
Private Declare PtrSafe Function GetDiskFreeSpaceEx Lib "kernel32" Alias _
    "GetDiskFreeSpaceExA" (ByVal lpDirectoryName As String, _
    lpFreeBytesAvailableToCaller As Currency, lpTotalNumberOfBytes As _
    Currency, lpTotalNumberOfFreeBytes As Currency) As LongPtr

getDC

 
Private Declare Function GetDC Lib "USER32" (ByVal hWnd As Long) As Long

Private
Declare PtrSafe Function GetDC Lib "USER32" (ByVal hWnd As LongPtr) As LongPtr

GetDesktopWindow

 
Public Declare Function GetDesktopWindow Lib "USER32" () As Long

Public Declare PtrSafe Function GetDesktopWindow Lib "USER32" () As LongPtr

getDeviceCaps

Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long, ByVal nIndex As Long) As Long

Private
Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hDC As LongPtr, ByVal nIndex As Long) As Long

GetDriveType

 
Private Declare Function GetDriveType Lib "kernel32" Alias _
                        "GetDriveTypeA" (ByVal sDrive As String) As Long

Private Declare PtrSafe Function GetDriveType Lib "kernel32" Alias _
                                "GetDriveTypeA" (ByVal sDrive As String) As LongPtr

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

GetForegroundWindow

 
Declare Function GetForegroundWindow Lib "user32.dll" () As Long

Declare PtrSafe Function GetForegroundWindow Lib "user32.dll" () As LongPtr

getFrequency

 
Declare Function getFrequency Lib "kernel32" Alias "QueryPerformanceFrequency" (cyFrequency As Currency) As Long

Private
Declare PtrSafe Function getFrequency Lib "kernel32" Alias "QueryPerformanceFrequency" (cyFrequency As Currency) As Long

GetKeyState

#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

GetLastInputInfo

 
#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

GetOpenFileName

 
Option Explicit

#If VBA7 Then
    Public Declare PtrSafe Function GetOpenFileName Lib "comdlg32.dll" Alias _
            "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
      
    Public 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

    Public Declare Function GetOpenFileName Lib "comdlg32.dll" Alias _
            "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
      
    Public 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    //
'/////////////////////////////////


Public 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

GetSystemMetrics

Private Declare Function GetSystemMetrics Lib "USER32" (ByVal nIndex As Long) As Long

Private
Declare PtrSafe Function GetSystemMetrics Lib "USER32" (ByVal nIndex As Long) As Long

GetTempPath

 
Declare Function GetTempPath Lib "kernel32" _
                             Alias "GetTempPathA" (ByVal nBufferLength As Long, _
                                                   ByVal lpbuffer As String) As Long

Declare PtrSafe Function GetTempPath Lib "kernel32" _
                             Alias "GetTempPathA" (ByVal nBufferLength As longptr, _
                                                   ByVal lpbuffer As String) As Long

getTickCount

 
Private Declare Function getTickCount Lib "kernel32" Alias "QueryPerformanceCounter" (cyTickCount As Currency) As Long

Private
Declare PtrSafe Function getTickCount Lib "kernel32" Alias "QueryPerformanceCounter" (cyTickCount As Currency) As Long
    '

getTime

 
Private Declare Function timeGetTime Lib "winmm.dll" () As Long

Private
Declare PtrSafe Function timeGetTime Lib "winmm.dll" () As Long

GetWindow

 
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 Long) As LongPtr

GetWindowLong

 

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

GetWindowsDirectory

 
Declare Function GetWindowsDirectory& Lib "kernel32" Alias _
                                      "GetWindowsDirectoryA" (ByVal lpbuffer As String, _
                                                              ByVal
nSize As Long)

Declare PtrSafe Function GetWindowsDirectory& Lib "kernel32" Alias _
                                      "GetWindowsDirectoryA" (ByVal lpbuffer As String, _
                                                              ByVal
nSize As LongPtr)

GetWindowText

 
Public Declare Function GetWindowText Lib "USER32" Alias "GetWindowTextA" _
                                      (ByVal hWnd As Long, ByVal lpString As String, _
                                       ByVal cch As Long) As Long

Public Declare PtrSafe Function GetWindowText Lib "USER32" Alias "GetWindowTextA" _
                                      (ByVal hWnd As LongPtr, ByVal lpString As String, _
                                       ByVal cch As LongPtr) As Long

GlobalAlloc

 
  Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As LongPtr) As LongPtr

  Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long

GlobalLock

 
  Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr

  Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long

InternetGetConnectedState

 
Public Declare Function InternetGetConnectedState _
        Lib "wininet.dll" (lpdwFlags As Long, _
        ByVal dwReserved As Long) As Boolean

Public Declare PtrSafe Function InternetGetConnectedState _
        Lib "wininet.dll" (lpdwFlags As LongPtr, _
        ByVal dwReserved As long) As Boolean

IsCharAlphaNumericA

 
Private Declare Function IsCharAlphaNumericA Lib "USER32" (ByVal byChar As Byte) As Long

Private
Declare PtrSafe Function IsCharAlphaNumericA Lib "USER32" (ByVal byChar As Byte) As Long

lstrcopy

 
  Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As LongPtr

  Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, ByVal lpString2 As Any) As Long

Mouse_Event

 
#If VBA7 Then
    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

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

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

OpenClipboard

 
  Declare PtrSafe Function OpenClipboard Lib "User32" (ByVal hwnd As LongPtr) As LongPtr

  Declare Function OpenClipboard Lib "User32" (ByVal hwnd As Long) As Long

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

ReleaseDC

 
Private Declare Function ReleaseDC Lib "USER32" (ByVal hWnd As Long, ByVal hDC As Long) As Long

Private
Declare PtrSafe Function ReleaseDC Lib "USER32" (ByVal hWnd As LongPtr, ByVal hDC As LongPtr) As Long

SendMessage

 
Public Declare Function SendMessageA Lib "user32" (ByVal hWnd As Long, ByVal wMsg As Long, _
                                                   ByVal wParam As Long, lParam As Any) As Long
Public Declare PtrSafe Function SendMessageA Lib "user32" (ByVal hWnd As LongPtr, ByVal wMsg As Long, _
                                                           ByVal wParam As LongPtr, lParam As Any) As LongPtr

SetActiveWindow

 
Declare Function SetActiveWindow Lib "user32.dll" (ByVal hWnd As Long) As Long

Declare PtrSafe Function SetActiveWindow Lib "user32.dll" (ByVal hWnd As LongPtr) As LongPtr

SetClipboardData

 
  Declare PtrSafe Function SetClipboardData Lib "User32" (ByVal wFormat As LongPtr, ByVal hMem As LongPtr) As LongPtr

  Declare Function SetClipboardData Lib "User32" (ByVal wFormat As Long, ByVal hMem As Long) As Long

SetCurrentDirectory

 
Private Declare Function SetCurrentDirectoryA Lib "kernel32" (ByVal lpPathName As String) As Long

Private
Declare PtrSafe Function SetCurrentDirectoryA Lib "kernel32" (ByVal lpPathName As String) As Long

SetWindowLongPtr

 

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

SetWindowPos

 
#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

SHBrowseForFolder

#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

ShellExecute

 
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

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

SHFileOperation

 
#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

SHGetPathFromIDList

 
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" _
        (ByVal pidl As Long, ByVal pszPath As String) As Boolean

Private Declare PtrSafe Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" _
        (ByVal pidl As LongPtr, ByVal pszPath As String) As Boolean

SHGetSpecialFolderLocation

#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

timeGetTime

 
Private Declare Function timeGetTime Lib "winmm.dll" () As Long

Private
Declare PtrSafe Function timeGetTime Lib "winmm.dll" () As Long

URLDownloadToFile

 
#If VBA7 Then
Private Declare PtrSafe 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
#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:

Public Declare Function SendMessageA Lib "user32" (ByVal hWnd As Long, ByVal wMsg As Long, _
                                                   ByVal wParam As Long, lParam As Any) As Long

64 bit:

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


Comments

Showing last 8 comments of 331 in total (Show All Comments):

 


Comment by: Jan Karel Pieterse (24-8-2020 10:26:00)

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)

Hi yongZhen,

Did you mean to ask a question about those declarations?

 


Comment by: Jim Meehan (30-11-2020 23:05:00)

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)

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)

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)

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)

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)

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

 


Have a question, comment or suggestion? Then please use this form.

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.

Please enter your name (required):

Your e-mail address (optional, will only be used to inform you when your comment is published or to respond to your question directly):

Your request or comment (max 2000 characters):

To post VBA code in your comment, use [VB] tags, like this: [VB]Code goes here[/VB].

I give permission to process this data and display my name and my comment on this website accoring to our Privacy Policy.