What happened to the Messenger Plus! forums on msghelp.net?
Shoutbox » MsgHelp Archive » Messenger Plus! for Live Messenger » Scripting » [REQ/HELP] Display Picture as Window Icon

Pages: (2): « First [ 1 ] 2 » Last »
[REQ/HELP] Display Picture as Window Icon
Author: Message:
NoWhereMan
Junior Member
**


Posts: 25
Joined: Oct 2009
O.P. [REQ/HELP] Display Picture as Window Icon
I was trying to do this myself but it looks like it is beyond my (barebone) knowledge of the Win32 API, so I'm asking if anyone is in the mood of doing it instead ;)

basically I'm asking for a script that changes a ChatWindow's icon to a mini-thumbnail of the contact's DP, as seen in other compatible clients such as Pidgin.

working code on matti's post

[Image: r5RSQl.jpg]

(sw in screenie: switcher)

This post was edited on 10-05-2009 at 06:15 PM by NoWhereMan.
10-04-2009 02:57 PM
Profile E-Mail PM Find Quote Report
matty
Scripting Guru
*****


Posts: 8336
Reputation: 109
39 / Male / Flag
Joined: Dec 2002
Status: Away
RE: [REQ/HELP] Display Picture as Window Icon
That is an interesting idea. Only thought is that at 16x16 pixels you wont be able to see the image that well considering the original is 96x96...

Anyways it will look something like this...

Untested as I am at work!
Javascript code:
var objChatWnds = {};
 
function setDpAsIcon ( sDpLocation , oChatWnd ) {
    var GdipToken = Interop.Allocate ( 4 );
    var GdipStartupInput = Interop.Allocate ( 16 );
        GdipStartupInput.WriteDWORD( 0 , 1 );
       
    var bInitialized = Interop.Call( 'gdiplus' , 'GdiplusStartup' , GdipToken , GdipStartupInput , 0 ) === 0;
   
    if ( bInitialized === true ) {
        var nImgPtr = Interop.Allocate ( 4 );
        Interop.Call( 'gdiplus' , 'GdipLoadImageFromFile' , sDpLocation , nImgPtr );
        var hImage = nImgPtr.ReadDWORD ( 0 ) !== 0 ? nImgPtr.ReadDWORD ( 0 ) : false;
       
        if ( hImage !== false ) {
            var hIcon = Interop.Allocate ( 4 );
            Interop.Call ( 'gdiplus' , 'GdipCreateHICONFromBitmap' , hImage , hIcon );
            objChatWnds [ oChatWnd ] = hIcon;
            Interop.Call( 'user32' , 'SendMessageW' , oChatWd.Handle , 0x80 /* WM_SETICON */ , 0 /* ICON_SMALL */ , hIcon );
            Interop.Call( 'user32' , 'SendMessageW' , oChatWd.Handle , 0x80 /* WM_SETICON */ , 1 /* ICON_BIG */ , hIcon );
        }
    }
    Interop.Call( 'gdiplus' , 'GdiplusShutdown' , GdipToken.ReadDWORD ( 0 ) );
}
 
function OnEvent_ChatWndCreated ( oChatWnd ) {
    if ( oChatWnd.Contacts.Count === 1 ) {
        for ( var oContact = new Enumerator ( oChatWnd.Contacts ); !oContact.atEnd ( ); oContact.moveNext ( ) ) {
            setDpAsIcon ( oContact.item( ).DisplayPicture , oChatWnd );
        }
    }
}
 
function OnEvent_ChatWndDestroyed ( oChatWnd ) {
    if ( typeof objChatWnds [ oChatWnd.Handle ] === 'object ' ) {
        if ( oChatWnd.Contacts.Count === 1 ) {
            Interop.Call( 'user32' , 'SendMessageW' , oChatWd.Handle , 0x80 /* WM_SETICON */ , 0 /* ICON_SMALL */ , 0 );
            Interop.Call( 'user32' , 'SendMessageW' , oChatWd.Handle , 0x80 /* WM_SETICON */ , 1 /* ICON_SMALL */ , 0 );
            Interop.Call ( 'user32' , 'DestroyIcon' , objChatWnds [ oChatWnd.Handle ] );
            delete objChatWnds [ oChatWnd.Handle ];
        }
    }
}


If the image needs to be resized that isn't a problem. Just need to use the GdipGetImageThumbnail call.

This is from Screenshot Sender 5:

