修改程序的图片

发现网上的程序都是修改程序图标的,心血来潮,决定写一个修改窗口背景图片的程序。先写一个简单的程序,该程序只有一个窗体,且资源中只有一张大图片(BMP背景图片)。听说高手都喜欢写控制台程序,我也建一个(冒充一次高手),将先前写好的程序加入资源中(同样为了有点神秘感),想像是,在控制台打入我的程序名,回车,一下就生成一个被修改了背景图片的程序,够酷吧>_<

以下是VC代码:


#include<windows.h>
#include<iostream>
#include<cstring>
//#include<io.h>
#include "resource.h"

using namespace std;

void main(int argc,char *argv[])
{
 if(argc!=2)
 {
  cout<<"  Usage:modify bitmap.bmp"<<endl;
  return;
 }

 char bmpFileName[_MAX_FNAME];
 strcpy(bmpFileName,argv[1]);

 LPOFSTRUCT bmpInfo=new OFSTRUCT();
 HANDLE hBmpFile=CreateFile(bmpFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
 if(hBmpFile==INVALID_HANDLE_VALUE)//access(bmpFileName,0))
 {
  cout<<"The file "<<bmpFileName<<" is not exist!"<<endl;
  return;
 }
 DWORD bmpSize=GetFileSize(hBmpFile,0);

 HRSRC hrsrc=FindResource(NULL,MAKEINTRESOURCE(IDR_MAINWNDEXE1),"MAINWNDEXE");
 DWORD EXEResSize=SizeofResource(NULL,hrsrc);
 HGLOBAL adrExeResource=LoadResource(NULL,hrsrc);
 unsigned char *lpEXEResource=(unsigned char *)LockResource(adrExeResource);

 if(!lpEXEResource)
 {
  cout<<"Load resource failed!"<<endl;
  return;
 }

 //
 IMAGE_DOS_HEADER *dosHeaderA=(IMAGE_DOS_HEADER *)lpEXEResource;
 IMAGE_NT_HEADERS *ntHeaderA=(IMAGE_NT_HEADERS *)(lpEXEResource+dosHeaderA->e_lfanew);
 IMAGE_SECTION_HEADER *secHeaderA=(IMAGE_SECTION_HEADER *)((char *)ntHeaderA+sizeof(IMAGE_NT_HEADERS));

 for(int i=0;i<ntHeaderA->FileHeader.NumberOfSections;i++,secHeaderA++)
 {
  if(strcmp((char *)secHeaderA->Name,".rsrc")==0)
   break;
 }
 
 IMAGE_RESOURCE_DIRECTORY *dirResourceA=(IMAGE_RESOURCE_DIRECTORY *)(lpEXEResource+secHeaderA->PointerToRawData);
 
 IMAGE_RESOURCE_DIRECTORY_ENTRY *first,*second,*third;
 IMAGE_RESOURCE_DIRECTORY *tmpDirRes;
 IMAGE_RESOURCE_DATA_ENTRY *lpFirstBmpData;

 first=(IMAGE_RESOURCE_DIRECTORY_ENTRY *)((unsigned char *)dirResourceA+sizeof(IMAGE_RESOURCE_DIRECTORY));
 for(i=0;i<dirResourceA->NumberOfIdEntries+dirResourceA->NumberOfNamedEntries;i++,first++)
 {
  if(first->Name==2)
  {
   tmpDirRes=(IMAGE_RESOURCE_DIRECTORY *)((unsigned char *)dirResourceA+first->OffsetToDirectory);
   second=(IMAGE_RESOURCE_DIRECTORY_ENTRY *)((unsigned char *)tmpDirRes+sizeof(IMAGE_RESOURCE_DIRECTORY));
   for(int j=0;j<tmpDirRes->NumberOfIdEntries+tmpDirRes->NumberOfNamedEntries;j++,second++)
   {
    //find first bitmap
    if(second->DataIsDirectory>0)
    {
     tmpDirRes=(IMAGE_RESOURCE_DIRECTORY *)((unsigned char *)dirResourceA+second->OffsetToDirectory);
     third=(IMAGE_RESOURCE_DIRECTORY_ENTRY *)((unsigned char *)tmpDirRes+sizeof(IMAGE_RESOURCE_DIRECTORY));
     
     lpFirstBmpData=(IMAGE_RESOURCE_DATA_ENTRY *)((unsigned char *)dirResourceA+third->OffsetToData);
     break;
    }
   }

  }
 }

 //change bitmap;
 unsigned char* addrOldBmp=(unsigned char *)dirResourceA+lpFirstBmpData->OffsetToData-secHeaderA->VirtualAddress;
 DWORD oldBmpSize=lpFirstBmpData->Size;
 //lpFirstBmpData->Size=bmpSize-0xe+6;         //发现BMP资源比原始BMP文件在文件头少了一些数据,怀疑是BMP文件标识。且资源尾部有6个字节都为0的数据,而原BMP没有,不得其解

 HANDLE hNewExe=CreateFile("MainWnd.exe",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
 if(!hNewExe)
 {
  cout<<"Create MainWnd.exe failed!"<<endl;
  return;
 }

 //¸´ÖÆEXEÎļþÖÁÒªÐÞ¸Ä×ÊÔ´µÄλÖÃ
 DWORD leftSize=EXEResSize;

 DWORD bytesWritten;
 BOOL result=WriteFile(hNewExe,lpEXEResource,addrOldBmp-lpEXEResource,&bytesWritten,NULL);
 if(!result)
 {
  cout<<"Write file failed!"<<endl;
  return;
 }
 else
  leftSize-=bytesWritten;

 //¸´ÖÆÐÂ×ÊÔ´
 DWORD bytesRead;
 const BUFSIZE=256;
 unsigned char readBuf[BUFSIZE];
 //È¥³ý0xe¸öÎļþÍ·
 result=ReadFile(hBmpFile,readBuf,0xe,&bytesRead,NULL);
 if(!result || bytesRead!=0xe)
 {
  cout<<"Read file failed!"<<endl;
  return;
 }


 DWORD bytesWillWrite=0;
 do
 {
  result=ReadFile(hBmpFile,readBuf,BUFSIZE,&bytesRead,NULL);
  if(!result)
  {
   cout<<"Read file failed!"<<endl;
   return;
  }
  
  if(bytesRead==0)
   break;

  result=WriteFile(hNewExe,readBuf,bytesRead,&bytesWritten,NULL);
  if(!result)
  {
   cout<<"Write file failed!"<<endl;
   return;
  }

 }while(bytesRead>0);
 
 /*/дÈë6¸ö×Ö½ÚµÄ0
 memset(readBuf,0,BUFSIZE);
 result=WriteFile(hNewExe,readBuf,6,&bytesWritten,NULL);
 if(!result)
 {
  cout<<"Write file failed!"<<endl;
  return;
 }*/

 

 //½áÊøÐÞ¸Ä×ÊÔ´,¼ÌÐø¸´ÖÆEXEÎļþ
 leftSize-=oldBmpSize;

 result=WriteFile(hNewExe,addrOldBmp+oldBmpSize,leftSize,&bytesWritten,NULL);
 if(!result)
 {
  cout<<"Write file failed!"<<endl;
  return;
 }

 CloseHandle(hBmpFile);
 CloseHandle(hNewExe);
}

写完后运行生成的EXE文件,报错! 试了N次,发现只有更换与原来背景图片大小相同的图片时程序才运行正常。原因是当修改的图片资源与原来的图片资源大个不一致时,会无意中修改了其它段的偏移地址,假如这些段的位置在资源段的后面的话。而当修改图标资源的时候,因为图标资源的大小一定,就不会出现这种错误了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值