[RESOLVED] Subclassing usercontrols (Previously: App closing sequence)
Hello!
I'm stuck on a problem i cant overcome. The problem is that my app is wont close up itself in the right order. Ive put a tons of debug out lines, to see what is the initialization, then termination and unload sequence of each usercontrol, class, forms and the main mdiform. (theres a lot of objects, i used a timestamped file output for my custom debugging)
At in every log, i see differences, sometimes the main mdi form will unload then terminates itself, in the middle of the closing sequence, but sometimes (just like i want it to) it closes itself at the end, but before terminating its content form. Sometimes, i also see 'rumbles' in the termination of class objects and usercontrols. They just change their order, found no reason why. (there are some usercontrols they contain timers, but not those im talking about)
The most painful thing is, that on rare case, it crashes the app also. unfortunately these crashes are just happen pretty much rare cases, so i cant track down what the reason of it. But im sure, that all timers are set to offline.
I use DoEvents in Terminate() and Unload() events, to fire the timers once again, before the form or object will close. Is that could happen, that the reason will be the timers or the DoEvents? What else can i do to stop everything before i execute the shutdown? Especially in case, when the mdi form will not unload/terminate itself, but after the half of its content?!
The project is huge enough, that i cant upload here.
-------------------------------------
In the meantime i typing this i included some routine into my mdi form's queryunload, that will walk thru on each mdi child and execute a speicifed subroutine that will do some inner workings, to unset the timers in their contained usercontrols, classes and so on... I hope it will works, ill report here my experiments.
Any input is welcome.
Re: Subclassing usercontrols (Previously: App closing sequence)
I've seen this problem before. The uc is subclassing the parent. When multiple uc's subclass the same parent, the crashes are common. What is happening is that the uc's are subclassing in order of loading: uc1, uc2, uc3, etc. But when unloading, they do not unload in reverse order to restore the subclassing stack, they unload in first loaded, first unloaded order. Let's look at it this way
Code:
' When UCs are loaded
UC1 subclasses: oldWndProc is Original
UC2 subclasses: oldWndProc is that in UC1
UC3 subclasses: oldWndProc is that in UC2
' When UC's are unloaded
UC1 unloads & resets subclass procedure to Original procedure
UC2 unloads & resets subclass procedure to that in UC1
>> crash. The procedure in UC1 is no longer in memory, it was unloaded
You can verify this yourself with a simple test project:
Code:
1. Add new form
2. Add new usercontrol (not yours, just a blank uc)
3. In UC, add this to Initialize event: Debug.Print "Loaded "; ObjPtr(Me)
4. In UC, add this to Terminate event: Debug.Print "Unloaded "; ObjPtr(Me)
5. Add 3 UCs to your form
6. Close your form in design view, Open Debug window (CTRL+G)
7. Clear any entries in it. Run test project. Close test project normally (X)
8. Open debug window & look at order loaded, unloaded.
I have tweaked Paul Caton's subclassing to avoid this issue. Basically, I've added a delay timer in the ASM thunk. The thunks prevent unloading the window procedure until a short timer expires, then unloads it. This works really well for UCs. You can find the modified thunks on PSC (as of this reply, PSC appears down for maintenance, so the link was obtained from googling & hopefully it is the correct one).
http://www.planetsourcecode.com/vb/s...68737&lngWId=1
Edited: This becomes even more crash prone when you have other UCs (3rd party) that subclass the parent also. The order of subclassing/unsubclassing is not in your control. And if those others use similar subclassing techniques as does your uc, what a mess! Which is the reason I don't write UCs to subclass any container/outside object, unless subclassing starts in a sub/function and terminates subclassing before the sub/function terminates.
Re: Subclassing usercontrols (Previously: App closing sequence)
Oh thanks! I will look forward how to avoid and/or replace these methods to get the proper functionality.
Thanks for informing me!
Re: [RESOLVED] Subclassing usercontrols (Previously: App closing sequence)
Quite frankly, I had a similar, if not the same problem.
I created a SubClassed UserControl and realised if only 1 instance was placed on a form it worked fine, without any crashes. But if multiple instances of the control were placed, then there was always a crash.
After tracking down, I spotted the problem and seem to have fixed it.
I always start off with a template of Paul Caton, which has a ready made Subclassed template of a UserControl.
In the SubClassed UserControl, you should probably have a Subclass_StopAll function. Find it and change it to this:
vb Code:
'Stop all subclassing
Private Sub Subclass_StopAll()
Dim i As Long
Dim getControlNo As Single
Dim wasHere As Boolean
i = UBound(sc_aSubData()) 'Get the upper bound of the subclass data array
Do While i >= 0 'Iterate through each element
With sc_aSubData(i)
If .hWnd <> 0 Then 'If not previously Subclass_Stop'd
' Debug.Print .hWnd, mParentHwnd
'Prevents crash if there are multiple controls on the form, because the Form is subclassed for MouseDown events
If .hWnd = mParentHwnd Then
If wasHere = False Then
' Call Subclass_Stop(.hWnd)
End If
wasHere = True
Else
Call Subclass_Stop(.hWnd) 'Subclass_Stop
End If
End If
End With
i = i - 1 'Next element
Loop
End Sub
Re: [RESOLVED] Subclassing usercontrols (Previously: App closing sequence)
Ssubtmr6.dll has a memory leak that will eventually crash Vb. It depends on how much memory you have, how many instances of the subclassed usercontrol are on the Form, and finally how many times the Form is Loaded/Unloaded. Also check to make sure that for every AttachMessage there is a corresponding DetachMessage when using Ssubtmr6.dll. You may want to try one of the subclassing Thunks on Planet Source Code.
Re: [RESOLVED] Subclassing usercontrols (Previously: App closing sequence)
Quote:
Originally Posted by some1uk03
In the SubClassed UserControl, you should probably have a Subclass_StopAll function. Find it and change it to this:
Its nice to you to show me your example, but its just not works. I am getting subscript out of range error codes, i also dont know where and how should i set the parent hwnd (mParentHwnd)!
Re: [RESOLVED] Subclassing usercontrols (Previously: App closing sequence)
Quote:
Originally Posted by Jim Davis
Its nice to you to show me your example, but its just not works. I am getting subscript out of range error codes, i also dont know where and how should i set the parent hwnd (mParentHwnd)!
Ohh yea I forgot about mParentHwnd : )
Decalre this in the General Declaration Section.
Code:
Private mParentHwnd As Long 'Remember parent Hwnd to stop crash
Then in your UserControl_ReadProperties add this.
Code:
mParentHwnd = UserControl.Parent.hWnd
--------------------
The Subscrit Out Of Range errors, are other coding errors you have, which can be tracked down through simple error coding in the subs.
Re: [RESOLVED] Subclassing usercontrols (Previously: App closing sequence)
Nevermind, its ok now. About the array issue, i found that the line i = UBound(sc_aSubData()) is raised the error, because in design time havent got dimensions of the array, therefore it have no upper bound. It is also fixed now.
I still got a crash once in IDE. But later there were no problems! By regarding LaVolpe's post, this wouldnt solve the problem. I will do some test to see it is stable or not.
Re: [RESOLVED] Subclassing usercontrols (Previously: App closing sequence)
You can usually avoid IDE crashes caused by subclassing by only using your programs controls to close the app.
In other words, don't use the vb6 Stop button.
Re: Subclassing usercontrols (Previously: App closing sequence)
Quote:
Originally Posted by
LaVolpe
Edited: This becomes even more crash prone when you have other UCs (3rd party) that subclass the parent also. The order of subclassing/unsubclassing is not in your control. And if those others use similar subclassing techniques as does your uc, what a mess! Which is the reason I don't write UCs to subclass any container/outside object, unless subclassing starts in a sub/function and terminates subclassing before the sub/function terminates.
i'm facing issues with subclassing uc
i created a listview window on vb uc
then subclass the uc to get messages,
one of the issues for example is:
the uc doesn't get some messages if there is no other control
on the uc parent
if i place the uc on an empty form, some messages simply don't arrived
i put debug.print in the wndproc, to print all the messages
i downloaded stuff from vbaccelerator to learn.
but any idea on how to get messages without subclassing
the uc would be helpfull.