Windows API

Creates a reference to a procedure or function in an external DLL.
The reason for calling an API function is to perform something that would otherwise be impossible.


These functions are a set of functions that Windows programs use to manipulate Windows.
In traditional applications the functions used / called where 'statically linked' to the program.
The program included all the functions it needed.
The obvious problem is the same functions and procedures are reproduced lots of times.


64 Bit - PtrSafe

In 32 bit office a pointer must be a 32 bit variable In 64 bit office a pointer must be a 64 bit variable.
When declaring an API you must acknowledge this fact by adding the PtrSafe keyword to the API declaration.

Public Declare PtrSafe Function GetTickCount Lib "kernel32" () As LongLong 

When declaring an API you must acknowledge this fact by adding the PtrSafe keyword to the API declaration.
The PtrSafe attribute is optional on the 32-bit version of Office.
When running 32 Bit Office a pointer must be a 32 bit variable
When running 64 Bit Office a pointer must be a 64 bit variable.


Alias Keyword

Whenever you use an API (Application Programming Interface) call function prefix the alias with "A" eg aFindWindow
Windows uses a different approach. Libraries are usually 'dynamically linked' to the program. The common routines reside in a Dynamic Link Library and are stored in the Windows / System directory if more than one program uses them.


[Public | Private] Declare Sub name Lib "libname" [Alias "aliasname"] [ (arglist) ] 

These functions provide facilities to create a window, change its size, read and write Registry entries, manipulate a file and so on. Most of these functions are stored in the three link libraries (User32.dll, Kernel.dll & ????)


A full list of all Windows API functions and subroutines, containing the syntax of their calls can be found in the help file "WIN32API.txt" which is available for download from the unit websites.


If you are going to use Windows API calls in your code it may be worth encapsulating them into a class.


Before you can use a Windows API function you must declare the function at the top of a standard code module above the first procedure.
Declaring a Windows API can be a bit tricky for the following reasons:
1) Deciding which API to actually use
2) Deciding in which library the function is located
3) Knowing the exact arguments

Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer 

Once it is declared you can use it just like a regular function.


Example - GetWindowsDirectory

Declare Function GetWindowsDirectoryA Lib "kernel32" (ByVal lpBuffer As String, ByVal nSize As Long) As Long 

This function returns the name of the directory in which Windows is installed and has two arguments,
After calling the function, the Windows directory is contained in lpBuffer, and the length of the directory string is contained in nSize.
Once you have added the Declare statement to the top of your module, you can access the function by calling the GetWindowsDirectoryA function.

Dim sPathName As String 
sPathName = GetWindowsDirectoryA(Space(255), 255)

Creating a Wrapper

Most of the time you will probably want to create a wrapper for the API function.
Creating a wrapper can simplify actually using the function.

Function WindowsDire() As String 
   Dim WinPath As String
   WinPath = Space(255)
   WindowsDir = Left(WinPath, GetWindowsDirectoryA(WinPath, Len(WinPath)) )
End Function

Dynamic Link Libraries (DLL)
One of the most powerful features of VBA is the ability to call a DDL from a VBA procedure. A dynamic link library is a list of routines loaded into memory and linked to applications at run-time. DLL's are normally written in C or C++ although you could create then using Pascal or Delphi. You declare a reference to an external procedure in a DLL by the following syntax.
Because DLL routines reside in files that are external to your application, you must let VBA know exactly where the files are
Public Declare PtrSafe Sub name Lib "libname" Alias "aliasname" (arglist)
Public Declare PtrSafe Function name Lib "libname" Alias "aliasname" (arglist) as type
The procedure name that immediately follows the Declare keyword indicates the name you are going to use to call the procedure (ie an alias name). The name in quotes, after the Alias keyword specifies the actual name of the procedure as it can be found in the DLL
Libname is the name of the DLL that contains the procedure being declared and alias name is the name of the procedure in the DLL. To use a DLL you must know the procedure in it and the arguments to each of these procedures.
Accompanying the DLL there may be a file called a 'type library' which describes the procedures within the DLL. A type library normally has the extension (.OLB) or (.TLB) and is registered with the OLE component of Windows. The Setup program that installs the DLL usually creates the properties with the Windows Registry. Tools > References shows all the registered type libraries available