Javascript code:
 "CreateThumbnail" : function (hPicture) {
        var ImageThumb = Interop.Allocate(4);
        var lBitmap = Interop.Allocate(4);
        var hbmBitmap = Interop.Allocate(4);
        Interop.Call('gdiplus', 'GdipCreateBitmapFromHBITMAP', hPicture, 0, lBitmap)
        Interop.Call('gdiplus', 'GdipGetImageThumbnail', lBitmap.ReadDWORD(0), 100, this.ImageHeight/(this.ImageWidth/100), ImageThumb.DataPtr, 0, 0);
        Interop.Call('gdiplus', 'GdipCreateHBITMAPFromBitmap', ImageThumb.ReadDWORD(0), hbmBitmap, 0x00000000);
        return  hbmBitmap.ReadDWORD(0);
    }


This post was edited on 10-05-2009 at 02:55 PM by matty.
10-05-2009 02:05 PM
Profile E-Mail PM Find Quote Report
NoWhereMan
Junior Member
**


Posts: 25
Joined: Oct 2009
O.P. RE: [REQ/HELP] Display Picture as Window Icon
Here's an updated version with an (optional) fixed size 16x16 thumb; unfortunately, neither calling it or not calling it seems to be able to make it work :/ (the icon is only cleared)

thank you a lot for your help, though :)

note: with the 32x32 or 48x48 icon available the avatar would be displayed on alt-tab too (and eventually on docks if you have one)

Javascript code:
var objChatWnds = {};
 
function getThumbnailFromPic(hPicture) {
        var ImageThumb = Interop.Allocate(4);
        var lBitmap = Interop.Allocate(4);
        var hbmBitmap = Interop.Allocate(4);
        Interop.Call('gdiplus', 'GdipCreateBitmapFromHBITMAP', hPicture, 0, lBitmap); /* 100, this.ImageHeight/(this.ImageWidth/100), */
        Interop.Call('gdiplus', 'GdipGetImageThumbnail', lBitmap.ReadDWORD(0), 16, 16, ImageThumb.DataPtr, 0, 0);
        Interop.Call('gdiplus', 'GdipCreateHBITMAPFromBitmap', ImageThumb.ReadDWORD(0), hbmBitmap, 0x00000000);
        return  hbmBitmap.ReadDWORD(0);
}
 
function setDpAsIcon ( sDpLocation , oChatWnd ) {
    var GdipToken = Interop.Allocate ( 4 );
    var GdipStartupInput = Interop.Allocate ( 16 );
        GdipStartupInput.WriteDWORD( 0 , 1 );
       
    var bInitialized = Interop.Call( 'gdiplus' , 'GdiplusStartup' , GdipToken , GdipStartupInput , 0 ) === 0;
   
    if ( bInitialized === true ) {
        var nImgPtr = Interop.Allocate ( 4 );
        Interop.Call( 'gdiplus' , 'GdipLoadImageFromFile' , sDpLocation , nImgPtr );
        var hImage = nImgPtr.ReadDWORD ( 0 ) !== 0 ? nImgPtr.ReadDWORD ( 0 ) : false;
       
        if ( hImage !== false ) {
            var hIcon = Interop.Allocate ( 4 );
 
            // uncomment for thumb:
            // hImage = getThumbnailFromPic(hImage);
           
            Interop.Call ( 'gdiplus' , 'GdipCreateHICONFromBitmap' , hImage , hIcon );
            objChatWnds [ oChatWnd.Handle ] = hIcon;
            Interop.Call( 'user32' , 'SendMessageW' , oChatWnd.Handle , 0x80 /* WM_SETICON */ , 0 /* ICON_SMALL */ , hIcon );
            Interop.Call( 'user32' , 'SendMessageW' , oChatWnd.Handle , 0x80 /* WM_SETICON */ , 1 /* ICON_BIG */ , hIcon );
        }
    }
    Interop.Call( 'gdiplus' , 'GdiplusShutdown' , GdipToken.ReadDWORD ( 0 ) );
}
 
function OnEvent_ChatWndCreated ( oChatWnd ) {
    if ( oChatWnd.Contacts.Count === 1 ) {
        for ( var oContact = new Enumerator ( oChatWnd.Contacts ); !oContact.atEnd ( ); oContact.moveNext ( ) ) {
            setDpAsIcon ( oContact.item( ).DisplayPicture , oChatWnd );
        }
    }
}
 
function OnEvent_ChatWndDestroyed ( oChatWnd ) {
    if ( typeof objChatWnds [ oChatWnd.Handle ] === 'object ' ) {
        if ( oChatWnd.Contacts.Count === 1 ) {
            Interop.Call( 'user32' , 'SendMessageW' , oChatWnd.Handle , 0x80 /* WM_SETICON */ , 0 /* ICON_SMALL */ , 0 );
            Interop.Call( 'user32' , 'SendMessageW' , oChatWnd.Handle , 0x80 /* WM_SETICON */ , 1 /* ICON_SMALL */ , 0 );
            Interop.Call ( 'user32' , 'DestroyIcon' , objChatWnds [ oChatWnd.Handle ] );
            delete objChatWnds [ oChatWnd.Handle ];
        }
    }
}

