Does API style code need to be in separate modules?

JMongi

Active member
Local time
Today, 16:21
Joined
Jan 6, 2021
Messages
802
I've reimplemented some code written by a variety of people smarter than me including some VBA that ties into Windows API calls. I'm not going to pretend to understand every nuance, but I do know that the structure of these API code blocks are different than defining functions and subs. Here's an example:

Code:
Option Compare Database
Option Explicit

#If VBA7 Then
       Dim handleW1 As LongPtr
#Else
        Dim handleW1 As Long
#End If
    
'###############################################
#If VBA7 Then 'PtrSafe
    Private Declare PtrSafe Function FindWindowA Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    Private Declare PtrSafe Function SetWindowPos Lib "user32" (ByVal handleW1 As LongPtr, ByVal handleW1InsertWhere As LongPtr, ByVal w As Long, _
        ByVal X As Long, ByVal Y As Long, ByVal Z As Long, ByVal wFlags As Long) As Long
        
#Else '32-bit Office
    Private Declare Function FindWindowA Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function SetWindowPos Lib "user32" (ByVal handleW1 As Long, ByVal handleW1InsertWhere As Long, ByVal w As Long, _
        ByVal X As Long, ByVal Y As Long, ByVal z As Long, ByVal wFlags As Long) As Long
#End If
'###############################################
 
Const TOGGLE_HIDEWINDOW = &H80
Const TOGGLE_UNHIDEWINDOW = &H40

Public strProc As String 'used in error code
Public blnShowTaskbar As Boolean
Public blnShowNavPane As Boolean

Then there are some functions defined afterward to help interface with this API code. My question is can I have more than one API call in a module? Something like this:

Code:
Option Compare Database
Option Explicit

'-------------------ACCESS WINDOW VISIBILITY API START-------------------

'************ Code Start **********
' This code was originally written by Dev Ashish.
' It is not to be altered or distributed,
' except as part of an application.
' You are free to use it in any application,
' provided the copyright notice is left unchanged.
'
' Code Courtesy of Dev Ashish

'Additional API code by Daolix

'/* ShowWindow() Commands */

Global Const SW_HIDE = 0
Global Const SW_SHOWNORMAL = 1
Global Const SW_SHOWMINIMIZED = 2
Global Const SW_SHOWMAXIMIZED = 3
Global Const SW_SHOW = 5
Public blnShowWindow As Boolean

'###############################################
#If VBA7 Then
    Declare PtrSafe Function ShowWindow Lib "user32" _
        (ByVal hWnd As LongPtr, ByVal nCmdShow As Long) As Long
        
    Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
        (ByVal hWnd As LongPtr, ByVal nIndex As Long) As Long
            
    Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
        (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    
    Declare PtrSafe Function GetParent Lib "user32" _
        (ByVal hWnd As LongPtr) As LongPtr
        
#Else  '32-bit Office
    Declare Function ShowWindow Lib "user32" _
        (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
        
    Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
        (ByVal hWnd As Long, ByVal nIndex As Long) As Long
            
    Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
        (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
        
    Declare Function GetParent Lib "user32" _
        (ByVal hWnd As Long) As Long
#End If
'###############################################
        
'/* Window field offsets for Set/GetWindowLong() */
Public Const GWL_EXSTYLE       As Long = -20

'/* Extended Window Styles */
Public Const WS_EX_APPWINDOW   As Long = &H40000

'-------------------ACCESS WINDOW VISIBILITY API END------------------

'------------------ACCESS FORM MOVE WITH MOUSE DOWN API START------------------

Public Const WM_NCLBUTTONDOWN = &HA1
Public Const HT_CAPTION = &H2

'===========================================================
'Usage with form mouse down event e.g.
'Private Sub FormHeader_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
 '  X = ReleaseCapture()
 '  X = SendMessage(Me.HWnd, WM_NCLBUTTONDOWN, HT_CAPTION, 0)
'End Sub
'===========================================================

#If VBA7 Then
    Public Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As LongPtr, _
        ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
    
    Public Declare PtrSafe Function ReleaseCapture Lib "user32.dll" () As Long
#Else
    Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, _
        ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
    
    Public Declare Function ReleaseCapture Lib "user32.dll" () As Long
#End If
'---------------------ACCESS FORM MOVE WITH MOUSE DOWN API END--------------------
 
Hi. I'm no expert on API either, but I think you can do that as long as there are no name conflicts. It might be safer to keep them separate though. Why are you considering putting them all together? Best way to find out is to give it a try.
 
The only reasonable requirement for API definitions is that they belong in a general module. Whether one of their own or merged into another of your general modules? Your call, whichever way best floats your boat.
 
I wish Access recognized the function definitions a little bit cleaner when API calls are used. But, thanks for the info.
 
I recognise that API code....

Its largely personal preference but I think one approach is far better ;)

My preference is to put all the API calls relevant to a particular module in that specific module. That helps me keep track of which APIs are used by specific procedures. As many of my modules are used in a large number of databases, I store them in a module code library.
This makes it much easier to transfer code to new databases as required

There is nothing to stop you putting all APIs together in a separate module, modAPI. However that would make it more difficult to transfer working module code to a new database unless you copied the ENTIRE modAPI as well. This would result in many unused APIs being imported as well.
 
@isladogs - Always lurking....heh.

I think part of the problem is that I'm NOT using all the modules, or at least, not all of the API calls from your sample database. that I copied over back in the day. I think I've layered up on myself and that's why sometimes it doesn't quite work perfectly. I'm simultaneously making sure my code is well organized and making sure I understand some of this code I am reimplementing.

I think mainly I just need to rename some modules so that it was more clear to me what was in them when I'm looking to investigae some particular code.
 
@JMongi
:ROFLMAO:

Not sure any more which sample database that was from ... partly for the reasons I mentioned..
This is a screenshot of some of the modules in my code library to show how I organise things...:

1628017687997.png


It works for me but may not be appropriate for everyone
 
Well, I was just about to hijack my own thread to ask Colin a few questions when I had a "duh" moment. I remember another time I didn't have the latest version of the sample DB. So, I went to Colin's site and "duh" there are notes on how to implement the functions (instead of me reverse engineering it from your form). While, head smacker there.
 
Glad to have helped...even if I can't remember which sample database you're referring to. 😉
 
Just to clarify how much space an API declaration takes up...

Using an API definition doesn't store a lot of code, maybe just an entry in a behind-the-scenes subroutine dispatch table, often called a "vector table" in some compiled languages. (Hint: Look at a form's Properties - specifically, the Entry list - which is another vector table.) An API definition is just like a named constant. The code of the API is in a .DLL file - which ISN'T in the .ACCDB file. It's a .DLL file because it is a Dynamically Linked Library for which the Windows "Image Loader" just "diddles" the memory management pointers dynamically to link the code to yours (or, technically, link YOUR code to it.) An API call is to actual code as a TableDef is to Externally Linked Tables. The .ACCDB doesn't contain the linked code or the linked table. Just some pointers that let you find either of them.

Therefore, keep the API declarations separate for your convenience... but if you keep them all together, your .ACCDB file is not going to get overwhelmed by the memory requirements unless you have hundreds - or even thousands - of API calls defined.

It still depends on your preferences, but it would be unlikely that a "keep-together" decision would affect resources seriously. Might affect your head by trying to remember what you defined in that all-in-one module, but not a big issue for Access.
 

Users who are viewing this thread

Back
Top Bottom