If you use a type library, there is no need to use Declare statements as the functionality is included. Type libraries also avoid the difficulties of passing strings to DLLs. The Windows API doesn't have a type library and so you must Declare the functions before they can be used. A Declare statement must be made in the declaration section of your module.
It is important to save your work before running any code that calls a DLL as an incorrect call will result in a General Protection (GP) fault and will cause VBA to crash losing any unsaved changes. Also take care when returning strings from DLLs


You can only pass numeric arrays to DLLs. (not string or user defined) When passing an array you must give some indication of the size of the array.
The name of the procedure given in the Declare statement is case sensitive. If you want the procedure name in your code to use a different capitalisation you must use the Alias Name.
Converting C parameters into VBA declarations. The documentation for DLLs that aren't part of the Windows API are usually in the form of a C header file that provides the type and number of the arguments to the functions in the DLL. Toy will need to convert the C data types into their equivalent VBA data type.
Calling a DLL procedure is a method of performing tasks that standard VBA functions and statements do not allow. For example VBA has no intrinsic ability to retrieve information about the amount of free memory available but you can easily do this with an API call. Windows itself includes a number of DLLs with hundreds of useful functions. These functions are collectively called the Windows API.


Libraries

File NameDescription
ADVAPI32.DLLRegistry and NT Security functions
COMDLG32.DLL.Standard Windows dialog functions
GDI32.DLLGraphics and Display functions
KERNEL32.DLLFile and System-related functions (such as managing programs)
MPR.DLLNetwork functions
NETAPI32.DLLNetwork functions
OLEAUTH22.DLL 
OLEPRO32.DLL 
SHELL32.DLLWindows shell functions (such as handling icons and launching programs)
SHLWAPI.DLL 
USER32.EXEUser-interface functions (such as managing windows, the keyboard, clipboard etc)
WININET.DLLInternet functions
WINMM.DLLMultimedia functions
WINSPOOL.DRVPrinting functions

DeleteUrlCacheEntry

Deleting a file from the cache:

Private Declare PtrSafe Function DeleteUrlCacheEntry Lib "wininet.dll" Alias "DeleteUrlCacheEntryA" ( _ 
    ByVal lpszUrlName As String) As Long

URLDownloadToFile

Downloading a file from a URL

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

WNetGetConnection


Private Declare PtrSafe Function WNetGetConnection Lib "mpr.dll" Alias "WNetGetConnectionA" ( _ 
    ByVal lpszLocalName As String, _
    ByVal lpszRemoteName As String, _
    cbRemoteName As Long) As Long

Visual Basic Editor - References

Here is a list of common Visual Basic Editor Libraries


Data Type Conversions

Windows APIVBA
BOOLLong
BYTE, BYTE*, CHARByte
Char_huge*, LPCSTR, LPTSTRString
UNIT, WORD, SHORTInteger
INT, DWORD, LONGLong
hWnd, hDC (handles)Long

Advapi32.dll

RegCloseKey 
RegCreateKeyEx 
RegOpenKeyEx 
RegSetValueExString 
RegSetValueExLong 
RegQueryValueExString 
RegQueryValueExLong 
RegQueryValueExNULL 

Private Declare PtrSafe Function RegOpenKeyA Lib "advapi32.dll" _ 
  (ByVal hKey As Long, ByVal sSubKey As String, ByRef hkeyResult As Long) As LongPtr

Private Declare PtrSafe Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As LongPtr

Private Declare PtrSafe Function RegSetValueExA Lib "advapi32.dll" _
  (ByVal hKey As Long, ByVal sValueName As String, ByVal dwReserved As Long, _
   ByVal dwType As Long, ByVal sValue As String, ByVal dwSize As Long) As LongPtr

Private Declare PtrSafe Function RegCreateKeyA Lib "advapi32.dll" _
  (ByVal hKey As Long, ByVal sSubKey As String, ByRef hkeyResult As Long) As LongPtr

