mIRC Homepage

WM_CLOSE

Posted By: greeny

WM_CLOSE - 22/12/05 06:18 PM

Hi there.

I'm using a docking DLL, which works just fine when I disable the "confirm on exit" option in mIRC.

Even with this option enabled, the DLL still works fine if I normally close mIRC and press the "yes" button in the confirmation dialog.

However, when I press the "no" button, the docking will be really messed up.

I traced this back to the WM_CLOSE message, which is sent even before you confirmed the exit. So basically, the DLL issues the commands that are meant for "unloading" the DLL even though mIRC is still running (i.e. you pressed "no" in the confirmation dialog).

So, my question is, is there a simple solution for this problem? Like a message I can use instead of WM_CLOSE, that triggers when mIRC is REALLY closed?

Thanks for your help.
Posted By: qwerty

Re: WM_CLOSE - 23/12/05 12:12 AM

Sounds like you want WM_DESTROY
Posted By: greeny

Re: WM_CLOSE - 23/12/05 09:14 AM

Yup, sounds like I want it, unfortunately, that message is never sent wink
Posted By: ClickHeRe

Re: WM_CLOSE - 23/12/05 02:23 PM

it is sent and in fact it's there that you should unsubclass mIRC before it closes and clean everything you need to clean.
Posted By: Narusegawa_Naru

Re: WM_CLOSE - 23/12/05 03:28 PM

technically youll want to un subclass in the WM_NCDESTROY. typically if youve reserved any memory. Dont forget to PostMessage the destroy and return 0 from your wndproc. (so your out of your proc when the dll unloads and mIRC can see the destroy)
Posted By: NaquadaServ

Re: WM_CLOSE - 17/01/06 07:43 AM

Let me save everyone a whole lot of time searching MSDN for info on the proper way to subclass windows using Win32 API calls... Download my DLL at SuperTemplate 1.1. Actually you only need one c++ file in my DLL Template, safe-subclass.cpp (will most likely be posted separately on mircscripts.org soon)... BTW, If handled properly, it doesn't matter what message is used to unsubclass... And if you use "safe-subclassing.cpp" it wont matter which you use either.

Basically, Any DLLs created using this subclassing process, can subclass the same window at the same time, AND neither needs to know about the other to unsubclass. This means it doesn't matter what order the DLLs are unsubclassed (unloaded) or what message they use to unsubclass...

And yes, either WM_DESTROY (Destroy Window Message) or WM_QUIT (Hwnd should be eliminated) can be used to unsubclass when the window is closed.
Posted By: Narusegawa_Naru

Re: WM_CLOSE - 17/01/06 04:14 PM

I wouldnt use WM_QUIT to unsubclass. If mIRC was the subclassed window and the user clicked "No" to the confirm dialog then your subclass will be removed even tho mIRC wasnt actually closed. mIRC uses WM_QUIT to display the confirm on close dialog.

Im curious as to how your controlling other dll's (that arent using your patch) in the unsubclass. You will still end up with a broken chain because dll's not using your file will simply unsubclass w/o calling a safe routine. My last attempt used api hijacking to control SetWindowLong but still required that all the dll's loaded be compiled with my lib. i.e it had a msg manager and added subclassed windows to a tree when the dll called SetWindowLong.
Posted By: NaquadaServ

Re: WM_CLOSE - 17/01/06 04:38 PM

Wrong... As your original post stated, mirc asks to confirm exit when a WM_CLOSE messsage is sent, WM_QUIT is the LAST message a window ever receives.

But you are correct that WM_QUIT should not be used (I just looked it up), WM_DESTORY is the proper place to unsubclass...

WM_CLOSE
WM_DESTROY
WM_QUIT

BTW, you are correct, there isn't a realisticly possible way to control "unsafe" dll's, Only DLL's that use my "safe-subclass.cpp" (or equivilant) file will be compatibile. IMHO, it should be part of the Win32 API... wink
Posted By: NaquadaServ

Re: WM_CLOSE - 17/01/06 05:11 PM

BTW, despite what Microsoft says here...

Quote:

The WM_QUIT message is not associated with a window and wherefore will never be received through a window's window procedure. It is retrieved only by the GetMessage or PeekMessage functions.

I tested this when I was writing safe-subclass.cpp, and it appears that WM_QUIT is received in subclassed windows procedures.
Posted By: greeny

Re: WM_CLOSE - 08/03/06 12:10 AM

I still can't get this to work. Could it be that mIRC unloads the DLL upon exit before the WM_DESTROY message is received?

I'm really not doing anything fancy with the DLL... I'm just catching the WM_SIZE message so I know when the mIRC window is resized.

I tested this with ShowMessage(), on WM_CLOSE a dialog pops up, but when I replace it with WM_DESTROY or WM_QUIT, nothing happens...
Posted By: NaquadaServ

Re: WM_CLOSE - 18/03/06 01:30 AM

I guess it is possible. If when using confirm on exit, a yes answer is given (still processing WM_CLOSE message), before the message completes, the DLL's are unload... This would not be good. mIRC should unload DLL's in WM_DESTROY or WM_QUIT. Only one person can tell you if that's the case though... wink
Posted By: NaquadaServ

Re: WM_CLOSE - 21/03/06 10:23 PM

Quote:
I still can't get this to work. Could it be that mIRC unloads the DLL upon exit before the WM_DESTROY message is received?


Using thread hooks I have determined that this is "probably" what does happen. That's a problem, here's why...

Say a DLL is subclassing the mIRC app, on WM_CLOSE it does nothing. Now the DLL is unloaded... The return value of WM_CLOSE is going to return to the subclassed callback, which is no longer in memory, regardless of what WND_PROC was changed to.

To prevent problems, unsubclassing must be completed when WM_CLOSE is received, then return 0L to the current WM_CLOSE message and PostMessage(WM_CLOSE) again so that the subclassed procedure is out of the chain when WM_CLOSE is processed by mIRC.

Now the problem is "Confirm on Exit"... WM_CLOSE can either finish closing or be canceled. If we unsubclass in WM_CLOSE before knowing this, and exit is canceled, mIRC will continue to run but now be unsubclassed.
Posted By: NaquadaServ

Re: WM_CLOSE - 21/03/06 11:03 PM

Here is what I saw hooking WM_CLOSE. I have excluded the WM_DESTROY messages of controls for simplicity.

Canceled
WM_CLOSE: 1376684 16 0 0 mIRC mIRC
WM_CREATE: 1180678 1 1225544 0 #32770
WM_DESTROY: 1180678 2 0 0 #32770 Confirm Exit
WM_CLOSE_RETURN mIRC 1376684

Close Confirmed
WM_CLOSE: 1376684 16 0 0 mIRC mIRC
WM_CREATE: 1246214 1 1225544 0 #32770
WM_DESTROY: 1246214 2 0 0 #32770
(NO RETURN)

It then appears that WM_DESTROY is sent out to all(?) mIRC children. The "confirm on exit's" dialog and controls receive WM_DESTORY first. Then any controls the DLL created receive WM_DESTROY. Here is where output stops, either because the DLL was unloaded or because mIRC will no longer process WM_MCOMMAND.
© 2021 mIRC Discussion Forums