Skip to content

Instantly share code, notes, and snippets.

@Noitidart
Last active August 29, 2015 14:02
Show Gist options
  • Save Noitidart/33b6d28ebf4ff5ebdff6 to your computer and use it in GitHub Desktop.
Save Noitidart/33b6d28ebf4ff5ebdff6 to your computer and use it in GitHub Desktop.
_ff-addon-snippet-ChangeWindowIcon - Uses js-ctypes to change the icon of a window. (Windows Only)
Cu.import('resource://gre/modules/ctypes.jsm');
var user32 = ctypes.open('user32.dll');
/* http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950%28v=vs.85%29.aspx
* LRESULT WINAPI SendMessage(
* __in HWND hWnd,
* __in UINT Msg,
* __in WPARAM wParam,
* __in LPARAM lParam
* );
*/
var SendMessage = user32.declare('SendMessageW', ctypes.winapi_abi, ctypes.uintptr_t,
ctypes.int32_t,
ctypes.unsigned_int,
ctypes.int32_t,
ctypes.voidptr_t
);
/* http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045%28v=vs.85%29.aspx
* HANDLE WINAPI LoadImage(
* __in_opt_ HINSTANCE hinst,
* __in_ LPCTSTR lpszName,
* __in_ UINT uType,
* __in_ int cxDesired,
* __in_ int cyDesired,
* __in_ UINT fuLoad
* );
*/
var LoadImage = user32.declare('LoadImageA', ctypes.winapi_abi, ctypes.voidptr_t,
ctypes.int,
ctypes.char.ptr,
ctypes.unsigned_int,
ctypes.int,
ctypes.int,
ctypes.unsigned_int
);
var IMAGE_BITMAP = 0;
var IMAGE_ICON = 1;
var LR_LOADFROMFILE = 16;
// RUNNING STUFF BELOW - ABVOE WAS JUST DEFINING STUFF
var basewindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.treeOwner
.QueryInterface(Ci.nsIInterfaceRequestor)
.nsIBaseWindow;
var nativeHandle = basewindow.nativeHandle;
var targetWindow_handle = parseInt(nativeHandle);
var hIconBig = LoadImage(targetWindow_handle, 'C:\\Documents and Settings\\SONY VAIO\\My Documents\\Downloads\\puzzle.ico', IMAGE_ICON, 256, 256, LR_LOADFROMFILE); //MUST BE A FILEPATH TO A ICO!!!
var hIconSmall = LoadImage(targetWindow_handle, 'C:\\Documents and Settings\\SONY VAIO\\My Documents\\Downloads\\puzzle.ico', IMAGE_ICON, 16, 16, LR_LOADFROMFILE); //MUST BE A FILEPATH TO A ICO!!!
var successSmall = SendMessage(targetWindow_handle, 0x0080 /** WM_SETICON **/ , 0 /** ICON_SMALL **/ , hIconSmall); //if it was success it will return 0? im not sure. on first time running it, and it was succesful it returns 0 for some reason
var successBig = SendMessage(targetWindow_handle, 0x0080 /** WM_SETICON **/ , 1 /** ICON_BIG **/ , hIconBig); //if it was success it will return 0? im not sure. on first time running it, and it was succesful it returns 0 for some reason
var me = Services.wm.getMostRecentWindow(null);
me.alert(successSmall);
me.alert(successBig);
user32.close();
@Noitidart
Copy link
Author

README

Rev1

  • Copy pasting this and running in scratchpad will change the icon of the main browser window that was most recently used but you have to have icon at path C:\Documents and Settings\SONY VAIO\My Documents\Downloads\puzzle.ico (or you have to change this path)
  • Second argument of LoadImage must be a path to a .ico
  • I'm not sure what SendMessage returns on success. Right now it returns 0 on first run and a long number on consequent runs using same ico path
  • I downloaded and used the icon IconArchive :: Blue Bits Icons by Icojam - Puzzle [Download ICO]
  • I left in some debug messages: alert and var me = Services.wm.getMostRecent...
  • Issues On WinXP
    • When press Alt + Tab the icon is the normal one
    • If windows are lumped into one group (because of taskbar overflow) and ALL icons are changed, the lumped group icon is still not the changed one. As seen in image here:
      _ff-addon-snippet-ChangeWindowIcon.js - Rev1 -- WinXP lumped icon issue.PNG
  • Issues On Win7
    • If the application IS PINNED and even if all windows icons are changed to be the same, it still does not changed the pin icon
    • If the application is NOT PINNED then if change the icon for all windows it will change the icon on the taskbar HOWEVER if you right click on the icon in the taskbar it reverts to what it was normally and running the snippet above again won't set it back, to get it back to icon you set you have to pin and unpin
  • Idea from StackOverflow :: Problems with setting application icon

