Question

If I don't use WM_SETICON first to set the icon then WM_GETICON is always returning 0. This is weird. Please help.

This is my code, can copy paste into scratchpad and run.

When doing SendMessage(targetWindow_handle, WM_GETICON , ICON_SMALL, ctypes.voidptr_t(0)), hIconSmall_orig and hIconBig_orig is always returning 0 I have no idea why. IF you go WM_SETICON on the window first then it properly gets the HICON but the whole purpose is to get the default icon.

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.voidptr_t,
    ctypes.unsigned_int,
    ctypes.int32_t,
    ctypes.voidptr_t
);

var WM_GETICON = 0x007F;
var WM_SETICON = 0x0080;
var ICON_SMALL = 0;
var ICON_BIG = 1;
var ICON_SMALL2 = 2; //for use with WM_GETICON only, not applicable to WM_SETICON

// 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 = ctypes.voidptr_t(ctypes.UInt64(nativeHandle));

var hIconSmall_orig = SendMessage(targetWindow_handle, WM_GETICON , ICON_SMALL, ctypes.voidptr_t(0));
var hIconBig_orig = SendMessage(targetWindow_handle, WM_GETICON , ICON_BIG, ctypes.voidptr_t(0));
Services.wm.getMostRecentWindow(null).alert('hIconSmall_orig = ' + hIconSmall_orig + '\nhIconBig_orig = ' + hIconBig_orig);

user32.close();
Was it helpful?

Solution

Since you got the WM_GETICON stuff from me (in another answer to another question) let me first say: It has been a while... So I forgot that WM_GETICON will return null when the window has no particular window icon assigned, but instead the icon is taken from the registered window class.

So you should:

  1. Check WM_GETICON to see if the window has a specific icon assigned.
  2. Check the class by GetClassLongPtr(hwnd, GCLP_HICON /* or GCLP_HICONSM */)
  3. If that fails, you can always try to load the main icon from the .exe
  4. If that fails, you can always try to load a stock icon.

Here is some C++ code which I use to actually get an icon from a window in my "mintrayr" extension:

  // Get the window icon
  HICON icon = reinterpret_cast<HICON>(::SendMessageW(hwnd, WM_GETICON, ICON_SMALL, 0));
  if (icon == 0) {
    // Alternative method. Get from the window class
    icon = reinterpret_cast<HICON>(::GetClassLongPtrW(hwnd, GCLP_HICONSM));
  }
  // Alternative method: get the first icon from the main module (executable image of the process)
  if (icon == 0) {
    icon = ::LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(0));
  }
  // Alternative method. Use OS default icon
  if (icon == 0) {
    icon = ::LoadIcon(0, IDI_APPLICATION);
  }

OTHER TIPS

Well, there is a surprisingly easy (and cross-platform) way to retrieve the default icon of Firefox.

var foxexe = FileUtils.getFile("XREExeF", []);
var iconurl = "moz-icon:" + Services.io.newFileURI(foxexe).spec;

You can treat iconurl the same way as any other image-pointing url. The default size is 16x16, append ?size=32 to get a bigger icon. It seems that these two values are the only supported on Windows. This might not be the case for other OSes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top