WM_GETICON not working (Windows)
Asked Answered
M

2

2

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();
Must answered 4/6, 2014 at 21:0 Comment(3)
May I ask if the objective is to get the icon of firefox.exe?Kevenkeverian
Originally it was but im skipping that now. I then moved to ExtractIconEx but then I realized just get the icon path packaged and no need to extract icons with js-ctypes. So now this is just out of curiosity.Must
Thank you all for undoing the down rep i got for this. Appreciate it guys.Must
D
6

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);
  }
Deutzia answered 5/6, 2014 at 5:17 Comment(4)
Sincere thanks man! I'm going to put this on hold for now as for my addon i just need the paths to the firefox icon png and ill put it on canvas then badge it then save to ico then set the icon. But I'm going to revisit this out of curiousity later. :)Must
So what you're saying is that you deliberately want to break my precious, superbly designed custom window icons that some of my add-ons use in their windows? :pDeutzia
Ah hahahaha. That's what I was worried about. But then I thought maybe people don't have custom icons. Thanks for letting me know man. :)Must
Just a curiosity thing here: how come you didn't do this ins js-ctypes in mintrar addon? Is it performance reasons or something?Must
K
1

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.

Kevenkeverian answered 5/6, 2014 at 9:32 Comment(7)
Super super! Thanks man!! This is the answer to my q here: ask.mozilla.org/question/751/path-to-the-builds-iconMust
How did you find that out man? Also does that return like a png?Must
Man the quality on the icon obtained this way for the 16 is noticeably poor, do you notice the same? The 32px one is good. I'm using WinXP Ill test this on Win7 and see whats up.Must
Branding folder seems to have high quality icons: mxr.mozilla.org/mozilla-release/source/browser/branding/nightly/… but how to get them at different sizes without blurring them?Must
I needed to do this because i was making a shortcut to firefox with the default icon of the firefox.exe :(Must
I was under the impression that querying the executable file through moz-icon would produce the relevant icon. Apparently this true only for Windows executables.Kevenkeverian
Thanks man for the confirmation I was wondering maybe i messed up. Just to double check, the issue isn't that I supplied 16 as size for linux and mac is it? I didnt try other sizes. Ill have to try today.Must

© 2022 - 2024 — McMap. All rights reserved.