SetWindowLong API

tiredofit

Well-known Member
Joined
Apr 11, 2013
Messages
1,926
Office Version
  1. 365
  2. 2019
Platform
  1. Windows
Can someone please check if the following API conversion, taken from here:


is correct?

Rich (BB code):
#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 SetWindowLongPtr Lib "USER32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong  As Long) As Long 
 #End If

These lines are in red:

Rich (BB code):
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 SetWindowLongPtr Lib "USER32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong  As Long) As Long


Thanks
 
Last edited:
I meant his GetWindowLong, not Getwindow.
@tiredofit

GetWindowLong and GetWindowLongPtr are basically the same ... They are just name Aliases of the actual ANSI versions of the GetWindowLongPtrA and GetWindowLongA API functions

So don't worry as long as you declare them all as GetWindowLongPtr or all as GetWindowLong ... the same applies to SetWindowLong
 
Upvote 0

Excel Facts

How to total the visible cells?
From the first blank cell below a filtered data set, press Alt+=. Instead of SUM, you will get SUBTOTAL(9,)
@tiredofit

GetWindowLong and GetWindowLongPtr are basically the same ... They are just name Aliases of the actual ANSI versions of the GetWindowLongPtrA and GetWindowLongA API functions

So don't worry as long as you declare them all as GetWindowLongPtr or all as GetWindowLong ... the same applies to SetWindowLong



Sorry but I perhaps I wasn't very clear earlier.

Jan's declared his GetWindowLong as:

LongPtr
LongPtr
Long


Rich (BB code):
#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 GetWindowLongPtr Lib "USER32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long 
 #End   If


whereas you've declared them as:

LongPtr
Long
Long

Rich (BB code):
#If    VBA7 Then   ' (OFFICE 2010 AND LATER - Either 32bit or 64bit Editions)
    
    #If    Win64 Then  '(64bit OS) AND (64bit Office)
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
        
    #Else     '(32 or 64 bit OS) AND (32bit Office)
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As Long
        
     #End    If
#Else      ' (OFFICE 2007 AND BEFORE)  .. Both (32bit OS) AND (32bit Office)
     Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    
#End    If

and is therefore not consistent.
 
Last edited:
Upvote 0
Greetings tiredofit,

Only as Jaafar, Rory or another member with more of a tight grasp on this has not stopped in, let me see if I can answer...

Did you download Win32API_PtrSafe.txt? I provided you a link in post # 7 and would suggest you download this and find a copy of WIN32API.TXT as well. Plus start searching for what you can find in regards to Microsoft Windows API as accessed through VBn/VBA.

Anyways, if you look for either Get|Set(Window), you will find this:

NOTE: Example declarations only (GetClassLongPtr and SetClassLongPtr removed for clarity)
Rich (BB code):
#If  Win64 Then
Declare PtrSafe Function GetWindowLongPtr Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
Declare PtrSafe Function SetWindowLongPtr Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
#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


' 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
Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
#End  If

Let us compare these to what is in WIN32API.TXT (at least the version/copy as updated by Karl E. Peterson)
Rich (BB code):
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

The first thing one might notice is that only in the section under #If Win64 do we actually call different functions Get|Set(WindowLongPtrA). Quite frankly, Jaafar or Rory can probably speak authoritatively to this, but for me it would be a guess if we are accessing user32.dll under System32 rather than the user32 in sysWOW32 for these functions. (My guess would be yes)

Regardless, and specific to your question, if we look at the documention: GetWindowLong function we see that GetWindowLong returns a LONG (in C++ I believe?), and that if we look up what this type of LONG in Windows Data Types, we find this info:
A 32-bit signed integer.
The range is -2147483648 through 2147483647 decimal.
This type is declared in WinNT.h as follows:
typedef long LONG;

Now, we need to match that with something VBA has, lest we watch not-so-funny things happen when we throw bad stuff to a dll. (Simply put, when dealing with API, we are skipping the 'safeties' present in native VBA functions.) So looking at our available data types, we see that a (VBA) Long is defined as:

