Solved

Change another app's icon.

Posted on 2000-04-18
38
352 Views
Last Modified: 2010-04-04
Hi.  I want to change the icon of a running application (NOT my application.)  I want to be able to use my own icon for notepad (for example.)

I can set the window size, title, etc., but can't figure out the icon.

I've put this at 150 points cos I think it's not particularly easy, and I also want an example of it.  Like I said, just an example that shows notepad with a different icon.

Thanks,

John.
0
Comment
Question by:Jaymol
  • 20
  • 8
  • 4
  • +4
38 Comments
 
LVL 5

Expert Comment

by:TheNeil
Comment Utility
There is a nasty way to do this...

Search through the exe at a byte level and replace the icon data with a new one. Sadly you have to do it before the exe starts, and it's permanent - looks pretty though

The Neil =;)
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Is that the only way of doing it Neil?  (Do you know?)

John.
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Also, is the icon always in the same location, or is there a particular way of locating it in the exe?

John.
0
 
LVL 4

Expert Comment

by:jeurk
Comment Utility
hello,
you mean at runtime ??
they must be another way because programs like windowsblinds are doing it.
must I think this involves using a system wide hook, or such hard stuff. I don't know how to do this...
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
I'm quite happy to do it Neil's way, as long as I know where the icon is in the executable and what format to write it.

John.
0
 
LVL 5

Expert Comment

by:TheNeil
Comment Utility
John,

I wasn't serious but if you really want to know (and there's probably a far better way than this)...

Extract the program's icon and then search through the EXE looking for the same set of bytes as the icon. At the same time you need to be copying the bytes that AREN'T what you want across into another file. When you hit the bytes that you DO want, write out the new byte pattern (which must be the same length), ignoring the bytes of the original icon. Then just copy across all the other bytes and copy your new file over the old one. It's a few years since I actually hacked a piece of code like this together (and I don't know where the source is) but I think the data MIGHT be stored backwards and you have to allow for the mask as well as the image

The Neil
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
That doesn't sound too troublesome, but I could do with some help regarding the format of the icon.  I'm basically going to be opening an executable that I've not touched before and supposed to be able to find the icon within it.  I can't leave any part of this down to manual operation - It has to all be automatic, as in "Put new icon in file X", and that's it!

John.
0
 
LVL 5

Expert Comment

by:TheNeil
Comment Utility
John,

Below is some code for extracting an icon from an EXE and when you read through the algorithm then you'll realise why I included it.

What you need to do is:

1.Extract the icon from the EXE that you're interested in (see the code below)
2.Load the extracted icon into an array of byte
3.Open the EXE file as FILE OF BYTE
4.Read bytes from the EXE file looking for a match with your array of stored icon data
5.When you match the set of data (the ENTIRE set, don't make any assumptions) copy your new icon file in (make sure that they're the same size by the way or you're in trouble)
6.Copy the rest of the EXE file across byte by byte

You can speed the whole thing up by using memory streams but I was useless when I did it and just stuck to files.

The Neil =:)

type ThIconArray = array[0..0] of hIcon;
type PhIconArray = ^ThIconArray;

function ExtractIconExA(lpszFile: PAnsiChar;
                        nIconIndex: Integer;
                        phiconLarge : PhIconArray;
                        phiconSmall: PhIconArray;
                        nIcons: UINT): UINT; stdcall;
  external 'shell32.dll' name 'ExtractIconExA';


function ExtractIconExW(lpszFile: PWideChar;
                        nIconIndex: Integer;
                        phiconLarge: PhIconArray;
                        phiconSmall: PhIconArray;
                        nIcons: UINT): UINT; stdcall;
  external 'shell32.dll' name 'ExtractIconExW';

function ExtractIconEx(lpszFile: PAnsiChar;
                       nIconIndex: Integer;
                       phiconLarge : PhIconArray;
                       phiconSmall: PhIconArray;
                       nIcons: UINT): UINT; stdcall;
  external 'shell32.dll' name 'ExtractIconExA';


