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:
Greetings again,

My shortest/partial answer is that you are rushing through the code, and while that is never a great idea, stuff can go BOOM! a lot harder when using API. I do not say this to be impolite whatsoever; simply to point out that we want do be sure what we are doing before chucking the wrong thing at a library.

Here are your declared functions from post # 10 tidied up a bit:


Rich (BB code):
Option Explicit


Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, _
                                                                          ByVal lpWindowName As String) As LongPtr
  
    
#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
    
    Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" _
                              Alias "SetWindowLongA" (ByVal hwnd As LongPtr, _
                                                      ByVal nIndex As Long, _
                                                      ByVal dwNewLong As LongPtr) As LongPtr
  #Else 
    
    Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _
                              Alias "GetWindowLongA" (ByVal hwnd As LongPtr, _
                                                      ByVal nIndex As Long) As LongPtr
    
    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) As Long
#End If


Const WS_SYSMENU = &H80000
Const GWL_STYLE = (-16)

Taking your last question first: Running 64 in 64 bit O/S but 32 bit Excel, I get an error here:...with GetWindowLong highlighted.

Well, if you look through your declarations, there's no such function to be called. Rather, there's GetWindowLongPtr.


I am not sure about the FindWindow issue, but hwnd should be declared as LongPtr, because that is what you have FindWindow returning. Does that make sense?

Mark
 
Upvote 0

Excel Facts

Remove leading & trailing spaces
Save as CSV to remove all leading and trailing spaces. It is faster than using TRIM().
Mark,

Thanks for your help, you can be as impolite as you like, all I want is for it to work, :)

Yes your comments do make sense and I have finally managed to get it to work for a 32 bit and 64 bit Excel!

The bit (excuse the pun!) to change was the declarations from Long to LongPtr for hwnd and lStyle, so here's the full code:

Code:
Sub TidyForm()
    Dim hwnd As LongPtr, lStyle As LongPtr
     
    hwnd = FindWindow(lpClassName:="ThunderDFrame", _
                      lpWindowName:=MyForm.Caption)
     
    lStyle = GetWindowLongPtr(hwnd:=hwnd, _
                           nIndex:=GWL_STYLE)
     
    Call SetWindowLongPtr(hwnd:=hwnd, _
                       nIndex:=GWL_STYLE, _
                       dwNewLong:=lStyle And Not WS_SYSMENU)
     
End Sub

This is where the buck stops (if you see my earlier threads, my users have requested I create an all in one program, to work on PCs and Macs), which is almost near impossible, as RoryA commented.

Thanks to you both for helping me out here.
 
Last edited:
Upvote 0
I am glad you got it working:)

Is there any real chance of any of the users having an Excel version earlier than 2010?

Mark
 
Upvote 0
I really can't say, as my program is not used internally but externally and therefore I don't know what the customers have.

What I do know is it won't work on 2003 (as it contains more than 255 worksheets, long story)!
 
Upvote 0
Okay. Well, at least as I read it, if any of the users have Excel 2007, then I believe that is VBA6, as I believe VBA7 came out in 2010.

See HERE

"Introducing the VBA 7 Code Base

VBA 7 is a new code base, replacing the earlier version of VBA. VBA 7 exists for both the 32-bit and 64-bit versions of Office 2010. It provides two conditional compilation constants: VBA7 and Win64. The VBA7 constant helps ensure the backward compatibility of your code by testing whether your application is using VBA 7 or the previous version of VBA."

If that turns out the case, you may need to include conditional declarations for that. If so, I believe it would be along the lines of:

Rich (BB code):
Option Explicit
  
#If  VBA7 Then
  
  Private Declare PtrSafe Function FindWindow Lib "user32" _
                            Alias "FindWindowA" (ByVal lpClassName As String, _
                            ByVal lpWindowName As String) As LongPtr
  
  
  #If  Win64 Then
    
    Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _
                              Alias "GetWindowLongPtrA" (ByVal hWnd As LongPtr, _
                                                         ByVal nIndex As Long) As LongPtr
    
    Private Declare PtrSafe Function SetWindowLongPtr Lib "user32" _
                              Alias "SetWindowLongA" (ByVal hWnd As LongPtr, _
                                                      ByVal nIndex As Long, _
                                                      ByVal dwNewLong As LongPtr) As LongPtr
  #Else 
    
    Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _
                              Alias "GetWindowLongA" (ByVal hWnd As LongPtr, _
                                                      ByVal nIndex As Long) As LongPtr
    
    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 PtrSafe Function FindWindow Lib "user32" _
                            Alias "FindWindowA" (ByVal lpClassName As String, _
                                                 ByVal lpWindowName As String) As Long
  
  
  Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _
                            Alias "GetWindowLongA" (ByVal hWnd As Long, _
                                                    ByVal nIndex As Long) As Long
  
  Private Declare Function SetWindowLongPtr Lib "user32" _
                    Alias "SetWindowLongA" (ByVal hWnd As Long, _
                                            ByVal nIndex As Long) As Long
#End If
  
Const WS_SYSMENU = &H80000
Const GWL_STYLE = (-16)

In case we need to handle VBA6, with the lack of LongPtr, then we would also need to conditionally declare the appropriate variables, like:

Rich (BB code):
Sub TidyForm()
If VBA7 Then
Dim hWnd As LongPtr, lStyle As LongPtr
Else
Dim hWnd As Long, lStyle As Long
End If
     
    '...remainder of code...


End Sub


I am getting a bit tired, so please test in a junk copy of your workbook if desired.

Mark
 