Long (long integer) 4 bytes (or 32-bits), range of -2,147,483,648 to 2,147,483,647

Presto! We have something we can safely pass to (or return from) the API function!

Now, as to using LongPtr instead, you can find a number of MSDN articles advising to use this whenever referring to a handle or pointer (in VBA7). This is because while LongPtr is not actually a true data type, it automatically casts itself to a (VBA) Long in 32-bit Excel, or a LomngLong if in 64-bit Excel.

Thus, I would not say that Jan Karel's decarations are a 'mistake' in any fashion, and in fact follow the general advisements from MSDN articles. Nor, in than manner in which we have structured our #If ...#Else ...#End If, would I find worry in using As Long for the return. After all, the LongPtr is going to evaluate to a Long in 32-bit.

I hope that all made sense,

Mark

PS. - Here are some links, all in no order...

GetWindowLong function (Windows)
GetWindowLongPtr function (Windows)
SetWindowLong function (Windows)
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644898(v=vs.85).aspx
https://en.wikipedia.org/wiki/C_data_types
https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/s3f49ktz.aspx
https://docs.microsoft.com/en-us/cpp/cpp/data-type-ranges
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384264(v=vs.85).aspx
https://msdn.microsoft.com/en-us/vb...64-bit-visual-basic-for-applications-overview
https://msdn.microsoft.com/en-us/vba/language-reference-vba/articles/longptr-data-type
https://bettersolutions.com/vba/numbers/longptr-data-type.htm
https://en.wikipedia.org/wiki/Two's_complement
https://en.wikipedia.org/wiki/Ones'_complement
https://msdn.microsoft.com/en-us/library/ee691831.aspx
 
Upvote 0
@GTO

Mark,

Thanks for taking the time to provide a lengthy explanation. I can't say I understand it all but it does make sense. I did download the doc and ploughed through it - a bit!

Perhaps you have explained my query already but if I can summarise in pseudo code:

Jan's version, is something like:

Rich (BB code):
If VBA7 AND Win64 Then Declare as LongPtr

If VBA AND NOT Win64 Then Declare as LongPtr

IF NOT VBA7 Then Declare as Long

whereas Jaafar's is:

Rich (BB code):
If VBA7 AND Win64 Then Declare as LongPtr

If VBA AND NOT Win64 Then Declare as Long

IF NOT VBA7 Then Declare as Long

You see my point, highlighting the difference between the two in red?
 
Last edited:
Upvote 0
@GTO

Mark,

Thanks for taking the time to provide a lengthy explanation. I can't say I understand it all but it does make sense. I did download the doc and ploughed through it - a bit!

Perhaps you have explained my query already but if I can summarise in pseudo code:

Jan's version, is something like:

Rich (BB code):
If VBA7 AND Win64 Then Declare as LongPtr

If VBA AND NOT Win64 Then Declare as LongPtr

IF NOT VBA7 Then Declare as Long

whereas Jaafar's is:

Rich (BB code):
If VBA7 AND Win64 Then Declare as LongPtr

If VBA AND NOT Win64 Then Declare as Long

IF NOT VBA7 Then Declare as Long
You see my point, highlighting the difference between the two in red?
My understanding is that they are both the same because LongPtr points to a Long in 32Bit office.
 
Upvote 0
@Mark.

The first thing one might notice is that only in the section under [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If]#If [/URL] Win64 do we actually call different functions Get|Set(WindowLongPtrA). Quite frankly, Jaafar or Rory can probably speak authoritatively to this, but for me it would be a guess if we are accessing user32.dll under System32 rather than the user32 in sysWOW32 for these functions. (My guess would be yes)

I am not sure what you mean exactly but as you know, 64 bit systems have two versions of the SetWindowLong function: SetWindowLong in the SysWOW64 folder for 32bit client applications and SetWindowLongPtr in the System32 folder for 64bit client applications .. in the case of #If win64, we have 64bit office application so it will look into the System32 folder for SetWindowLongPtr API.
 
Upvote 0

Forum statistics

Threads
1,224,827
Messages
6,181,197
Members
453,022
Latest member
RobertV1609

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top