10-05-2009 03:48 PM
Profile E-Mail PM Find Quote Report
NoWhereMan
Junior Member
**


Posts: 25
Joined: Oct 2009
O.P. RE: [REQ/HELP] Display Picture as Window Icon
«An exception was thrown while calling "GdipCreateHICONFromBitmap" in "gdiplus"» :/

EDIT: I think the problem is that function requires a Bitmap struct as input :/

This post was edited on 10-05-2009 at 05:05 PM by NoWhereMan.
10-05-2009 04:46 PM
Profile E-Mail PM Find Quote Report
Matti
Elite Member
*****

Avatar
Script Developer and Helper

Posts: 1646
Reputation: 39
32 / Male / Flag
Joined: Apr 2004
RE: [REQ/HELP] Display Picture as Window Icon
That doesn't work since GdipCreateHICONFromBitmap requires Bitmap to be a GDI+ Bitmap and not a HBITMAP.

However, I managed to get this working by using the code in matty's reply to [REQ/HELP] Display Picture as Window Icon. The only real thing that needed changing was that the hIcon had to be read from the DataBloc before being passed to WM_SETICON or DestroyIcon since those normal Win32 functions use the handle as a regular DWORD. Oh, and of course you made some typos. :P
Javascript code:
var objChatWnds = {};
 
// Let's not forget the already opened chats
function OnEvent_Initialize(MessengerStart) {
    if(Messenger.MyStatus > 0) {
        for( var oChatWnd = new Enumerator ( Messenger.CurrentChats ); !oChatWnd.atEnd ( ); oChatWnd.moveNext ( ) ) {
            OnEvent_ChatWndCreated( oChatWnd.item() );
        }
    }
}
 
// Destroy our generated icons on shutdown
function OnEvent_Uninitialize() {
    for( var hChatWnd in objChatWnds ) {
        Interop.Call ( 'user32' , 'DestroyIcon' , objChatWnds [ oChatWnd.Handle ] );
        delete objChatWnds [ oChatWnd.Handle ];
    }
}
 
// Main function
function setDpAsIcon ( sDpLocation , oChatWnd ) {
    var GdipToken = Interop.Allocate ( 4 );
    var GdipStartupInput = Interop.Allocate ( 16 );
        GdipStartupInput.WriteDWORD( 0 , 1 );
 
    // Initialize GDI+
    var bInitialized = Interop.Call( 'gdiplus' , 'GdiplusStartup' , GdipToken , GdipStartupInput , 0 ) === 0;
 
    if ( bInitialized === true ) {
        // Load a GDI+ Image from the file
        var nImgPtr = Interop.Allocate ( 4 );
        Interop.Call( 'gdiplus' , 'GdipLoadImageFromFile' , sDpLocation , nImgPtr );
        var hImage = nImgPtr.ReadDWORD ( 0 ) !== 0 ? nImgPtr.ReadDWORD ( 0 ) : false;
 
        if ( hImage !== false ) {
            // Get a HICON from the GDI+ Bitmap
            var hIcon = Interop.Allocate ( 4 );
            Interop.Call ( 'gdiplus' , 'GdipCreateHICONFromBitmap' , hImage , hIcon );
            // Read the actual handle and save it
            hIcon = hIcon.ReadDWORD ( 0 );            objChatWnds [ oChatWnd.Handle ] = hIcon;
            // Set the chat window icon
            Interop.Call( 'user32' , 'SendMessageW' , oChatWnd.Handle , 0x80 /* WM_SETICON */ , 0 /* ICON_SMALL */ , hIcon );
            Interop.Call( 'user32' , 'SendMessageW' , oChatWnd.Handle , 0x80 /* WM_SETICON */ , 1 /* ICON_BIG */ , hIcon );
        }
    }
 
    // Shutdown GDI+
    Interop.Call( 'gdiplus' , 'GdiplusShutdown' , GdipToken.ReadDWORD ( 0 ) );
}
 
// Set the icon on new chat windows
function OnEvent_ChatWndCreated ( oChatWnd ) {
    if ( oChatWnd.Contacts.Count === 1 ) {
        var oContact = new Enumerator ( oChatWnd.Contacts ).item();
        setDpAsIcon ( oContact.DisplayPicture , oChatWnd );
    }
}
 
// Remove the icon when a chat window is closed
function OnEvent_ChatWndDestroyed ( oChatWnd ) {
    if ( typeof objChatWnds [ oChatWnd.Handle ] === 'object' ) {
        Interop.Call( 'user32' , 'SendMessageW' , oChatWnd.Handle , 0x80 /* WM_SETICON */ , 0 /* ICON_SMALL */ , 0 );
        Interop.Call( 'user32' , 'SendMessageW' , oChatWnd.Handle , 0x80 /* WM_SETICON */ , 1 /* ICON_SMALL */ , 0 );
        Interop.Call ( 'user32' , 'DestroyIcon' , objChatWnds [ oChatWnd.Handle ] );
        delete objChatWnds [ oChatWnd.Handle ];
    }
}}

Just one small note: when tabbed chats are enabled, the big icon won't show up, but the small ones will still work in the title bar.

Enjoy! ;)

quote:
Originally posted by NoWhereMan
EDIT: I think the problem is that function requires a Bitmap struct as input :/
Luckily, it doesn't.

So my guess would be that the Image class resulted from the loaded file will already be a Bitmap instance, it simply decides which derived class to use based on the type of the loaded file.

quote:
Originally posted by matty
Typos?
Yes, like oChatWd where you want oChatWnd and typeof o === 'object ' where you want typeof o === 'object'. (note the loss of the space between object and ' )
But I'll forgive you because you couldn't test it. :)

This post was edited on 10-05-2009 at 05:35 PM by Matti.
Plus! Script Developer | Plus! Beta Tester | Creator of Countdown Live | Co-developer of Screenshot Sender 5

Found my post useful? Rate me!
10-05-2009 05:26 PM
Profile E-Mail PM Web Find Quote Report
matty
Scripting Guru
*****


Posts: 8336
Reputation: 109
39 / Male / Flag
Joined: Dec 2002
Status: Away
RE: [REQ/HELP] Display Picture as Window Icon
quote:
Originally posted by Matti
That doesn't work since GdipCreateHICONFromBitmap requires Bitmap to be a GDI+ Bitmap and not a HBITMAP.

However, I managed to get this working by using the code in matty's reply to [REQ/HELP] Display Picture as Window Icon. The only real thing that needed changing was that the hIcon had to be read from the DataBloc before being passed to WM_SETICON or DestroyIcon since those normal Win32 functions use the handle as a regular DWORD. Oh, and of course you made some typos. :P
Typos?

And oops... forgot about the DataBloc... as stated untest as I am at work.

This is going to sound like an excuse... however my keyboard has been acting funny. It causes me to return to the previous page, or overwrite previous typed text, or highlight the last letter typed... its fucked. But its intermittent.

This post was edited on 10-05-2009 at 05:38 PM by matty.
10-05-2009 05:31 PM
Profile E-Mail PM Find Quote Report
NoWhereMan
Junior Member
**


Posts: 25
Joined: Oct 2009
O.P. RE: [REQ/HELP] Display Picture as Window Icon
well guys, thank you for the hard work, this is just awesome :)
I updated my first post with a link to the working code. Maybe you'll want to wrap this thing up and submit it on the main site :)

EDIT: screenie in first post for added awesomeness

This post was edited on 10-05-2009 at 07:17 PM by NoWhereMan.
10-05-2009 05:47 PM
Profile E-Mail PM Find Quote Report
ryxdp
Senior Member
****


Posts: 804
Reputation: 16
30 / Male / Flag
Joined: Jun 2006
RE: [REQ/HELP] Display Picture as Window Icon
Cool script, thanks matti, but what about when the contact has no display picture? I've added to the code a bit (for my own use unless you want me to share it :P) to use the WLM9 image for no DP. It doesn't seem to like transparency much so I put a white layer under the actual image so it looks a bit better.

Also, what about when the contact changes their DP mid-conversation? I guess all that can be done is put a timer on there that goes off every 15 seconds or so and checks the path against the current stored data.
10-06-2009 01:35 AM
Profile PM Find Quote Report
NoWhereMan
Junior Member
**


Posts: 25
Joined: Oct 2009
O.P. RE: [REQ/HELP] Display Picture as Window Icon
quote:
Originally posted by ryxdp
Also, what about when the contact changes their DP mid-conversation? I guess all that can be done is put a timer on there that goes off every 15 seconds or so and checks the path against the current stored data.


I wouldn't poll the filesystem just for that. I would just ignore the change; your DP will be updated the next time you close and re-open the chat window anyway :)
10-06-2009 06:26 AM
Profile E-Mail PM Find Quote Report
ryxdp
Senior Member
****


Posts: 804
Reputation: 16
30 / Male / Flag
Joined: Jun 2006
RE: RE: [REQ/HELP] Display Picture as Window Icon
quote:
Originally posted by NoWhereMan
I wouldn't poll the filesystem just for that. I would just ignore the change; your DP will be updated the next time you close and re-open the chat window anyway :)

It sort of is the whole point of the script, but yeah, you're probably right. Anyway, maybe 15 seconds would have been a bit too fast; perhaps a minute or five might be more appropriate :P
10-06-2009 07:19 AM
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