Upvote 0
SetWindowLong and GetWindowLong have one of the most confusing declarations .. Basically, there are 3 deifferent declarations depending on the VBA/OFFICE version , the VBA/Office Bitness and the Operating System Bitness.

[TABLE="width: 1413"]
<tbody>[TR]
[TD]OS Bitness[/TD]
[TD]Office Version[/TD]
[TD]Office Bitness[/TD]
[TD] API Declaration[/TD]
[/TR]
[TR]
[TD]32[/TD]
[TD]2007 and Before (VBA6)[/TD]
[TD]32[/TD]
[TD]Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long[/TD]
[/TR]
[TR]
[TD]64[/TD]
[TD]2007 and Before (VBA6)[/TD]
[TD]32[/TD]
[TD]Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long[/TD]
[/TR]
[TR]
[TD]32[/TD]
[TD]2010 and Later (VBA7)[/TD]
[TD]32[/TD]
[TD]Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long[/TD]
[/TR]
[TR]
[TD]64[/TD]
[TD]2010 and Later (VBA7)[/TD]
[TD]64[/TD]
[TD]Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr[/TD]
[/TR]
</tbody>[/TABLE]


Also, I like to always use uniform generic API name Aliases for consistency and to remove unnecessary confusion .. So if the official declaration says SetWindowLongPtr, I change it to SetWindowLong so the API function name is consistent throughout subsequent code regardless of the user's platform.

So in your case, I would write the code as follows : (Notice the necessary different variable declarations inside the "
TidyForm" routine using conditional compilation as well)

Code:
[URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If]#If[/URL]  VBA7 Then [COLOR=#008000]' (OFFICE 2010 AND LATER - Either 32bit or 64bit Editions)[/COLOR]

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

    [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If]#If[/URL]  Win64 Then [COLOR=#008000]' (64bit OS) AND (64bit Office)[/COLOR]
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As LongPtr
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
    [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else]#Else[/URL]  [COLOR=#008000]' (32bit OS) AND (32bit Office)[/COLOR]
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As Long
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
     [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End]#End[/URL]  If

[URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else]#Else[/URL]  [COLOR=#008000]' (OFFICE 2007 AND BEFORE)  .. Both (32bit OS) AND (32bit Office)[/COLOR]
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    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) As Long
[URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End]#End[/URL]  If

Private Const WS_SYSMENU = &H80000
Private Const GWL_STYLE = (-16)
Private pMyForm As UserForm
    
Public Property Get MyForm() As UserForm
    Set MyForm = pMyForm
End Property

Public Property Set MyForm(ByVal MForm As UserForm)
    Set pMyForm = MForm
End Property

Sub TidyForm()
    
   [COLOR=#008000] '============= Variable Declarations==============================[/COLOR]
    
    [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If]#If[/URL]  VBA7 Then[COLOR=#008000] '(OFFICE 2010 AND LATER - Either 32bit or 64bit Editions)[/COLOR]
        
        [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=If]#If[/URL]  Win64 Then[COLOR=#008000] '(64bit OS) AND (64bit Office)[/COLOR]
            Dim hwnd As LongPtr, lStyle As LongPtr, lNewStyle As LongPtr
        [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else]#Else[/URL]  [COLOR=#008000]'(32bit OS) AND (32bit Office)[/COLOR]
            Dim hwnd As LongPtr, lStyle As Long, lNewStyle As Long
        [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End]#End[/URL]  If
   
    [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=Else]#Else[/URL]  [COLOR=#008000]'(OFFICE 2007 AND BEFORE)  .. Both (32bit OS) AND (32bit Office)[/COLOR]
        Dim hwnd As Long, lStyle As Long, lNewStyle As Long
    [URL=https://www.mrexcel.com/forum/usertag.php?do=list&action=hash&hash=End]#End[/URL]  If
    
    [COLOR=#008000]'===================================================================[/COLOR]
         
    hwnd = FindWindow(lpClassName:="ThunderDFrame", _
                      lpWindowName:=MyForm.Caption)
     
    lStyle = GetWindowLong(hwnd:=hwnd, _
                           nIndex:=GWL_STYLE)
                           
    lNewStyle = lStyle And Not WS_SYSMENU
     
    Call SetWindowLong(hwnd:=hwnd, _
                       nIndex:=GWL_STYLE, _
                       dwNewLong:=llNewStyle)
     
End Sub


 
Upvote 0
Another thing you can do as well in order to remove clutter from the sub-routines is that instead of declaring the local variables inside of the sub-routines using messy Conditional Compilation clauses, you can declare them as module level variables so they can be conviniently wrapped along with the API declarations.
 
Upvote 0
@JAAFAR:

Thank you very much for the corrections Jaafar.:bow: If I read through that correctly, you corrected:

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 SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
    #Else   ' (32bit OS) AND (32bit Office)
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As Long
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
     #End If
#Else   ' (OFFICE 2007 AND BEFORE)  .. Both (32bit OS) AND (32bit Office)
#End If
I understand why I goofed the LongPtr(s) in where Long(s) needed to stay, but missing SetWindowLongPtrA under Win64...:banghead: ARGH!

Just for clarity's sake, shouldn't your comment for the first #Else read ' (32 or 64 bit OS) AND (32bit Office) ?

Thanks again,

Mark
 
Upvote 0
Mark,

Obviously I wasn't aware you goofed at all because I copied and pasted your code into both 64 bit and 32 bit Excel 2013, running off Windows 7 64 bit and both ran fine!

Jaafar,

Thanks for your corrections.
 
Last edited:
Upvote 0

Forum statistics

Threads
1,224,827
Messages
6,181,197
Members
453,021
Latest member
pingpong7117

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