Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

SetWindowLong and GWL_WNDPROC in Win2000 1

Status
Not open for further replies.

NipsMG

Programmer
Dec 27, 2000
215
US
Hi everyone..

I've recently switched my development machine from Win98 to Win2k.

Since doing so, however, I have been having LARGE amouts of trouble subclassing window messages. I consistantly get return values of 0 every time I try to get or set the window procedure of any window outside the development environment.

Upon reading the MSDN Library's entry for SetWindowLong w/ GWL_WNDPROC I found this:

Windows NT/2000: You cannot change this attribute if the window does not belong to the same process as the calling thread.

However, in MSDN Library's entry for SetWindowLongPtr, it does not specify this restriction next to GWLP_WNDPROC.

In MSDN Library, it says GetWindowLongPointer and its constants are declared in WinUser.h, however, after opening WinUser.h and looking for the Declarations, I was unable to find them.

(I'm using MS VS6 SP3).

Does anyone know:
A.) If using SetWindowLongPtr and GWLP_WNDPROC will get and set window procedures where SetWindowLong and GWL_WNDPROC will not.. And
B.) What the declarations are of SetWindowLongPtr, GetWindowLongPtr and the values for any GWLP_ constants?

Thanks, I appreacate all your help.. :)

--Michael P. Gerety
 
According to the Platform SDK:
The SetWindowLongPtr function changes an attribute of the specified window. The function also sets a value at the specified offset in the extra window memory.

This function supersedes the SetWindowLong function. To write code that is compatible with both 32-bit and 64-bit versions of Windows, use SetWindowLongPtr.


Since VB 6 doesn't know about 64-bit addresses, I would suggest you continue using SetWindowLong until you make the switch to VB.NET. BTW, you should switch to SP4 as soon as you can - it has better support for Windows 2000.

Since you're getting 0's when you try to subclass windows outside the development environment (I assume you're trying to subclass windows that aren't part of your project), it sounds like the comment in MSDN is correct. I think this is a result of MS's beefing up security in Windows 2000 over NT4.

Maybe if you posted some more about how you're using it?

Chip H.



 
Well, here's a perfect example....
This retreives the class name exactly as it should, but GetWindowLong returns 0 then trying to retrieve the WNDPROC.

Code:
Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Public lNotepadHwnd As Long
Public Const GWL_WNDPROC = -4

Public Sub Main()
    EnumWindows AddressOf EnumWindowsProc, 0&
    MsgBox lNotepadHwnd
End Sub

Public Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) As Boolean
    Dim sClass As String, Result As Long
    
    'Initialize class String, Get Class name & trim
    sClass = Space(100)
    Result = GetClassName(hwnd, sClass, 100)
    sClass = Trim(sClass)
    'If we found the Notepad window, get the window handle
    'and put it in global variable lNotepadHwnd
    If InStr(sClass, &quot;Notepad&quot;) <> 0 Then
        lNotepadHwnd = GetWindowLong(hwnd, GWL_WNDPROC)
        hwnd = 0
    End If
    If Not hwnd = 0 Then EnumWindowsProc = True Else EnumWindowsProc = False
End Function


Also, You mentioned that VB6 doesn't know 64 bit addresses.. however, upon investigation, I found out the GetWindowLongPtr function returns a 32 bit val in 32 bit environments, and 64 bit val in 64 bit environments... So it should still work correctly (plus they don't specify that it won't work in win2k for GWL_WNDPROC... unlike GetWindowLong)... however I have been unable to find a definition. MSDN Library suggests it's in User32.dll but when I declare it I get a &quot;DLL Entry Point not Found&quot; error ...

Any ideas anyone? (besides reverting back to Win9x)...
 
I did a search in my C:\Program Files\Microsoft Visual Studio\VC98\Include directory, and I was unable to find the prototype for this function either (and I have SP4 on Win2000Pro SP1). I suspect it's for Windows XP, or .NET when they come out later this year/early next year.

It's starting to sound like 2000 is simply not going to allow you to do this. Maybe Jeff Marler or Eric D. will join in the discussion and help out.

Chip H.
 
Hi,

I have the same problem with NT 4.0 service pack 4. In MSDN Library's entry for SetWindowLongPtr, it says:

&quot;The SetWindowLongPtr function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread.&quot;

I have tried to do that using AttachThreadInput API, but with no success. Does anyone know HOW could I subclass a window´s proc supposing it belongs to another thread?