procedure TForm1.Button1Click(Sender: TObject);
var
    NumIcons : integer;
    pTheLargeIcons : phIconArray;
    pTheSmallIcons : phIconArray;
    LargeIconWidth : integer;
    SmallIconWidth : integer;
    SmallIconHeight : integer;
    i : integer;
    TheIcon : TIcon;
    TheBitmap : TBitmap;
begin
  NumIcons :=
  ExtractIconEx('C:\Program Files\Borland\Delphi 3\BIN\delphi32.exe',
                -1,
                nil,
                nil,
                0);
  if NumIcons > 0 then begin
    LargeIconWidth := GetSystemMetrics(SM_CXICON);
    SmallIconWidth := GetSystemMetrics(SM_CXSMICON);
    SmallIconHeight := GetSystemMetrics(SM_CYSMICON);
    GetMem(pTheLargeIcons, NumIcons * sizeof(hIcon));
    GetMem(pTheSmallIcons, NumIcons * sizeof(hIcon));
    FillChar(pTheLargeIcons^, NumIcons * sizeof(hIcon), #0);
    FillChar(pTheSmallIcons^, NumIcons * sizeof(hIcon), #0);
   ExtractIconEx('C:\Program Files\Borland\Delphi 3\BIN\delphi32.exe',
                  0,
                  pTheLargeIcons,
                  pTheSmallIcons,
                  numIcons);
   {$IFOPT R+}
     {$DEFINE CKRANGE}
     {$R-}
   {$ENDIF}
    for i := 0 to (NumIcons - 1) do begin
      DrawIcon(Form1.Canvas.Handle,
               i * LargeIconWidth,
               0,
               pTheLargeIcons^[i]);
      TheIcon := TIcon. Create;
      TheBitmap := TBitmap.Create;
      TheIcon.Handle := pTheSmallIcons^[i];
      TheBitmap.Width := TheIcon.Width;
      TheBitmap.Height := TheIcon.Height;
      TheBitmap.Canvas.Draw(0, 0, TheIcon);
      TheIcon.Free;
      Form1.Canvas.StretchDraw(Rect(i * SmallIconWidth,
                                    100,
                                    (i + 1) * SmallIconWidth,
                                    100 + SmallIconHeight),
                               TheBitmap);
      TheBitmap.Free;
    end;
   {$IFDEF CKRANGE}
     {$UNDEF CKRANGE}
     {$R+}
   {$ENDIF}
    FreeMem(pTheLargeIcons, NumIcons * sizeof(hIcon));
    FreeMem(pTheSmallIcons, NumIcons * sizeof(hIcon));
  end;
end;

end.
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
I'll have a go and come back.

Ta.
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
It's possible during runtime, too. Probably you would have to use SetClassLong(GCL_HICON, ...). But the problem is: You have to call this API from inside notepad. That again means you have to inject a little DLL into notepad's process, then in this DLL you can call SetClassLong. Injecting can be done e.g. by misusing SetWindowsHookEx. Quite difficult stuff.

Regards, Madshi.
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Could you do us a favour and cut that down to just extracting the 1st small icon?  (I'm assuming that that's the one that you see on the taskbar.)

John.
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Thanks Madshi but, woooooshhhh!!!! It went right over my head that did!

John.
0
 
LVL 5

Expert Comment

by:TheNeil
Comment Utility
John,

Hmmm. Not sure if I can. It all depends on the EXE that you're trying to change - some don't have 16x16 icons and Windows scales the 32x32 one down.

The Neil
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Would it be possible then to get both the 1st small and the 1st large?  (If there is no small one then the large one is used!)

John.
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Ignore that last pathetic comment I made!  I've just done that myself.

John.
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Neil : Okay then, can you do me a little example of a prog that returns the size and location of the TaskBar icon within an EXE?  If you do this for me, I'll bump the points up to 400 and grade it Excellent so they bump up even more.  Would you do that for us?

John.
0
 
LVL 5

Expert Comment

by:TheNeil
Comment Utility
No can do I'm afraid. Inside the EXE can be several icons and ExtractIconsEx will get them all - it won't know which one is being used for the tray icon. I'll have a think and see what I can come up (no promises)

Wouldn't have minded those points either...

The Neil =:(
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
I don't actually mean the tray icon - I mean the Task Manager icon (Alt+Tab icon).  That'd be the 1st biggun wouldn't it?

John.
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
I don't think it has to be the first one. It depends on what the application gives into the API "RegisterClass". It may be the first icon from the resources, it may be the last icon from the resources, it may even be an external ico file or something completely different...   :-(
Sorry for posting such sad infos.

Regards, Madshi.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Madshi - are you saying that it's not possible unless you go down that nasty path that you mentioned earlier?  (Something about Captain Hook.)

John.
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Well, I'm not 100% sure, but I guess so...   :-(
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Damn it!

I'll leave the question here till tomorrow and then delete it if there's no reasonable answer.

Thanks anyway everyone.

John.
0
 
LVL 5

Accepted Solution

by:
TheNeil earned 400 total points
Comment Utility
John,

I have the source for an app I wrote a few years ago that rips through an EXE and can modify the icon (and any other string of data actually). Give me your email and I'll send it through (if you want it)

The Neil =;)
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Neil, you are a beauty!!!

If this program makes me smile, I'll give you the points I referred to previously!

My email is....

      JayMol@Pu-Nani.co.uk

That's due to the fact that when I'm not programming, I just Looooove to ride it!

Thanks,

John.
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Hey The Neil, this sounds interesting! Would you mind sending me this program, too? That would be kind...    :O)

madshi@gmx.net
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
BANDWAGON!!!!
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Adjusted points from 150 to 400
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Thanks for your help Neil.  As I said, here's your points.  (I am a man of my word!)

Thanks again.

John.
0
 
LVL 5

Expert Comment

by:TheNeil
Comment Utility
Do you mean the stupid thing actually worked? I am quite amazed seeing as I wrote this way back in the dim distant past when I was remotely intelligent (unlike now when I'm just brain dead). There are probably loads of ways to optimise it and if you do then I'd appreciate an updated version

It works, it works... <stunned disbelief>

The Neil =:0
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
If I do stuff, I'll keep you posted mate.

Thanks again Neil,

John.
0
 

Expert Comment

by:lingxin
Comment Utility
TheNeil
your example is wrong.
give me
delphi2000@soim.com
0
 

Expert Comment

by:New2Delphi
Comment Utility
TheNeil or Jaymol, I have purchased this question and have found out that the answer I was looking for was sent through e-mail. Would you be so kind as to send me the Project. I would really appreciate it. My e-mail address is syndromecrew@yahoo.com. Thank you!
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Neil, can you sort this out for him?

John.
0
 
LVL 5

Expert Comment

by:TheNeil
Comment Utility
I'll have a hunt around and find the ZIP. Give me a couple of days though as this will be archived away somewhere (and I don't know where)

The Neil =:)
0
 
LVL 6

Author Comment

by:Jaymol
Comment Utility
Same here, or I'd send it now.

If you don't find it, let me know and I'll see what I can do.

John.
0
 

Expert Comment

by:New2Delphi
Comment Utility
It's lost? Please help me. Thanks!
0
 

Expert Comment

by:New2Delphi
Comment Utility
Jaymol or The Neil, why doesn't BinaryReplace.exe seem to work? I have tried it several times and it always says the same error message over and over: "Data could not be located. No changes have been made." Please help! Thanks!
0
 

Expert Comment

by:ashrafsalah
Comment Utility
Hey The Neil, this sounds great! Would you mind sending me this program, too? That would be kind...    :O)

ashraf@al-waha.net
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now