Private Declare PtrSafe Function RegQueryValueExA Lib "advapi32.dll" _
  (ByVal hKey As Long, ByVal sValueName As String, ByVal dwReserved As Long, _
   ByRef lValueType As Long, ByVal sValue As String, ByRef lResultLen As Long) As LongPtr

Private Declare PtrSafe Function RegQueryValueExString Lib "advapi32.dll" Alias "RegQueryValueExA" _
  (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, _
   lpType As Long, ByVal lpData As String, lpcbData As Long) As LongPtr

Private Declare PtrSafe Function RegQueryValueExLong Lib "advapi32.dll" _ ' _
  (ByVal hKey As Long, ByVal lpValueName As String, 'ByVal lpReserved As Long, lpType As Long, _
'lpData As Long, lpcbData As Long) As LongPtr

Private Const REG_SZ As Long = 1
Private Const REG_EXPAND_SZ As Long = 2
Private Const REG_BINARY As Long = 3
Private Const REG_DWORD As Long = 4

Public Sub GetRegistry_Value()
Dim RootKey As String
Dim Path As String
Dim RegEntry As String
Dim lasttime As String

RootKey = "HKEY_CURRENT_USER"

'Path = "software\microsoft\office\16.0\Excel"
'RegEntry = "ExcelName"

Path = "software\microsoft\office\16.0\excel\options"
RegEntry = "Open1"

'Path = "software\microsoft\office\excel\addins\COMExcelModelCover.MyConnect"
'RegEntry = "FriendlyName"

   Call GetRegistry(RootKey, Path, RegEntry)

End Sub

Private Function GetRegistry( _
ByVal Key As String, _
ByVal Path As String, _
ByVal ValueName As String) As String

' Reads a value from the Windows Registry

Dim hKey As Long

Dim lValueType As Long
Dim sResult As String
Dim lResultLen As Long
Dim ResultLen As Long
Dim x As LongPtr
Dim TheKey As Long

TheKey = -99

Select Case UCase(Key)
Case "HKEY_CLASSES_ROOT": TheKey = &H80000000
Case "HKEY_CURRENT_USER": TheKey = &H80000001
Case "HKEY_LOCAL_MACHINE": TheKey = &H80000002
Case "HKEY_USERS": TheKey = &H80000003
Case "HKEY_CURRENT_CONFIG": TheKey = &H80000004
Case "HKEY_DYN_DATA": TheKey = &H80000005
End Select

' Exit if key is not found
If TheKey = -99 Then
    GetRegistry = "Not Found"
    Exit Function
End If

If RegOpenKeyA(TheKey, Path, hKey) <> 0 Then
    MsgBox "cannot find/open key"
    Exit Function
End If

lValueType = REG_SZ
sResult = Space(150)
lResultLen = 150

x = RegQueryValueExString(hKey, ValueName, 0&, lValueType, sResult, lResultLen)
    
   Call RegCloseKey(hKey)

    If (x = 2) Then
        Call MsgBox("Cannot find the file specified")
        Exit Function
    End If

  Call MsgBox("'" & VBA.Left(VBA.Trim(sResult), lResultLen - 1) & "'")

End Function

Private Declare Function RegOpenKeyA Lib "ADVAPI32.DLL" _ 
    (ByVal hKey As Long, ByVal sSubKey As String, _
    ByRef hkeyResult As Long) As Long

Private Declare Function RegCloseKey Lib "ADVAPI32.DLL" _
    (ByVal hKey As Long) As Long

Private Declare Function RegSetValueExA Lib "ADVAPI32.DLL" _
    (ByVal hKey As Long, ByVal sValueName As String, _
    ByVal dwReserved As Long, ByVal dwType As Long, _
    ByVal sValue As String, ByVal dwSize As Long) As Long

Private Declare Function RegCreateKeyA Lib "ADVAPI32.DLL" _
    (ByVal hKey As Long, ByVal sSubKey As String, _
    ByRef hkeyResult As Long) As Long

Private Declare Function RegQueryValueExA Lib "ADVAPI32.DLL" _
    (ByVal hKey As Long, ByVal sValueName As String, _
    ByVal dwReserved As Long, ByRef lValueType As Long, _
    ByVal sValue As String, ByRef lResultLen As Long) As Long

Sub UpdateRegistryWithTime() 
    RootKey = "hkey_current_user"
    Path = "software\microsoft\office\9.0\excel\LastStarted"
    RegEntry = "DateTime"
    RegVal = Now()
    LastTime = GetRegistry(RootKey, Path, RegEntry)
    Select Case LastTime
        Case "Not Found"
            Msg = "This routine has not been executed before."
        Case Else
            Msg = "This routine was lasted executed: " & LastTime
    End Select
    Msg = Msg & Chr(13) & Chr(13)
    
    Select Case WriteRegistry(RootKey, Path, RegEntry, RegVal)
        Case True
            Msg = Msg & "The registry has been updated with the current date and time."
        Case False
            Msg = Msg & "An error occured writing to the registry..."
    End Select
    MsgBox Msg, vbInformation, "Registry Demo"
End Sub

Private Function GetRegistry(Key, Path, ByVal ValueName As String) 
' Reads a value from the Windows Registry

    Dim hKey As Long
    Dim lValueType As Long
    Dim sResult As String
    Dim lResultLen As Long
    Dim ResultLen As Long
    Dim x, TheKey As Long

    TheKey = -99
    Select Case UCase(Key)
        Case "HKEY_CLASSES_ROOT": TheKey = &H80000000
        Case "HKEY_CURRENT_USER": TheKey = &H80000001
        Case "HKEY_LOCAL_MACHINE": TheKey = &H80000002
        Case "HKEY_USERS": TheKey = &H80000003
        Case "HKEY_CURRENT_CONFIG": TheKey = &H80000004
        Case "HKEY_DYN_DATA": TheKey = &H80000005
    End Select
    
' Exit if key is not found
    If TheKey = -99 Then
        GetRegistry = "Not Found"
        Exit Function
    End If

    If RegOpenKeyA(TheKey, Path, hKey) <> 0 Then _
        x = RegCreateKeyA(TheKey, Path, hKey)
    
    sResult = Space(100)
    lResultLen = 100
    
    x = RegQueryValueExA(hKey, ValueName, 0, lValueType, _
    sResult, lResultLen)
        
    Select Case x
        Case 0: GetRegistry = Left(sResult, lResultLen - 1)
        Case Else: GetRegistry = "Not Found"
    End Select
    
    RegCloseKey hKey
End Function

Private Function WriteRegistry(ByVal Key As String, _ 
    ByVal Path As String, ByVal entry As String, _
    ByVal value As String)
    
    Dim hKey As Long
    Dim lValueType As Long
    Dim sResult As String
    Dim lResultLen As Long
   
    TheKey = -99
    Select Case UCase(Key)
        Case "HKEY_CLASSES_ROOT": TheKey = &H80000000
        Case "HKEY_CURRENT_USER": TheKey = &H80000001
        Case "HKEY_LOCAL_MACHINE": TheKey = &H80000002
        Case "HKEY_USERS": TheKey = &H80000003
        Case "HKEY_CURRENT_CONFIG": TheKey = &H80000004
        Case "HKEY_DYN_DATA": TheKey = &H80000005
    End Select
    
' Exit if key is not found
    If TheKey = -99 Then
        WriteRegistry = False
        Exit Function
    End If

' Make sure key exists
    If RegOpenKeyA(TheKey, Path, hKey) <> 0 Then
        x = RegCreateKeyA(TheKey, Path, hKey)
    End If

    x = RegSetValueExA(hKey, entry, 0, 1, value, Len(value) + 1)
    If x = 0 Then WriteRegistry = True Else WriteRegistry = False
End Function

Sub TestIt() 
    RootKey = "hkey_current_user"
    Path = "software\microsoft\office\9.0\common\autocorrect"
    RegEntry = "path"
    MsgBox GetRegistry(RootKey, Path, RegEntry), vbInformation, _
        Path & "\RegEntry"
End Sub

Kernel32.dll

CloseHandle 
CopyMemory 
FileTimeToSystemTime 
GetCommandLine 
GetCurrentThreadId 
GetExitCodeProcess 
GetLocaleInfo 
GetSystemTime 
GetTempPath 
GetTempPathA 
GetTickCountUsed for timing a macro
GetVersionEx 
GlobalAlloc 
GlobalLock 
GlobalSize 
GlobalUnlock 
LocalFileTimeToFileTime 
Lstrcpy 
Lstrlen 
MultiByteToWideChar 
OpenProcess 
RtlMoveMemory 
RtlZeroMemory 
Sleep 
SystemTimeToFileTime 
WaitForSingleObject 
WideCharToMultiByte 
xLib 

CopyMemory

Private Declare PtrSafe Sub CopyMemory Lib "kernel32" _ 
    Alias "RtlMoveMemory" (ByVal lpDst As LongPtr, ByVal lpSrc As LongPtr, ByVal byteLength As Long)

GetCommandLine

Public Declare PtrSafe Function GetCommandLine Lib "kernel32" _ 
    Alias "GetCommandLineA" () As Long

GetCurrentThreadId

Private Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long 

GetLocaleInfo

Private Declare PtrSafe Function GetLocaleInfo Lib "kernel32" Alias "GetLocaleInfoA" ( _ 
    ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String, ByVal cchData As Long) As Long

GetSystemTime

Private Declare PtrSafe Sub GetSystemTime Lib "kernel32" (lpSystemTime As SYSTEMTIME) 

GetTempPath

Getting temp folder path:

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

GlobalUnlock

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

GlobalLock

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

GlobalAlloc

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

lstrcpy

Public Declare PtrSafe Function lstrcpy Lib "kernel32" _ 
    Alias "lstrcpyA" (ByVal lpString1 As String, ByVal lpString2 As Long) As LongPtr

lstrlen


Public Declare PtrSafe Function lstrlen Lib "kernel32" _ 
    Alias "lstrlenA" (ByVal lpString As LongPtr) As Long

xLib

Declare PtrSafe Sub xLib "Kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long) 

Public Sub TestPause()
    Dim start As Double
    start = Timer
    Sleep 8000 'Pause for 8 seconds
    Debug.Print "Paused for " & Format(Timer - start, "#,###.000") & " seconds"
End Sub

Shell32.dll

ShellExecute 
BrowseForFolder 
SHGetPathFromIDList 

ShellExecute

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

SHBrowseForFolder and SHGetPathFromIDList

These two functions are not compatible with 64 bit.

Declare Function SHBrowseForFolder Lib "shell32.dll" (lpBrowseInfo As BROWSEINFO) As Long 
Declare Function SHGetPathFromIDList Lib "shell32.dll" (ByVal pidl As Long, ByVal pszPath As String) As Long

If you are using these APIs to browse for a folder you should replace your code with this:

link - learn.microsoft.com/en-us/windows/win32/shell/shell-browseforfolder 
Enum vbShellGetFolderFlags
  BIF_RETURNONLYFSDIRS = &H1
  BIF_DONTGOBELOWDOMAIN = &H2
  BIF_STATUSTEXT = &H4
  BIF_RETURNFSANCESTORS = &H8
  BIF_EDITBOX = &H10
  BIF_VALIDATE = &H20
  BIF_NEWDIALOGSTYLE = &H40
  BIF_BROWSEINCLUDEURLS = &H80
  BIF_BROWSEFORCOMPUTER = &H1000
  BIF_BROWSEFORPRINTER = &H2000
  BIF_BROWSEINCLUDEFILES = &H4000
  BIF_SHAREABLE = &H8000
  BIF_SHOWALLOBJECTS = &H8
End Enum

Const BIF_DefaultOptions = BIF_EDITBOX Or BIF_VALIDATE Or BIF_SHOWALLOBJECTS Or BIF_STATUSTEXT Or BIF_NEWDIALOGSTYLE
Const BIF_BrowseFolder = BIF_RETURNONLYFSDIRS Or BIF_DefaultOptions

Public Sub Example_ShellGetFolder()
   Debug.Print ShellGetFolder("Select the folder")
End Sub

Public Function ShellGetFolder(Caption As String) As String
Dim objShell As Object
Dim objBrowse As Object

   On Error GoTo ErrorHandler
   Set objShell = CreateObject("Shell.Application")
   Set objBrowse = objShell.BrowseForFolder(&H0, Caption, BIF_BrowseFolder, Chr(0))

   ShellGetFolder = objBrowse.Self.Path
   Exit Function
ErrorHandler:
   MsgBox Err.Description
End Function

User32.dll

CallWindowProcA
CallNextHookEx
CloseClipboard
CreateWindow
EmptyClipboard
EnableWindow
EnumDisplayDevices
EnumDisplayMonitors
EnumDisplaySettings
FindWindow
FindWindowEx
GetAsyncKeyState
GetClassName
GetClipboardData
GetClipboardSequenceNumber
GetDC
GetForegroundWindow
GetParent
GetSysColor
GetSystemMetrics
GetWindow
GetWindowLongPtr
GetWindowRect
GetWindowText
GetWindowThreadProcessId
IsClipboardFormatAvailable
LockWindowUpdate
MonitorFromWindow
OpenClipboard
PostMessage
PutFocus
ReleaseDC
ScrollWindowEx
SetClipboardData
SetDlgItemText
SetForegroundWindow
SetWindowPos
ShowWindow

Private Type RECT 
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

CallNextHookEx

Private Declare PtrSafe Function CallNextHookEx Lib "USER32" _ 
    (ByVal hHook As LongPtr, ByVal nCode As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr

CloseClipboard

Private Declare PtrSafe Function CloseClipboard Lib "USER32" () As LongPtr 

EmptyClipboard

Private Declare PtrSafe Function EmptyClipboard Lib "USER32" () As Long 

EnumDisplayDevices

Private Declare PtrSafe Function EnumDisplayDevices Lib "USER32" Alias "EnumDisplayDevicesW" _ 
   (ByVal lpDevice As LongPtr, ByVal iDevNum As Long, ByRef lpDisplayDevice As DISPLAY_DEVICEW, ByVal dwFlags As Long) As Long

EnumDisplayMonitors

Private Declare PtrSafe Function EnumDisplayMonitors Lib "USER32" _ 
   (ByVal hdc As Long, lprcClip As Any, ByVal lpfnEnum As LongPtr, dwData As Long) As Long

EnumDisplaySettings

Private Declare PtrSafe Function EnumDisplaySettings Lib "USER32" Alias "EnumDisplaySettingsA" _ 
   (ByVal lpszDeviceName As String, _
    ByVal iModeNum As Long, _
    lpDevMode As DEVMODE) As LongPtr

FindWindow

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

FindWindowEx

Private Declare PtrSafe Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" ( _ 
    ByVal hWnd1 As Long, _
    ByVal hWnd2 As Long, _
    ByVal lpsz1 As String, _
    ByVal lpsz2 As String _
) As Long

GetAsyncKeyState

link - cpearson.com/excel/keytest.aspx 

Detect Key Stroke

Private Declare PtrSafe Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer 

Private Const VK_F9 = &H78

Sub WaitUntilF9Key()
Do Until GetAsyncKeyState(VK_F9)
    DoEvents
Loop
MsgBox "Hello World"
End Sub

GetClipboardSequenceNumber

Private Declare PtrSafe Function GetClipboardSequenceNumber Lib "USER32" () As Long 

GetMonitorInfo

link - docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmonitorinfoa

Private Declare PtrSafe Function GetMonitorInfo Lib "USER32" Alias "GetMonitorInfoA" _ 
   (ByVal hMonitor As LongPtr, _
    ByRef lpMI As MONITORINFOEX) As Boolean

Private Const MONITOR_CCHDEVICENAME As Long = 32 'MONITORINFOEX.szDevice: device name fixed length

Private Type MONITORINFOEX
    cbSize As Long
    rcMonitor As RECT
    rcWork As RECT
    dwFlags As Long
    szDevice As String * MONITOR_CCHDEVICENAME
End Type

GetSysColor

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

GetSystemMetrics

link - docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics 
Private Declare PtrSafe Function GetSystemMetrics Lib "USER32" _
   (ByVal nIndex As Long) As Long

GetWindowLong

link - docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlonga 
Private Declare PtrSafe Function GetWindowLong Lib "USER32" _
    Alias "GetWindowLongA" ( _
    ByVal Hwnd As LongPtr, _
    ByVal nIndex As Long) As Long

#If Win64 Then
    Declare PtrSafe Function GetWindowLongPtr Lib "USER32" Alias "GetWindowLongPtrA" _
      (ByVal Hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
'https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptra
    Declare PtrSafe Function SetWindowLongPtr Lib "USER32" Alias "SetWindowLongPtrA" _
      (ByVal Hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
'https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlongptra
#Else
    Declare PtrSafe Function GetWindowLongPtr Lib "USER32" Alias "GetWindowLongA" _
      (ByVal Hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
    Declare PtrSafe Function SetWindowLongPtr Lib "USER32" Alias "SetWindowLongA" _
      (ByVal Hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
#End If

GetWindowRect

Private Declare PtrSafe Function GetWindowRect Lib "USER32" _ 
   (ByVal Hwnd As LongPtr, _
    lpRect As RECT) As Long

LockWindowUpdate

Private Declare PtrSafe Function LockWindowUpdate Lib "USER32" _ 
   (ByVal hwndLock As Long) As Long

MonitorFromWindow

Public Declare PtrSafe Function MonitorFromWindow Lib "USER32" _ 
   (ByVal Hwnd As LongPtr, _
    ByVal dwFlags As Long) As LongPtr

Public Const MONITOR_DEFAULTTONULL As Long = 0 'dwFlags: Returns NULL

OpenClipboard

Private Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As Long 

Putfocus

Private Declare PtrSafe Function Putfocus Lib "USER32" Alias "SetFocus" ( _ 
        ByVal Hwnd As LongPtr) As LongPtr

ScrollWindowEx

Private Declare PtrSafe Function ScrollWindowEx Lib "USER32" _ 
   (ByVal Hwnd As LongPtr, _
    ByVal dx As Long, _
    ByVal dy As Long, _
    lprcScroll As Any, _
    lprcClip As Any, _
    ByVal hrgnUpdate As LongPtr, _
    lprcUpdate As Any, _
    ByVal fuScroll As Long) As Long

Const SW_SCROLLCHILDREN = &H1
Const SW_INVALIDATE = &H2
Const SW_ERASE = &H4

SetClipboardData

Private Declare PtrSafe Function SetClipboardData Lib "USER32" _ 
   (ByVal wFormat As LongPtr, ByVal hMem As LongPtr) As LongPtr

SetDlgItemText

Private Declare PtrSafe Function SetDlgItemText Lib "USER32" Alias "SetDlgItemTextA" _ 
    (ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long, ByVal lpString As String) As Long

SetForegroundWindow

Public Declare PtrSafe Function SetForegroundWindow Lib "USER32" ( _ 
    ByVal Hwnd As LongPtr) As Long

SetWindowLong

link - docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowlonga 
Private Declare PtrSafe Function SetWindowLong Lib "USER32" _
    Alias "SetWindowLongA" ( _
    ByVal Hwnd As LongPtr, _
    ByVal nIndex As Long, _
    ByVal dwNewLong As Long) As Long

SetWindowPos

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

SetWindowsHookEx

Private 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

ShowWindow

link - docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow 
Private Declare PtrSafe Function ShowWindow Lib "USER32" _
   (ByVal Hwnd As LongPtr, _
    ByVal nCmdSHow As Long) As Long

UnhookWindowsHookEx

Private Declare PtrSafe Function UnhookWindowsHookEx Lib "USER32" _ 
    (ByVal hHook As LongPtr) As Long

© 2026 Better Solutions Limited. All Rights Reserved. © 2026 Better Solutions Limited TopPrevNext