Page 1 of 2 12 LastLast
Results 1 to 40 of 42

Thread: Subclassing Class and Module...can anyone see whats wrong???

  1. #1

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632

    Subclassing Class and Module...can anyone see whats wrong???

    VB Code:
    1. 'In Module:
    2. Option Explicit
    3.  
    4. Const GWL_WNDPROC = -4
    5. Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal ndx As Long, ByVal newValue As Long) As Long
    6. Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    7.  
    8. Private Type mtypWindowInfoUDT
    9.     hWnd        As Long
    10.     OldWndProc  As Long
    11.     MsgHook     As MsgHook
    12. End Type
    13.  
    14. Dim mudtWindowInfo()        As mtypWindowInfoUDT
    15. Dim mlngmudtWindowInfoCount As Long
    16.  
    17. Public Sub HookWindow(ByRef pobjMsgHook As MsgHook, ByVal hWnd As Long)
    18.     If mlngmudtWindowInfoCount = 0 Then
    19.         ReDim mudtWindowInfo(10) As mtypWindowInfoUDT
    20.     ElseIf mlngmudtWindowInfoCount > UBound(mudtWindowInfo) Then
    21.         ReDim Preserve mudtWindowInfo(mlngmudtWindowInfoCount + 9) As mtypWindowInfoUDT
    22.     End If
    23.     mlngmudtWindowInfoCount = mlngmudtWindowInfoCount + 1
    24.     With mudtWindowInfo(mlngmudtWindowInfoCount)
    25.         .hWnd = hWnd
    26.         Set .MsgHook = pobjMsgHook
    27.         .OldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WndProc)
    28.     End With
    29. End Sub
    30.  
    31. Public Sub UnhookWindow(ByRef pobjMsgHook As MsgHook)
    32. Dim lngIndex        As Long
    33.     For lngIndex = 1 To mlngmudtWindowInfoCount
    34.         If mudtWindowInfo(lngIndex).MsgHook Is pobjMsgHook Then
    35.             SetWindowLong mudtWindowInfo(lngIndex).hWnd, GWL_WNDPROC, mudtWindowInfo(lngIndex).OldWndProc
    36.             mudtWindowInfo(lngIndex) = mudtWindowInfo(mlngmudtWindowInfoCount)
    37.             mlngmudtWindowInfoCount = mlngmudtWindowInfoCount - 1
    38.             Exit For
    39.         End If
    40.     Next lngIndex
    41. End Sub
    42.  
    43. Public Function WndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    44. Dim lngIndex    As Long
    45. Const WM_DESTROY = &H2
    46.     For lngIndex = 1 To mlngmudtWindowInfoCount
    47.         If mudtWindowInfo(lngIndex).hWnd = hWnd Then
    48.             WndProc = mudtWindowInfo(lngIndex).MsgHook.WndProc(hWnd, uMsg, wParam, lParam, mudtWindowInfo(lngIndex).OldWndProc)
    49.             If uMsg = WM_DESTROY Then
    50.                 Call mudtWindowInfo(lngIndex).MsgHook.StopSubclass
    51.             End If
    52.             Exit For
    53.         End If
    54.     Next lngIndex
    55. End Function
    and...
    VB Code:
    1. 'In a class
    2. Option Explicit
    3.  
    4. Event BeforeMessage(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByRef RetValue As Long, ByRef Cancel As Boolean)
    5. Event AfterMessage(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long)
    6.  
    7. Private mlnghWnd As Long
    8.  
    9. Public Sub StartSubclass(ByVal hWnd As Long)
    10.     If mlnghWnd Then
    11.         Call StopSubclass
    12.     End If
    13.     mlnghWnd = hWnd
    14.     If mlnghWnd Then
    15.         Call HookWindow(Me, mlnghWnd)
    16.     End If
    17. End Sub
    18.  
    19. Public Sub StopSubclass()
    20.     If mlnghWnd Then
    21.         Call UnhookWindow(Me)
    22.     End If
    23. End Sub
    24.  
    25. Friend Function WndProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, ByVal oldWindowProc As Long) As Long
    26. Dim blnCancel   As Boolean
    27. Dim lngRet      As Long
    28.     RaiseEvent BeforeMessage(hWnd, uMsg, wParam, lParam, lngRet, blnCancel)
    29.     If Not blnCancel Then
    30.         lngRet = CallWindowProc(oldWindowProc, hWnd, uMsg, wParam, lParam)
    31.     End If
    32.     RaiseEvent AfterMessage(hWnd, uMsg, wParam, lParam)
    33.     WndProc = lngRet
    34. End Function
    35.  
    36. Private Sub Class_Terminate()
    37.     Call StopSubclass
    38. End Sub

  2. #2
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373
    what error are you getting?

  3. #3

  4. #4
    Let me in .. techyspecy's Avatar
    Join Date
    Aug 2002
    Location
    Back to VBF.
    Posts
    2,456
    Your copy/pasting has caused you bad naming conventions ....

    VB Code:
    1. Dim mlngmudtWindowInfoCount As Long

  5. #5
    Fanatic Member
    Join Date
    Feb 2003
    Location
    C:\Windows\Microsoft.NET\Framework
    Posts
    574
    I may be wrong, but it is very clear where your code fails.

    Here in your Hook procedure, as soon your array ubound reaches 11 elements (or 10 elements if your Option Base is 1), you re-allocate more dynamic memory of 9 elements. Soon after which, you increment the counter mlngmudtWindowInfoCount only by 1 element. Immediately after that, you populate the UDT instance based on the value of mlngmudtWindowInfoCount . All of it will fall in place except in one situation. Consider when the ubound of your UDT array mudtWindowInfo reaches exactly 10. You have no construct for that, do you? You simply increment your counter and move forward, the 11th element (or the 10th one if your Option Base is 1) escapes the hook.

    Code:
    ElseIf mlngmudtWindowInfoCount > UBound(mudtWindowInfo) Then
            ReDim Preserve mudtWindowInfo(mlngmudtWindowInfoCount + 9) As mtypWindowInfoUDT
        End If
        mlngmudtWindowInfoCount = mlngmudtWindowInfoCount + 1
        With mudtWindowInfo(mlngmudtWindowInfoCount)
            .hWnd = hWnd
            Set .MsgHook = pobjMsgHook
            .OldWndProc = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WndProc)
        End With
    End Sub
    The correct code be just adding an = sign here instead of a greater than sign.


    Code:
    
    ElseIf mlngmudtWindowInfoCount = UBound(mudtWindowInfo) Then
    

  6. #6

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    Yea, but I am only added 1 message hook class...never added 10, I cut and pasted that part of the code...theoreticall when I get round to writeing in correctly I would use a collenot a stupid array

    Techy...Booooooooooo...well spotted Hahahahaha

  7. #7
    I'm about to be a PowerPoster! kleinma's Avatar
    Join Date
    Nov 2001
    Location
    NJ - USA (Near NYC)
    Posts
    23,373
    Originally posted by Wokawidget
    Yea, but I am only added 1 message hook class...never added 10, I cut and pasted that part of the code...theoreticall when I get round to writeing in correctly I would use a collenot a stupid array

    Techy...Booooooooooo...well spotted Hahahahaha
    woka what are you smoking today???

    and more importaintly.. why are you not sharing?

  8. #8

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    Nothing
    Haven't had any for 2 days *sob*
    End of the month...Skint!

    If anyone would like to post me something as a donation then I would be very greatful

    Woka

  9. #9
    PowerPoster
    Join Date
    Jul 2002
    Location
    Dublin, Ireland
    Posts
    2,148
    What symptoms are you getting i.e. does the program crash, or does the subclassed proc never get called or what?

  10. #10
    Let me in .. techyspecy's Avatar
    Join Date
    Aug 2002
    Location
    Back to VBF.
    Posts
    2,456
    Exactly - you never said what problem you are encountering ????

  11. #11

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    In an active X EXE create a window using CreateWindowEx API...
    The module and class module above are in the same activeX EXE and I subclass this new window...from another app I pass a custom message to it...If the ActiveX is running in the IDE OR when it's compiled it works...BUT

    If I add the 2 things above into a seperate DLL, one that I can use for subclassing in many projects, then use this DLL in the ActiveX EXE and subclass the Newly created window then the following happens...

    If The activeX EXE is running in the IDE then it works, it traps my custom message and processes it...BUT if I compile the ActiveX EXE it doesn't trap my Message and So the SendMessage command I use returns straight away with a return value of 0...

    Woka

  12. #12

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    Here's the general DLL I use with the NewWindow and The MsgHook classes...

    Ignore the modSubclass...this is only used for the subclassing of the SystemTray...should change this to sue the MsgHook class, but I subclass the form instead for the Systray...very old code...
    Attached Files Attached Files

  13. #13

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    I have just created a small ActiveX EXE demo to show you...
    Here it is...Compile the above project and then reference it in the following attached project...

    Woka
    Attached Files Attached Files

  14. #14

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    Now here's my main app, again a simplified cut down version...Reference ProxyDLL.EXE in this app...

    Now run ProxyDLL.EXE in the VB IDE then run the app I have attached to tyhis post....you should see the msgbox "Woof" followed by a MsgBox 1234567

    Ok, sunclassing works...

    Now close the apps down...compile the ProxyDLL activeX EXE and reference the ActiveX EXE in the project attached to this post...now run it...you'll notice no msgbox "Woof" and the return from the sendmessage is 0!!!



    Woka
    Attached Files Attached Files

  15. #15

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    Now, if you remove the relevant classes and modules and add them into ProxyDLL.EXE, so you're not using VBTools.DLL in this project anymore then it works!



    Woka

  16. #16

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    The classes to add, from VBTools, to ProxyDLL.EXE are module modMsgHook, Class MsgHook and class NewWindow....add these to proxyDLL and remove the refereence to VBTools and compile....the app now works....so why doesn't it trap my message when it references VBTools and uses the classes in there to subclass and create new window???

    Woka

  17. #17

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    I could howveer just add the required modules and classes into my project, but I didn't want this, I wanted a generic DLL will tools that I use frequently...Booooooooooooooooooooo

    Any ideas to why it won't subclass???

    Woka

  18. #18

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    *BuMp*

    Bad Woka *sLaP*

    Come on you API gobbling guru's...I thought it was me being a prune and that someone would have looked at the code and said "Woka, you are a real moron, you forogot to do..."

    Come on, prove that I am a moron and am doing something really stupid in the above demos...

    Moronic Woka

  19. #19
    PowerPoster
    Join Date
    Jul 2002
    Location
    Dublin, Ireland
    Posts
    2,148
    Have downloaded this and will look at it as soon as this hangover abates to a dull roar

  20. #20
    PowerPoster
    Join Date
    Jul 2002
    Location
    Dublin, Ireland
    Posts
    2,148
    Well - I ran DemoApp.vbp which was referencing the compiled activeX yoke and got 1234567 returned.

    The only change I made was to make the instancing of ReferenceClass in the ActiveX exe to "3 - Singleuse".

  21. #21

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    So which classes need to be set to single use? I have the set to MultiUse...
    Did you get the problem I have having if you didn't set this property?
    Why does it do this?

    Woka

  22. #22

  23. #23

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    Sorry, was looking at the wrong project...D'oh!

    OK, so I set the class I reference in my Starndard EXE project to Single use, in the demo above it's ReferenceClass...what about MsgHook and NewWindow???

    Woka

    Don't suppose you know why this is happening?
    What's the defference between MultiUser, which I had it set to, and singleuse???

    Woka (again)

  24. #24
    Fanatic Member
    Join Date
    Feb 2003
    Location
    C:\Windows\Microsoft.NET\Framework
    Posts
    574
    What's the defference between MultiUser, which I had it set to, and singleuse???
    When you set the Instancing property of a COM object to MultiUse, which is also the default property, every client using it uses the same copy of the object. The object is only loaded once in the memory and it serves multiple client references. Multiuse is the default property setting.

    SingleUse means just the opposite. Every single AddRef call creates a new object of the COM component/class. This uses more memory than the MultiUse setting.

    As to what your problem in the project on subclassing was, I haven't looked at it. I downlaoded the first project you'd sent, the one with the modules modSubclass and stuff, but one of the modules was missing perhaps, that had the declaration to your CUSTOM_MESSAGE used by SendByteArray() routine, so I dropped the idea.

    Besides, although I have been using subclassing for a fair amount of time now, I admit, there is still more to it. And I believe it is generally true of all the average programmers, many of us know how to subclass, some of us know to subclass elegantly, but then at the end of the day, we're still defeated.

    Haven't downloaded your files, but I just hope you aren't trying to subclass windows in a foreign process. Its near impossible.

  25. #25

  26. #26
    PowerPoster
    Join Date
    Jul 2002
    Location
    Dublin, Ireland
    Posts
    2,148
    I think the single/multi use thing may be a red herring....I just instinctively set anything that uses subclassing to single use because the idea of multiple processes basically sharing the same window is too freaky for a bear of very little brain such as me.

  27. #27
    Fanatic Member
    Join Date
    Feb 2003
    Location
    C:\Windows\Microsoft.NET\Framework
    Posts
    574
    I cannot say anything at this point without looking at any of your code as a whole. The first of your projects itself did not compile for me. And since it had a binary compatibility option, I did not deem fit to remove SendByteArray() from the interface, even after having checked you were not using it anywhere else.

    What you will use as Instancing really depends on your needs. I do not have much knowledge to comment on that. May be someone else who's done enough of under-the-hood COM scum would better be able to advise you on Instancing. And without having seen your code as a whole, the ActiveX EXE, the Standard EXE, I cannot make a decisive comment. However, one truth I might tell you about subclassing is that you cannot subclass a window in another process , under no circumstances. (There are workarounds for everything though, someone will tell you, and he'd not be lying). Now, taking into account this statement, just let me flip a wild guess (not having seen your code), that every WndProc has an address, we know that, right? This address is a memory address relative to the process in which it runs (in this case, the process space of the calling thread that your DLL shares). Now, you've not created a global subclass. You actually did subclass only the window under question being passed to your StartSubclass procedure (you've posted your code above). Since this window is a local subclass, its procedure address (AddressOf WndProc) resides locally in the calling thread's process shared by the DLL containing the WndProc). This process address is relative to the process and as such does not have any meaning outside the process context. Right? From here it get's a little loose. Now tie this up with the Merrion's observation about the project working as soon as he set the Instancing to SingleUse. Do you not get some feelers? Of course, I cannot be very sure of what exactly is the problem even now unless I have your code. Even then, I might not be competent enough to comment on it. Just a thought.

  28. #28

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    I don't think any modules are missing from the 1st project...Merrion is there any missing...the CUSTOM MESSAGE was just a number...523453 I think...
    U can subclass something in another process but you have to do some VERY nasty API calls and "inject" your app into the processes memory space

    Just recompiling all my DLLs and EXE's to test of Merrions theory...will get back to u if it works

    Woka

  29. #29
    Let me in .. techyspecy's Avatar
    Join Date
    Aug 2002
    Location
    Back to VBF.
    Posts
    2,456
    Could not run your projects, I tried referencing the Active X exe in your demo application, it kept giving me ActiveX component can't create object.

    Anyway,
    WOKA,

    When you compile your Proxy DLL, do you check the option called 'Unattended Execution' in the project properties ???

  30. #30
    Let me in .. techyspecy's Avatar
    Join Date
    Aug 2002
    Location
    Back to VBF.
    Posts
    2,456
    and what the hell is CUSTOM_MESSAGE, it kept saying variable not defined in your VBtool.dll. I cannot compile VBtool.dll.

  31. #31
    Let me in .. techyspecy's Avatar
    Join Date
    Aug 2002
    Location
    Back to VBF.
    Posts
    2,456
    check the pic
    Attached Images Attached Images  

  32. #32

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    Sorry, I did miss a module...stupid project. It was saved in another folder...D'oh!
    VB Code:
    1. Option Explicit
    2.  
    3. Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long
    4.  
    5. Public Property Get CUSTOM_MESSAGE() As Long
    6. Static lngMsgID     As Long
    7.     If lngMsgID = 0 Then
    8.         lngMsgID = RegisterWindowMessage("CUSTOM_MESSAGE")
    9.     End If
    10.     CUSTOM_MESSAGE = lngMsgID
    11. End Property

    Woka

  33. #33
    Let me in .. techyspecy's Avatar
    Join Date
    Aug 2002
    Location
    Back to VBF.
    Posts
    2,456
    you didn't tell me if you checked the unattended execution thing while you compiled your proxy dll active X exe ?

  34. #34
    Let me in .. techyspecy's Avatar
    Join Date
    Aug 2002
    Location
    Back to VBF.
    Posts
    2,456
    check the pic and see what am i talking about ..
    Attached Images Attached Images  

  35. #35

  36. #36
    Fanatic Member
    Join Date
    Feb 2003
    Location
    C:\Windows\Microsoft.NET\Framework
    Posts
    574

    Talking

    And what were you just begging us to call you? Did you hear it?

    Just kidding.

  37. #37

  38. #38
    PowerPoster
    Join Date
    Jul 2002
    Location
    Dublin, Ireland
    Posts
    2,148
    Is it wise to set all my classes to Single Use???
    No - but where they involve creating a window, or subclassing, or having locked access to a resources it might be a good idea.

  39. #39

    Thread Starter
    Super Moderator Wokawidget's Avatar
    Join Date
    Nov 2001
    Location
    Headingly Occupation: Classified
    Posts
    9,632
    OK badger baiters, espescially Techyspeccy!
    Here's my code...that create a client-server multiuser app using TCP IP...

    OK, in SQLServer create a DB Called MBELots:
    then
    Code:
    if exists (select * from sysobjects where id = object_id(N'[dbo].[tblRecipes]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [dbo].[tblRecipes]
    GO
    
    if exists (select * from sysobjects where id = object_id(N'[dbo].[tblStructures]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [dbo].[tblStructures]
    GO
    
    CREATE TABLE [dbo].[tblRecipes] (
    	[UID] [uniqueidentifier] NOT NULL ,
    	[StructureUID] [uniqueidentifier] NOT NULL ,
    	[Description] [varchar] (30) NOT NULL 
    ) ON [PRIMARY]
    GO
    
    CREATE TABLE [dbo].[tblStructures] (
    	[UID] [uniqueidentifier] NOT NULL ,
    	[Description] [varchar] (30) NOT NULL 
    ) ON [PRIMARY]
    Now do do some insert commands on tblStructures...
    Code:
    INSERT tblstructures VALUES(NEWID(),'Badger Mumps')
    OK...1st compile VBTools...
    All other projects use this...

    Then do MBEServerObjects....making sure you set you DSN name to the DB u just created...

    Then compile MBEServerProxy, which references MBEServerObjects. and VBTools

    Now compile MBEServer which references MBEServerProxy and VBTools

    Now compile MBEClientProxy making sure you enter the IP address of the PC you will run the MBEServer.EXE on. this references VBTools.

    Now compile MBE Client which references VBTools and MBEClientProxy...

    And then run the server and then run as many clients as you want...

    When you get an error loading MBEClient it's because of a button I use here. Just delete the pic box and add a standard button. easy.

    Techy...see full tranactional multiuser server

    Woof Woof

  40. #40

Page 1 of 2 12 LastLast

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