What happened to the Messenger Plus! forums on msghelp.net?
Shoutbox » MsgHelp Archive » Messenger Plus! for Live Messenger » Scripting » [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)

Pages: (2): « First [ 1 ] 2 » Last »
[Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
Author: Message:
phalanxii
Full Member
***


Posts: 146
Reputation: 5
31 / Male / Flag
Joined: Aug 2006
Status: Away
O.P. [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
Subclassing is quite a useful way of monitoring the messages sent to the keyboard (such as key presses), mouse (such as right mouse clicks) and windows (such as minimizing).

Plus! can already do some subclassing; take for example matty's hotkey code and SpunkyLoveMuff's StatusKey script. These both involve an invisible Plus! window which monitors the keyboard for a specific hotkey.

However, sometimes Plus! windows are not enough. For example, (as far as I know) it is impossible to detect the changing of tabbed chats using only the Plus! scripting engine and the Win32 API. It is even more impossible to detect messages sent to external applications (like Winamp for example).

This is where the ActiveXObjects come in. By using these, we are able to do all these things, right in Plus! itself!

After doing some browsing, I came across two free subclassing ActiveX files.


1. ARSubclass

Link
Download

ARSubclass is a very lightweight ActiveX library. It allows you to monitor the messages sent to a specific window (given its handle). Firstly, the DLL is required to be registered when the script is imported, so this line must be added to ScriptInfo.xml:
code:
<OleFiles>
    <FileName>ARSubclass.dll</FileName>
</OleFiles>
Here is an example code of how to use it:
code:
var ARSubclass = new ActiveXObject("ARSubclassLib.ARSubclass");

function OnEvent_Initialize(MessengerStart) {
    ARSubclass.hWnd = Messenger.ContactListWndHandle;
    ARSubclass.Message(/* WM_ACTIVATE */ 6) = true;
}

function OnEvent_ContactListWndCreated() { OnEvent_Initialize(); }

var Event = function() {
    function ARSubclass::WindowProc(hWnd, iMessage, wParam, lParam, Res) {
        if(wParam === /* WA_INACTIVE */ 0) Debug.Trace("WA_INACTIVE");
        if(wParam === /* WA_ACTIVE */ 1) Debug.Trace("WA_ACTIVE");
        if(wParam === /* WA_CLICKACTIVE */ 2) Debug.Trace("WA_CLICKACTIVE");
    }
}

Event();
This will trace when the WM_ACTIVATE message is sent to the contact list and show whether it is activated, activated by click or deactivated. (Here, "activated" simply means that the window gets "focus".) When the contact list is created, the ActiveXObject takes its handle and is set to receive all WM_ACTIVATE messages. When it receives one of these messages, it is processed by the WindowProc function with wParam and lParam. (Cheers to Pai for the ActiveX event trick).

More information can be found on the website.


2. SubClassX5 and SubClassX6

Link
Download

SubClassX5 and SubClassX6 work identically except they are compiled with different versions of VisualBasic. They work very similar to ARSubclass, except they can deal with more than one window. This makes them especially useful for our tabbed chats scenario as previously mentioned. Unfortunately, the size is quite a bit larger than ARSubclass, but still useable nonetheless! Again, we must register the DLL with ScriptInfo.xml:
code:
<OleFiles>
    <FileName>SubClassX6.dll</FileName>
</OleFiles>
Here is an example code of how to use it:
code:
var SubClassX6 = new ActiveXObject("SubClassX6.Window");

function OnEvent_ChatWndCreated(ChatWnd) {
    SubClassX6.SubClass_Start(ChatWnd.Handle);
}

function OnEvent_ChatWndDestroyed(ChatWnd) {
    SubClassX6.SubClass_Stop(ChatWnd.Handle);
}

var Event = function() {
    function SubClassX6::Message(hWnd, Msg, wParam, lParam, Return_Value, Return_SetValue) {
        if(Msg == /* WM_ACTIVATE */ 6 && wParam != /* WA_INACTIVE */ 0) Debug.Trace(hWnd);
    }
}

Event();
This will trace the handle of a chat window when it is activated (set in focus). Notice that we are able to subclass more than one window simultaneously from the one ActiveXObject. Here, the callback function is Message.

A full documentation of all the functions and properties comes with the DLL.


Finally, I have an example of how this may be useful to scripters. I have attached a script which uses subclassing that will change the window icon (yes, in the toolbar too!) of tabbed chats to reflect the current contact's status. This should work with tabbed chats disabled too. (You may need to restart WLM first.) Credits to Veggie for his original StatusIcon script.

Hopefully this has been useful to some of you. All mistakes are entirely deliferate.

TabbedStatusIconV3 - Download

EDIT: Updated version of TabbedStatusIcon has been attached. This fixes some minor bugs.

EDIT: Updated again because I stuffed up the contact status change. It should all be fixed now!

.plsc File Attachment: TabbedStatusIconV3.plsc (35.98 KB)
This file has been downloaded 368 time(s).

This post was edited on 03-28-2008 at 01:08 AM by phalanxii.
03-27-2008 12:05 PM
Profile PM Find Quote Report
effection
Full Member
***

Destroy The Runner

Posts: 135
Reputation: 4
– / Male / Flag
Joined: Sep 2006
RE: [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
very very nice piece of work
03-27-2008 04:45 PM
Profile E-Mail PM Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
quote:
Originally posted by phalanxii
However, sometimes Plus! windows are not enough. For example, (as far as I know) it is impossible to detect the changing of tabbed chats using only the Plus! scripting engine and the Win32 API.
That's very possible iirc.

quote:
Originally posted by phalanxii
It is even more impossible to detect messages sent to external applications (like Winamp for example).
Also possible....

No need for an ActiveX for all of this. Just some API stuff... In fact, the ActiveXs do exactly what you already can do in Plus! by using the Windows API.

Though using this ActiveX might be the easy solution for some. So, very good and nice find though (y)...



But then again, some problems may arise when you use ActiveX (especially if more than one script is going to use the same one):
quote:
Originally posted by phalanxii
Firstly, the DLL is required to be registered when the script is imported, so this line must be added to ScriptInfo.xml:
code:
<OleFiles>
    <FileName>ARSubclass.dll</FileName>
</OleFiles>
Here is an example code of how to use it:
code:
var ARSubclass = new ActiveXObject("ARSubclassLib.ARSubclass");

I actually do not recommend all of this (even including the use of <OleFiles>). (I think Patchou will shoot me now :p) The reason is again that you will get into trouble when more than one script is going to use that DLL and you later install or remove even more scripts which use it.




---------

As for the tabbed chat window example, I think that can be done much easier and with subclassing just 1 window. The hidden Plus! window which controls the tabs.

This post was edited on 03-27-2008 at 08:10 PM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
03-27-2008 07:25 PM
Profile PM Find Quote Report
phalanxii
Full Member
***


Posts: 146
Reputation: 5
31 / Male / Flag
Joined: Aug 2006
Status: Away
O.P. RE: RE: [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
quote:
Originally posted by effection
very very nice piece of work
Thanks. :)
quote:
Originally posted by CookieRevised
No need for an ActiveX for all of this. Just some API stuff... In fact, the ActiveXs do exactly what you already can do in Plus! by using the Windows API.

Though using this ActiveX might be the easy solution for some. So, very good and nice find though (Y)...
Would you be able to give an example of such a code (using only Plus! and the Windows API)? I'm quite interested in knowing how to do this. I didn't think it would be possible to have real-time events (when the windows messages are received), even with the new Interop.GetCallbackPtr() which only supports synchronous calls (I assume this means the calls are returned immediately).
quote:
Originally posted by CookieRevised
I actually do not recommend all of this (even including the use of <OleFiles>). (I think Patchou will shoot me now :P) The reason is again that you will get into trouble when more than one script is going to use that DLL and you later install or remove even more scripts which use it.
I just experimented with this and noticed that it does cause a few problems. However, the ActiveX is not completely unregistered and the script's functionality returns to normal after restarting WLM.
quote:
Originally posted by CookieRevised
As for the tabbed chat window example, I think that can be done much easier and with subclassing just 1 window. The hidden Plus! window which controls the tabs.
Hmm... I tried subclassing just the hidden Plus! window, but I wasn't sure which message needed to be detected (WM_ACTIVATE doesn't work with it). The problem is that tabs can be changed with left mouse clicks as well as ctrl+tab on the keyboard. Also, subclassing each individual conversation window makes it easier to keep track of the current conversation handle. Suggestions?

I've also updated the TabbedStatusIcon to fix a few bugs.
03-28-2008 12:47 AM
Profile PM Find Quote Report
felipEx
Scripting Contest Winner
***


Posts: 378
Reputation: 24
35 / Male / Flag
Joined: Jun 2006
RE: [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
Hi :]

phalanxii:  i'm not totally sure if it's correct, but it works fine here

code:
var GWL_WNDPROC = -4
var lpPrevWndProc = 0

function OnEvent_Initialize() {
    if(Messenger.MyStatus > 0) OnEvent_SigninReady();
}

function OnEvent_SigninReady() {
    for (var e = new Enumerator(Messenger.CurrentChats); !e.atEnd(); e.moveNext()) OnEvent_ChatWndCreated(e.item());
}

function OnEvent_Uninitialize(MessengerExit){
    for (var e = new Enumerator(Messenger.CurrentChats); !e.atEnd(); e.moveNext()){
        if (lpPrevWndProc != 0)    Interop.Call('user32', 'SetWindowLongW', e.item().Handle, GWL_WNDPROC, lpPrevWndProc)
    }
}

function OnEvent_ChatWndCreated(ChatWnd){
    lpPrevWndProc = Interop.Call('user32', 'SetWindowLongW', ChatWnd.Handle, GWL_WNDPROC,  Interop.GetCallbackPtr('WindowProc') )
}

function OnEvent_ChatWndDestroyed(ChatWnd){
    if (lpPrevWndProc != 0)    Interop.Call('user32', 'SetWindowLongW', ChatWnd.Handle, GWL_WNDPROC, lpPrevWndProc)
}

function WindowProc(hwnd, uMsg, wParam, lParam){
    if (uMsg == 0x6 && wParam != 0){
        // stuff
    }
    return Interop.Call('user32', 'CallWindowProcW', lpPrevWndProc, hwnd, uMsg, wParam, lParam)
}
* felipEx waits for Cookie's reply :D
03-28-2008 05:00 AM
Profile E-Mail PM Find Quote Report
phalanxii
Full Member
***


Posts: 146
Reputation: 5
31 / Male / Flag
Joined: Aug 2006
Status: Away
O.P. RE: [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
Thanks felipEx! It works fine over here too. I must say that it is also a lot more reliable than the ActiveX libraries and the script file size is obviously much smaller.

I'm wondering about the documentation though:
quote:
Originally posted by Messenger Plus! Live Scripting Documentation

Interop::GetCallbackPtr

Remember that the use of callback functions is restricted to synchronous calls. This means that all the calls made to the callback function must be done before the callee returns. Asynchronous calls are not permitted and must not be attempted in any circumstances.
Would this be considered an asynchronous call? :S

If this method is fine, I will release an updated TabbedStatusIcon (possibly in a separate thread).
03-28-2008 07:03 AM
Profile PM Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
quote:
Originally posted by felipEx
* felipEx waits for Cookie's reply :D
That's what I meant, yes.

At phalanxii, hmmm, very good point. I guess this has something todo with the fact that scripts can be unloaded, removed, etc. But then again, as felipEx showed, you could handle that with Uninitialize() and ChatWndDestroyed() and stuff. Dunno really.... This is something for Patchou to answer I think: why it is that it isn't allowed, but still possible.


Anyways, even if it wouldn't have been possible like that, you could also make a very small ActiveX dll which does the same as  GetCallbackPtr(). I have used such an ActiveX a long time ago as kind of experiment, before GetCallbackPtr existed, and it worked nice. You call the ActiveX, the ActiveX returns a pointer you could use in a call to the SetWindowLongW API and you needed a var function (like the one used with Xniff and other ActiveX which call back to the script).

And, but I never made this experiment yet, I think you could also device something with a Plus! Window of which you 'borrowed' the WinProc address to be used to overwrite the WinProc of another window. And with OnWindowidEvent_MessageNotification you can catch the window messages of that 'external' window. If this works, it also means you could subclass already long before GetCallbackPtr() existed.
.-= A 'frrrrrrrituurrr' for Wacky =-.
03-28-2008 04:57 PM
Profile PM Find Quote Report
deAd
Scripting Contest Winner
*****

Avatar

Posts: 1060
Reputation: 28
– / Male / Flag
Joined: Jan 2006
RE: RE: [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
quote:
Originally posted by CookieRevised
And, but I never made this experiment yet, I think you could also device something with a Plus! Window of which you 'borrowed' the WinProc address to be used to overwrite the WinProc of another window. And with OnWindowidEvent_MessageNotification you can catch the window messages of that 'external' window. If this works, it also means you could subclass already long before GetCallbackPtr() existed.
I tried this once, but it doesn't work because you only have control over certain messages. You can't call the original window proc for messages you don't handle yourself because Plus! only tells you about the ones you ask for, and if you ask for everything you'll experience severe delays since JScript is so slow.
03-28-2008 06:22 PM
Profile PM Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
Isn't the reason you want to subclass something because you need to catch just a certain message? I don't see why you would want to catch all possible messages there are, that would be useless (unless you make a Windows Message Spying program).

This post was edited on 03-28-2008 at 06:50 PM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
03-28-2008 06:49 PM
Profile PM Find Quote Report
deAd
Scripting Contest Winner
*****

Avatar

Posts: 1060
Reputation: 28
– / Male / Flag
Joined: Jan 2006
RE: RE: [Resource] Subclassing ActiveXObjects (and [Release] TabbedStatusIcon too!)
quote:
Originally posted by CookieRevised
Isn't the reason you want to subclass something because you need to catch just a certain message? I don't see why you would want to catch all possible messages there are, that would be useless (unless you make a Windows Message Spying program).
Yes, but you have to send the messages you don't want back to the original windowproc. You can't do this with a Plus! window because you only have control over the messages you ask for.
03-28-2008 07:20 PM
Profile PM Find Quote Report
Pages: (2): « First [ 1 ] 2 » Last »
« Next Oldest Return to Top Next Newest »


Threaded Mode | Linear Mode
View a Printable Version
Send this Thread to a Friend
Subscribe | Add to Favorites
Rate This Thread:

Forum Jump:

Forum Rules:
You cannot post new threads
You cannot post replies
You cannot post attachments
You can edit your posts
HTML is Off
myCode is On
Smilies are On
[img] Code is On