?
Solved

Change another app's icon.

Posted on 2000-04-18
38
Medium Priority
?
359 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 20
  • 8
  • 4
  • +4
38 Comments
 
LVL 5

Expert Comment

by:TheNeil
ID: 2726355
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
ID: 2726357
Is that the only way of doing it Neil?  (Do you know?)

John.
0
 
LVL 6

Author Comment

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

John.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 4

Expert Comment

by:jeurk
ID: 2726376
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
ID: 2726386
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
ID: 2726409
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
ID: 2726425
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
ID: 2726479
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
ID: 2726495
I'll have a go and come back.

Ta.
0
 
LVL 20

Expert Comment

by:Madshi
ID: 2726506
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
ID: 2726538
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
ID: 2726540
Thanks Madshi but, woooooshhhh!!!! It went right over my head that did!

John.
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 2726553
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
ID: 2726579
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
ID: 2726597
Ignore that last pathetic comment I made!  I've just done that myself.

John.
0
 
LVL 6

Author Comment

by:Jaymol
ID: 2726624
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
ID: 2726659
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
ID: 2726682
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
ID: 2726765
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
 
LVL 6

Author Comment

by:Jaymol
ID: 2726797
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
ID: 2726894
Well, I'm not 100% sure, but I guess so...   :-(
0
 
LVL 6

Author Comment

by:Jaymol
ID: 2726905
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 1600 total points
ID: 2727710
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
ID: 2729748
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
ID: 2729755
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
ID: 2729805
BANDWAGON!!!!
0
 
LVL 6

Author Comment

by:Jaymol
ID: 2729827
Adjusted points from 150 to 400
0
 
LVL 6

Author Comment

by:Jaymol
ID: 2729833
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
ID: 2729886
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
ID: 2730101
If I do stuff, I'll keep you posted mate.

Thanks again Neil,

John.
0
 

Expert Comment

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

Expert Comment

by:New2Delphi
ID: 6459639
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
ID: 6459816
Neil, can you sort this out for him?

John.
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 6459869
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
ID: 6459875
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
ID: 6465861
It's lost? Please help me. Thanks!
0
 

Expert Comment

by:New2Delphi
ID: 6467996
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
ID: 7760137
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

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.
Suggested Courses

764 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