Regards,

Aitor Agirre.
 
Aitor:

I have also seen an example using the AttachThreadInput API to do something similar..

I guess that Win2k and Win98 no longer allow the use of SetForegroundWindow to take the focus away from another application, so this guy used AttachThreadInput to achieve sort of the same thing we're trying to do also...

The example is at:


Looking for &quot;ForceFore.zip&quot;

I've tried to alter this code to work with subclassing, however I have been unsuccessful in getting handles on any windows outside of VB6's IDE..

Please take a look at it and let me know if you have any luck with it..

Thanks! :)

NipsMG
 

&quot;I have tried to do that using AttachThreadInput API, but with no success. Does anyone know HOW could I subclass a window´s proc supposing it belongs to another thread?&quot;



I have seen cases where the callback funciton MUST be a Win32 C++ DLL if the callback is for a window in another process (sorry . . . VB's ActiveX DLL won't work for this). This is specifically for the SetWindowsHookEx API, but it may also apply to AttachThreadInput as well.
I ahve not experienced the problem described earlier in this thread . . . let me look at my Win2K box and see if I can reproduce it . . .



- Jeff Marler B-)
 
Jeff...

Attach thread input doesn't use a callback.. :)

Code:
BOOL AttachThreadInput(
  DWORD idAttach,    // thread to attach
  DWORD idAttachTo,  // thread to attach to
  BOOL fAttach       // attach or detach
);

Hehe, I'm guessing you probably meant the SetWindowLong function instead. ;-)

Anyways... I'm 99.9 percent sure that the SetWindowLong API Does not require a C++ dll as the callback..

I've used it before, and can currently use it for windows in the current process thread.

If you figure anything out though, Please let me know.

Thanks.

--NipsMG

 
Actually, I was referring to the SetWindowsHookEx (a function that I use a lot). that one does require a callback and for it to monitor ALL processes (i.e. global) it needs to be in a C++ DLL.
I've not used to AttachThreadInput much, but I'm always open to learning a new API! :) I'll take a look at this and see if I can offer any input.

- Jeff Marler B-)
 
Jeff...

My problem could actually be solved(Well, at least for the current application I'm working on)
if I were able to find some C++ source for a win32 dll that would implement a system wide hook searching for window creation and dumped the messages back to me through a callback function that I could implement in VB..

Got any source for something like that? (or a resource I could look at?)

--NipsMG
 
That is normally how I would do it and I already have code that works (using a system wide Hook) . . . however it is at home and I am in the office right now . . . I'll post it later. - Jeff Marler B-)
 
Just so you all know.... :)

I found a system wide hook dll IN VB (yes you have to specify the messages to look for.. but I'll just specify to look for them ALL... You declare an object of it WithEvents and you have an event for each window message fired (or I can probably have ONE event for ANY message fired.... i'll just have to alter the code..))

So I'm all set now..
Thanks again for everybody's help... I really appreciate it! :)


If you guys are interested in a link to it... post again and I'll try to figure out where I got it from.. :)

--NipsMG
 
What DLL was that? And does it come with VB or is it 3rd party? - Jeff Marler B-)
 
Jeff..

It's third party, BUT it was submitted to a free source site and has the VB source for the DLL and a demo project.. it's NICE. :)

Gimme a few to find the link and I'll post it here. :)

--NipsMG
 
Cool . . . I'll have to look at it. Seems like that are using a different API (RegisterShellHook) than the SetWindowsHookEx. And that DLL will monitor every event queue on the system (i.e. all processes)? - Jeff Marler B-)
 
Jeff:

Seems like it.. you however have to hardcode in the dll which messages to look for... but if you code for all of them... ;-)

(which is nice, because you can return &quot;WINDOW CREATED&quot; or &quot;WM_CREATE&quot; instead of returning &H1..) :)

--NipsMG
 
hmmm . . . interesting . . .
I grabbed the source code and saw that it is grabbing the API at ordinal #181 with no name (an alias is assigned in the API declaration). I ran dumpbin on Shell32.dll and found that the API at ordinal #181 has no name assigned to it (hence no way to track down any concrete information about the API). In addition to 181, I founc several other exported APIs with no names . . . Anyone have any idea how to go about finding out what these function do or getting some specs on them (beside stepping through the assembly code)? - Jeff Marler B-)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top