Rev2

  • Removed reliance on FindWindow made it use nativeHandle now
  • Removed the SetForegroundWindow debug part as that was to test if I had got the right window but with nativeHandle I now know for sure I got the right handle
  • All issues from Rev1 are still outstanding

Rev3

  • Removed debug messages
  • Made it use nsIWindowsMediator to apply to all windows
  • All issues from Rev1 are still outstanding

Rev4

  • Doing parseInt on nativeHandle is wrong because nativeHandle might be a 64-bit pointer. Also js numbers are floats.
  • All issues from Rev1 are still outstanding

@nmaier
Copy link

nmaier commented Jun 4, 2014

@nmaier
Copy link

nmaier commented Jun 4, 2014

I would actually change the title to some uuid and only then find the window in production code, to avoid running into problems when two windows have the same name.

@nmaier
Copy link

nmaier commented Jun 4, 2014

@Noitidart
Copy link
Author

Thanks man, this is the code I'm using to set it on all windows. But I'm running into problems. If I uncomment the Services.wm.getMostRecentWindow(null).alert(aDOMWindow.document.documentElement.getAttribute('title')); then it doesn't work. It's so weird.

Here's the code:

Cu.import('resource://gre/modules/ctypes.jsm');

var user32 = ctypes.open('user32.dll');

var FindWindow = user32.declare('FindWindowW', ctypes.winapi_abi, ctypes.int32_t,
    ctypes.jschar.ptr,
    ctypes.jschar.ptr
);

var SendMessage = user32.declare('SendMessageW', ctypes.winapi_abi, ctypes.uintptr_t,
    ctypes.int32_t,
    ctypes.unsigned_int,
    ctypes.int32_t,
    ctypes.voidptr_t
);

var LoadImage = user32.declare('LoadImageA', ctypes.winapi_abi, ctypes.voidptr_t,
    ctypes.int,
    ctypes.char.ptr,
    ctypes.unsigned_int,
    ctypes.int,
    ctypes.int,
    ctypes.unsigned_int
);

var IMAGE_BITMAP = 0;
var IMAGE_ICON = 1;
var LR_LOADFROMFILE = 16;


// RUNNING STUFF BELOW - ABVOE WAS JUST DEFINING STUFF
var DOMWindows = Services.wm.getEnumerator(null);
while (DOMWindows.hasMoreElements()) {
    var aDOMWindow = DOMWindows.getNext();
    var targetWindow_title = aDOMWindow.document.documentElement.getAttribute('title');
    var targetWindow_titleOriginal = targetWindow_title;
    targetWindow_title += ' - Profilist Iconing Proc';
    aDOMWindow.document.documentElement.setAttribute('title', targetWindow_title);

    Services.wm.getMostRecentWindow(null).alert(aDOMWindow.document.documentElement.getAttribute('title'));

    var targetWindow_handle = FindWindow(null, targetWindow_title);

    var hIconBig = LoadImage(targetWindow_handle, 'C:\\Documents and Settings\\SONY VAIO\\My Documents\\Downloads\\puzzle.ico', IMAGE_ICON, 256, 256, LR_LOADFROMFILE); //MUST BE A FILEPATH TO A ICO!!!
    var hIconSmall = LoadImage(targetWindow_handle, 'C:\\Documents and Settings\\SONY VAIO\\My Documents\\Downloads\\puzzle.ico', IMAGE_ICON, 16, 16, LR_LOADFROMFILE); //MUST BE A FILEPATH TO A ICO!!!

    var successSmall = SendMessage(targetWindow_handle, 0x0080 /** WM_SETICON **/ , 0 /** ICON_SMALL **/ , hIconSmall); //if it was success it will return 0? im not sure. on first time running it, and it was succesful it returns 0 for some reason
    var successBig = SendMessage(targetWindow_handle, 0x0080 /** WM_SETICON **/ , 1 /** ICON_BIG **/ , hIconBig); //if it was success it will return 0? im not sure. on first time running it, and it was succesful it returns 0 for some reason   

    aDOMWindow.document.documentElement.setAttribute('title', targetWindow_titleOriginal);
}

user32.close();

@Noitidart
Copy link
Author

Oh I think I know the problem with what I just posted. After I do setAttribute on the window title it takes a little while before it registers with windows?

@Noitidart
Copy link
Author

Committed Rev2

@Noitidart
Copy link
Author

Hey man it was definitely the problem where when I set the title of the window, then ran FindWindow right after that, it was not finding the window because it takes a little bit after the setting of title for it to register on OS. I updated in Rev2 to use nativeHandle so that's fixed now. :)

@Noitidart
Copy link
Author

Committed Rev3

@Noitidart
Copy link
Author

Committed Rev4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment