[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
(sw in screenie: switcher)
This post was edited on 10-05-2009 at 06:15 PM by NoWhereMan.
|
|
10-04-2009 02:57 PM |
|
|
matty
Scripting Guru
Posts: 8336 Reputation: 109
39 / /
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!
js 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:
js 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 |
|
|
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 |
|
|
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 |
|
|
Matti
Elite Member
Script Developer and Helper
Posts: 1646 Reputation: 39
32 / /
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.
js 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.
|
|
10-05-2009 05:26 PM |
|
|
matty
Scripting Guru
Posts: 8336 Reputation: 109
39 / /
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.
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 |
|
|
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 |
|
|
ryxdp
Senior Member
Posts: 804 Reputation: 16
29 / /
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 ) 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 |
|
|
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 |
|
|
ryxdp
Senior Member
Posts: 804 Reputation: 16
29 / /
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
|
|
10-06-2009 07:19 AM |
|
|
Pages: (2):
« First
[ 1 ]
2
»
Last »
|
|
|