Results 1 to 11 of 11

Thread: Why is there SetWindowLongA and SetWindowLongW in Windows API?

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Why is there SetWindowLongA and SetWindowLongW in Windows API?

    I generally program in VBA and hooking is not a big thing there. Lately I have been playing with hooking in VB6 and I noticed in the Windows API there is a SetWindowLongA and SetWindowLongW. I try to do everything I do in Unicode so I want to use the W version. When I look at Microsoft's documentation for each, it shows 3 parameters which are all passed ByVal and none of them relates to a string so the two calls look identical. Does anyone know why there is an "A" version and a "W" version?

    BTW, the same question is for functions SetWindowsHookExA and SetWindowsHookW.

    Thanks

  2. #2
    PowerPoster
    Join Date
    Jun 2012
    Posts
    2,375

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    Quote Originally Posted by MountainMan View Post
    I generally program in VBA and hooking is not a big thing there. Lately I have been playing with hooking in VB6 and I noticed in the Windows API there is a SetWindowLongA and SetWindowLongW. I try to do everything I do in Unicode so I want to use the W version. When I look at Microsoft's documentation for each, it shows 3 parameters which are all passed ByVal and none of them relates to a string so the two calls look identical. Does anyone know why there is an "A" version and a "W" version?

    BTW, the same question is for functions SetWindowsHookExA and SetWindowsHookW.

    Thanks
    If a window handle is ANSI, then use SetWindowLongA. If a window is Unicode (e.g. from a CreateWindowExW call) then use SetWindowLongW.

    It's certainly also possible to unicodify a window proc by using GetWindowLongA and GWL_WNDPROC and then re-apply with SetWindowLongW.

    You can use the IsWindowUnicode API to know if a window is ANSI or Unicode.

    But it's not so inconvinient/complicated as it sounds. You can use SendMessageW on an ANSI window without an issue. Windows will take care of the conversions.
    Last edited by Krool; Aug 7th, 2020 at 07:33 AM.

  3. #3
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    Quote Originally Posted by Krool View Post
    It's certainly also possible to unicodify a window proc by using GetWindowLongA and GWL_WNDPROC and then re-apply with SetWindowLongW.
    . . . and this changes the way keyboard messages for this specific window are "translated" by the OS, along with probably other internal changes needed to retrofit unicode support (long time ago).

    cheers,
    </wqw>

  4. #4
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    And, from VB6 (or VBA), when using the ...W version of API calls, you must always wrap your passed in strings (and string buffers) with the StrPtr() function to prevent conversion to ANSI (and the API String arguments must be declared as Long in the declaration). But it sounds like you're probably already aware of that one.

    EDIT: And just further commenting on what's already been said: Basically, I just always try and use the ...W version of the API functions, and let Windows worry about whether the window is ANSI or Unicode.

    EDIT2: For grins, here's an example:

    Code:
    
    Private Declare Function LoadLibraryExW Lib "kernel32" (ByVal lpLibFileName As Long, ByVal hFile As Long, ByVal dwFlags As Long) As Long
    
    [in a procedure]
    
        hHandle = LoadLibraryExW(StrPtr(sModule), 0&, 0&)
    
    ----------- versus ----------
    
    Private Declare Function LoadLibraryExA Lib "kernel32" (ByVal lpLibFileName As String, ByVal hFile As Long, ByVal dwFlags As Long) As Long
    
    [in a procedure]
    
        hHandle = LoadLibraryExA(sModule, 0&, 0&)
    
    Last edited by Elroy; Aug 7th, 2020 at 09:45 AM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  5. #5
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    A long time ago there was SetWindowLong(). Later on when NT came along it was split into SetWindowLongA() and SetWindowLongW() while Win9x only had SetWindowLongA().

    In C programs you normally defined the one you wanted as SetWindowLong() in a macro, so old programs needed minimal rewriting.

    Later in Win9x's life cycle it got the unicows.dll add-on library, which added W entrypoints for many calls. Eventually unicows.dll started shipping with Win9x (98SE maybe?) but before that later versions of IE installed it (maybe 4.1 or so?). The unicows adapter library had to translate text to ANSI then call the old A entrypoints in Win9x and then translate back to Unicode so there was some performance cost.

    NT was native Unicode, so the A entrypoints are slower, translating from then back to ANSI.

    Worse yet, in VB5 and 6 calling A entrypoints with any ByVal String argument involves two more translations to/from ANSI. That's a total of 4 for each String for each call on NT.
    Win2K was NT 5.0, XP was NT 5.1, Vista was NT 6.0, etc.

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2015
    Location
    Colorado USA
    Posts
    261

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    I use the W functions all the time too. I was just wondering why those particular functions had an A and a W version since the parameters did not involve strings.

  7. #7
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    The ones without any text arguments might do something else under the covers, for example call text-encoding sensitive procedures themselves or send different message values since those often come in both ANSI and Unicode forms.

    On Win9x it didn't matter, it was all ANSI. NT OSs can be a different story. To get the actual details you have to ask somebody like Raymond Chen.

  8. #8
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    Lots of "and... " posts, so I'll add another. I grouped Strings & UDTs below; even though Strings were talked about earlier.

    When using W type APIs, be very careful with any strings and UDTs (user-defined types) you pass to those APIs. Typically, strings are passed via StrPtr() and the API string parameters are "As Long" not "As String". Likewise, UDTs that contain strings are typically passed via VarPtr(UDT) and the API UDT parameters are "As Long" not "As [theUDTname]"

    You need to protect strings from being converted to ANSI when they are passed to W type APIs.
    Some UDTs can have members that are predefined for ANSI or unicode, i.e., array(0 to 31) when ANSI vs array(0 to 63) for unicode.

    I use the W functions all the time too. I was just wondering why those particular functions had an A and a W version since the parameters did not involve strings.
    As mentioned earlier, the structures returned by the API may be using strings or ANSI/Unicode specific values. For example, listview/treeviews return Long values in many WM_NOTIFY structures. The value of those Longs may be different when unicode is used vs ANSI.

    edited: Another thing to keep in mind is what an API call does. It calls a function inside a DLL. If the API has both a W and A version, likely two different functions. One function may be expecting 2-byte characters while the other isn't, maybe one is expecting a larger UDT than the other. Windows may be able to redirect/fix some improper calls to the wrong version, but maybe it's only smart enough for its own DLLs?
    Last edited by LaVolpe; Aug 7th, 2020 at 01:09 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  9. #9
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    Part of the complication comes from the hacks VB6 implements to try to make the transition to Unicode transparent.

    A "Declare" compiles to a bunch of code that tries to deal with the mismatch between old A entrypoints and VB's Unicode text. That's where the extra conversion-copying on the way in and back out comes from.

    Typelibs can often be used instead of Declares to bypass that and simplify things. They can often make some calls possible that might otherwise require gymnastics in your VB code.

    A lot of this might have eventually been washed away if VB had not been frozen at VB6.

  10. #10
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    Quote Originally Posted by dilettante View Post
    A lot of this might have eventually been washed away if VB had not been frozen at VB6.
    Yes, it would be nice if we had AsAnsi and AsUnicode keywords for these API declarations, much like the PtrSafe keyword in the VBA. For instance, something like:


    Code:
    
    Private Declare AsUnicode Function LoadLibraryExW Lib "kernel32" (ByVal lpLibFileName As String, ByVal hFile As Long, ByVal dwFlags As Long) As Long
    
    And then, we could make the calls without any conversion or worrying about StrPtr().

    But hey ho, that's just wishful thinking.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  11. #11
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Why is there SetWindowLongA and SetWindowLongW in Windows API?

    @Elroy, you could pass ANSI string parameters As Long.
    But who would want to make that their standard, As Long vs As String, for ANSI?

    Notice, parameters in both APIs are As Long
    Code:
    Private Declare Function SetWindowText Lib "user32.dll" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As Long) As Long
    Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As Long, ByVal cch As Long) As Long
    
    Private Sub Command1_Click()
        SetWindowText Me.hwnd, StrPtr(StrConv("Hello World", vbFromUnicode))
        
        Dim sCaption As String, lSize As Long
        sCaption = Space$(128)  ' half of what's required/desired
        lSize = GetWindowText(hwnd, StrPtr(sCaption), LenB(sCaption))
        MsgBox Left$(StrConv(sCaption, vbUnicode), lSize)
    End Sub
    oops, convert then get Left$ -- patched above.
    Last edited by LaVolpe; Aug 7th, 2020 at 02:40 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width