Шаг 85.
Библиотека OWL.
Смена иконки файла

    На этом шаге мы рассмотрим реализацию этого приложения.

    Студент 4 курса (2013-14 уч.год) Улько Дмитрий реализовал приложение средствами бибилиотеки OWL, позволяющее сменить иконку файла.

    Внешний вид приложения приведен на рисунке 1.


Рис.1. Внешний вид приложения

    Данное приложение позволяет заменять иконки exe-файлов, загрузив их из библиотеки иконок dll или из exe-файла. Загруженные значки отображаются в окне приложения. Выбор нужного из них осуществляется щелчком левой кнопки мыши по пиктограмме нужной иконки. Выбор файла с иконками и файла, иконку которого необходимо заменить, осуществляется с помощью команд меню или соответствующих кнопок на панели управления.

    Приведем текст программы.

    Основной файл decor.cpp.

//-----------------------------Подключаемые файлы-------------------------------

#include <owl\applicat.h>
#include <owl\decframe.h>
#include <owl\controlb.h>
#include <owl\buttonga.h>
#include <owl\statusba.h>
#include <owl\messageb.h>
#include <owl\opensave.h>
#include <owl\dc.h>
#include <string.h>
#include "decor.rc"

#define COL_ICONS 500 // Количетво элементов массива иконок

TRect check;
TRect *rect[COL_ICONS];
TIcon *icons[COL_ICONS];
int col,Number;
char filename[50],iconname[50];
TMessageBar *msgbar1,*msgbar2;

//--------------------------------Класс приложения------------------------------

class TApp: public TApplication
{
  public:
	 TApp():TApplication(){}
	 void InitMainWindow();
};

//-----------------------------Класс клиентского окна---------------------------

class TCWndw: public TWindow
{
  public:
	 TCWndw(TWindow *parent,const char far*title);
  protected:
	 void Paint(TDC&DC,BOOL,TRect&);
	 void EvLButtonDown(uint modKeys,TPoint &point);
	 void EvLButtonUp(uint modKeys,TPoint &point);
	 void CmFileSelect();
	 void CmIconSelect();
	 void CmIconReplace();
	 void CmAbout();
	 BOOL CanClose();
	 BOOL ReplaceIcon(int);
	 int NumIcon(int);

	 HINSTANCE hinstance;
	 HRSRC     hrsrc;
	 HGLOBAL   hglobal;
	 LPVOID    lpvoid;
	 HANDLE    handle;
	 HICON     hicon;
	 BOOL      result;

	 DECLARE_RESPONSE_TABLE(TCWndw);
};

//------------------------Таблица откликов клиентского окна---------------------

DEFINE_RESPONSE_TABLE1(TCWndw,TWindow)
	EV_WM_LBUTTONDOWN,
	EV_WM_LBUTTONUP,
	EV_COMMAND(CM_FILESELECT, CmFileSelect),
	EV_COMMAND(CM_ICONSELECT, CmIconSelect),
	EV_COMMAND(CM_ICONREPLACE, CmIconReplace),
	EV_COMMAND(CM_ABOUT, CmAbout),
END_RESPONSE_TABLE;

//---------------------------Конструктор клиентского окна-----------------------

TCWndw::TCWndw(TWindow*parent,const char far*title):TWindow(parent,title) {}

//-------------------------------Класс основного окна---------------------------

class TWndw : public TDecoratedFrame
{
  public:
	  TWndw(TWindow *parent, const char far *title, TWindow *client,
			  BOOL trackMenuSelection);
	 ~TWndw();
};

//---------------------------Конструктор основного окна-------------------------

TWndw::TWndw(TWindow *parent, const char far *title, TWindow *client,
BOOL trackMenuSelection):TDecoratedFrame(parent,title,client,trackMenuSelection)
{
  TButtonGadget *b;
  TSeparatorGadget *s;
  AssignMenu("MENU_1");
  TControlBar *cntrlBar = new TControlBar(this,TControlBar::Vertical);
  cntrlBar->SetHintMode(TGadgetWindow::EnterHints);
  b = new TButtonGadget(BMP_FILESELECT, CM_FILESELECT);
  cntrlBar->Insert(*b);
  b = new TButtonGadget(BMP_ICONSELECT, CM_ICONSELECT);
  cntrlBar->Insert(*b);
  b = new TButtonGadget(BMP_ICONREPLACE, CM_ICONREPLACE);
  cntrlBar->Insert(*b);
  s = new TSeparatorGadget(10);
  cntrlBar->Insert (*s);
  b = new TButtonGadget(BMP_ABOUT, CM_ABOUT);
  cntrlBar->Insert(*b);
  s = new TSeparatorGadget(10);
  cntrlBar->Insert (*s);
  b = new TButtonGadget(BMP_EXIT, CM_EXIT);
  cntrlBar->Insert(*b);
  Insert(*cntrlBar, TDecoratedFrame::Right);
  TStatusBar *statbar=new TStatusBar(this,TGadget::Embossed,TStatusBar::CapsLock|
				 TStatusBar::NumLock|TStatusBar::Overtype);
  statbar->SetText("Программа для замены иконок файлов");
  Insert(*statbar,TDecoratedFrame::Bottom);

  strcpy(filename,"Файл не выбран!");
  strcpy(iconname,"Иконка не выбрана!");

  msgbar2=new TMessageBar(this);
  msgbar2->SetText(iconname);
  Insert(*msgbar2,TDecoratedFrame::Bottom);

  msgbar1=new TMessageBar(this);
  msgbar1->SetText(filename);
  Insert(*msgbar1,TDecoratedFrame::Bottom);

  Attr.W = 820;
  Attr.H = 460;
  Attr.X = GetSystemMetrics(SM_CXSCREEN)/2-Attr.W/2;
  Attr.Y = GetSystemMetrics(SM_CYSCREEN)/2-Attr.H/2;

  col=0; Number=1;
  check.SetEmpty();
}

//-------------------------Деструктор основного окна----------------------------

TWndw::~TWndw()
{
	for(int i=0;i<col;i++) delete icons[i];
}

//------------------------Перерисовка клиентского окна--------------------------

void TCWndw::Paint(TDC &DC,BOOL,TRect&)
{
	int x=10,y=-32;
	//************************Вывод иконок на экран
	for(int i=0;i<col;i++)
	{
	  if(!((i)%8)&&(i)) {x+=42; y=-32;}
	  y+=42;
	  DC.DrawIcon(x,y,*icons[i]);
	}
	//*********Рисование прямоугольника, отмечающего выделенную иконку
	if(check.left)
	{
	  TPen *pen = new TPen(13,3,PS_SOLID);
	  DC.SelectObject(*pen);
	  DC.MoveTo(check.left-3,check.top-3);
	  DC.LineTo(check.right+3,check.top-3);
	  DC.LineTo(check.right+3,check.bottom+3);
	  DC.LineTo(check.left-3,check.bottom+3);
	  DC.LineTo(check.left-3,check.top-3);
	  delete pen;
	}
}

//-----------------Нажатие левой кнопки мыши в клиентском окне------------------

void TCWndw::EvLButtonDown(UINT,TPoint &point)
{
	 for(int i=0;i<col-1;i++)
	 if((point.x>=rect[i]->left)&&(point.x<=rect[i]->right)&&
		(point.y>=rect[i]->top)&&(point.y<=rect[i]->bottom)) Invalidate();
	 check.SetEmpty();
}

//-----------------Отпускание левой кнопки мыши в клиентском окне---------------

void TCWndw::EvLButtonUp(UINT,TPoint &point)
{
	 //***********************Выделение нужной иконки
	 for(int i=0;i<col-1;i++)
	 if((point.x>=rect[i]->left)&&(point.x<=rect[i]->right)&&
		(point.y>=rect[i]->top)&&(point.y<=rect[i]->bottom))
	 {
		 TDC *DC = new TClientDC(HWindow);
		 TPen *pen = new TPen(13,3,PS_SOLID);
		 DC->SelectObject(*pen);
		 DC->MoveTo(rect[i]->left-3,rect[i]->top-3);
		 DC->LineTo(rect[i]->right+3,rect[i]->top-3);
		 DC->LineTo(rect[i]->right+3,rect[i]->bottom+3);
		 DC->LineTo(rect[i]->left-3,rect[i]->bottom+3);
		 DC->LineTo(rect[i]->left-3,rect[i]->top-3);
		 delete pen;
		 delete DC;
		 Number=i+1;
		 check=*rect[i];
	 }
}

//----------------------------------Выбор файла---------------------------------

void TCWndw::CmFileSelect()
{
  //**********************Вывод диалогового окна выбора файла
  char errorMsg[81];
  TOpenSaveDialog::TData fileData(OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|
       OFN_PATHMUSTEXIST, "Приложения(*.exe)|*.exe|",0,0,"*");
  TFileOpenDialog *dialog = new TFileOpenDialog(this, fileData,0,"Выбор файла");
  int result=dialog->Execute();
  if (result==IDOK)
  {
	  strcpy(filename,fileData.FileName);
	  strcat(strcpy(fileData.FileName,"Файл:  "),filename);
	  msgbar1->SetText(fileData.FileName);
  }
  else if (fileData.Error != 0)
  {
	  wsprintf(errorMsg,"Возникла ошибка #%ld.", fileData.Error);
	  MessageBox(errorMsg, "Ошибка",  MB_OK | MB_ICONEXCLAMATION);
  }
}

//-----------------------------------Выбор иконки-------------------------------

void TCWndw::CmIconSelect()
{
  //**********************Вывод диалогового окна выбора иконки
  col=0;
  check.SetEmpty();
  Invalidate();
  char errorMsg[81];
  TOpenSaveDialog::TData fileData(OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|
       OFN_PATHMUSTEXIST, "Библиотеки(*.dll)|*.dll|
       Файлы прилоежний (*.exe)|*.exe|",0,0,"*");
  TFileOpenDialog *dialog = new TFileOpenDialog(this,fileData,0,"Выбор иконки");
  int result=dialog->Execute();
  if (result==IDOK)
  {
	  strcpy(iconname,fileData.FileName);
	  strcat(strcpy(fileData.FileName,"Иконка:  "),iconname);
	  msgbar2->SetText(fileData.FileName);
	  //**************************Вывод иконок на экран
	  hinstance=LoadLibrary(iconname);
	  if(hinstance==NULL) MessageBox("Не удалось загрузить библилтеку!",
             "Сообщение",MB_OK|MB_ICONEXCLAMATION);
	  col=0;
	  int x=10,y=-32;
	  TDC *DC=new TClientDC(HWindow);
	  do
	  {
		 if(!(col%8)&&(col)) {x+=42; y=-32;}
		 hicon=ExtractIcon(hinstance,iconname,col);
		 if(hicon==NULL && !col) 
                      MessageBox("Не удалось загрузить иконки!","Сообщение",
			 MB_OK|MB_ICONEXCLAMATION);
		 y+=42;
		 DC->DrawIcon(x,y,hicon);
		 icons[col]=new TIcon(hicon);
		 rect[col]=new TRect(x,y,x+32,y+32);
		 col++;
	  } while (hicon!=NULL);
	  delete DC;
	  FreeLibrary(hinstance);
  }
  else if (fileData.Error != 0)
  {
	  wsprintf(errorMsg,"Возникла ошибка #%ld.", fileData.Error);
	  MessageBox(errorMsg, "Ошибка",  MB_OK | MB_ICONEXCLAMATION);
  }
}

//------------------------Нажатие на кнопку "Заменить иконку"-------------------

void TCWndw::CmIconReplace()
{
	if(!strcmp(filename,"Файл не выбран!")) 
          MessageBox("Выберите файл!","Сообщение",MB_OK|MB_ICONEXCLAMATION); 
        else
	  if(!strcmp(iconname,"Иконка не выбрана!")) 
             MessageBox("Выберите иконку!","Сообщение",MB_OK|MB_ICONEXCLAMATION); 
           else
	     if(!ReplaceIcon(Number)) 
                MessageBox("Не удалось заменить иконку!","Сообщение",MB_OK); 
             else
	        MessageBox("Иконка заменена!","Сообещние",MB_OK);
}
//-----------Замена иконки (редактирование ресурсов исполняемого файла)----------

BOOL TCWndw::ReplaceIcon(int Number)
{
  hinstance=LoadLibrary(iconname);
  if(hinstance == NULL) 
    {MessageBox("Ошибка при загрузке библиотеки!","",MB_OK); 
     return FALSE;}

  hrsrc = FindResource(hinstance,MAKEINTRESOURCE(NumIcon(Number)),
      MAKEINTRESOURCE(RT_ICON));
  if(hrsrc == NULL) 
    {MessageBox("Ошибка при поиске ресурсов!","",MB_OK); 
     return FALSE;}

  hglobal = LoadResource(hinstance,hrsrc);
  if(hglobal == NULL) 
  {MessageBox("Ошибка при загрузке ресурсов!","",MB_OK); 
   return FALSE;}

  lpvoid = LockResource(hglobal);
  if(lpvoid == NULL) 
  {MessageBox("Ошибка при фиксации ресурсов!","",MB_OK); 
   return FALSE;}

  handle = BeginUpdateResource(filename,false);
  if(handle == NULL) 
  {MessageBox("Ошибка при обновлении ресурсов","",MB_OK); 
   return FALSE;}

  result = UpdateResource(handle,MAKEINTRESOURCE(RT_ICON),
          MAKEINTRESOURCE(1),
  MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),
          lpvoid,SizeofResource(hinstance, hrsrc));
  if(result == FALSE) 
  {MessageBox("Ошибка при обновлении ресурсов","",MB_OK); 
   return FALSE;}

  if(!EndUpdateResource(handle, FALSE)) 
    return FALSE;
  if(!FreeLibrary(hinstance)) 
  {MessageBox("FreeLibrary","",MB_OK); 
   return FALSE;}
  return TRUE;
}

//----------------------------------О программе---------------------------------
void TCWndw::CmAbout()
{
  MessageBox ("Программа для замены иконок файлов. Все права защищены!!! \n
        Copyright 2013", "",MB_OK);
}

/*----------------------Определение номера выбранной иконки---------------------

  Данная функция определяет номер иконки, под которым она числится в
  исполняемом файле */

int TCWndw::NumIcon(int i)
{
  if(strstr(iconname,"moricons.dll"))
  {
    switch(i)
    {
      case 67: case 68: case 69: case 49: case 26: case 27: case 28: case 29:
      case 30: case 23: case 21: case 17: case 15: case 13: case 11: case 6:
      case 96: case 97: case 98: case 99: case 100: case 101: case 102:
      case 103: case 104: case 105: case 106: case 107: return 2*i-1;
      case 108: return 220;
      case 109: return 225;
      case 110: return 228;
      case 111: return 231;
      case 112: return 234;
      case 113: return 237;
      case 114: return 246;
      default: return 2*i;
    }
  }
  else if(strstr(iconname,"progman.exe"))
  {
	 switch(i)
	 {
		 case 1: return 16;
		 case 2: return 12;
		 case 3: return 10;
		 case 4: return 4;
		 case 5: return 100;
		 case 7: return 26;
		 case 8: return 15;
		 case 9: return 2;
		 case 10: return 8;
		 case 11: return 22;
		 case 12: return 6;
		 case 49: return 103;
		 default: return 2*i+2;
	 }
  }
  else return i;
}

//------------------------------------------------------------------------------

BOOL TCWndw::CanClose()
{
  int result=MessageBox("Вы действительно хотите выйти из приложения?","Закрытие",
  MB_YESNO | MB_ICONQUESTION);
  if(result==IDYES) return TRUE; else return FALSE;
}

//------------------------------------------------------------------------------

void TApp::InitMainWindow()
{
  TWindow *client = new TCWndw (0,0);
  TDecoratedFrame *wndw= new TWndw(0,"Замена иконок файлов",client,TRUE);
  MainWindow = wndw;
  MainWindow->SetIcon(this,ICON_1);
  SetMainWindow(wndw);
  EnableBWCC();
}

//------------------------------------------------------------------------------

int OwlMain(int,char *[])
{
  return TApp().Run();
}

//------------------------------------------------------------------------------

    Файл ресурсов.

#ifndef WORKSHOP_INVOKED
#include "windows.h"
#endif

#define ICON_1            100
#define DIALOG_1            1
#define ID_OK             101
#define ID_CANCEL         102
#define CM_POPUPITEM1     104
#define CM_POPUPITEM      101
#define BMP_EXIT            3
#define BMP_FILESELECT      2
#define BMP_ICONSELECT      1
#define BMP_ICONREPLACE     4
#define BMP_ABOUT           5
#define CM_EXIT         24310
#define CM_FILESELECT     103
#define CM_ICONSELECT     102
#define CM_ICONREPLACE    106
#define CM_ABOUT          105

#ifdef RC_INVOKED

MENU_1 MENU 
{
 POPUP "&File"
 {
  MENUITEM "&Select a file",  CM_FILESELECT
  MENUITEM SEPARATOR
  MENUITEM "&Exit",           CM_EXIT
 }

 POPUP "&Icon"
 {
  MENUITEM "Select an &icon", CM_ICONSELECT
  MENUITEM "&Replace icon",   CM_ICONREPLACE
 }

 POPUP "&Help"
 {
  MENUITEM "&About...",       CM_ABOUT
 }
}

STRINGTABLE 
{
 CM_FILESELECT,               "Выбрать файл"
 CM_EXIT,                     "Выход из приложения"
 CM_ICONSELECT,               "Выбрать иконку"
 CM_ABOUT,                    "О программе"
 CM_ICONREPLACE,              "Заменить иконку"
}

BMP_FILESELECT    BITMAP      "filesele.bmp"
BMP_ICONSELECT    BITMAP      "iconsele.bmp"
BMP_ICONREPLACE   BITMAP      "iconrepl.bmp"
BMP_ABOUT         BITMAP      "about.bmp"
BMP_EXIT          BITMAP      "exit.bmp"

ICON_1            ICON        "ICON_1.ICO"

#endif
Текст этого приложения можно взять здесь.

    Рассмотрим основные функции приложения.

//------------------------Перерисовка клиентского окна-------------------------

void TCWndw::Paint(TDC &DC,BOOL,TRect&)
{
	int x=10,y=-32;
	//************************Вывод иконок на экран
	for(int i=0;i<col;i++)
	{
	  if(!((i)%8)&&(i)) {x+=42; y=-32;}
	  y+=42;
	  DC.DrawIcon(x,y,*icons[i]);
	}
	//*********Рисование прямоугольника, отмечающего выделенную иконку
	if(check.left)
	{
	  TPen *pen = new TPen(13,3,PS_SOLID);
	  DC.SelectObject(*pen);
	  DC.MoveTo(check.left-3,check.top-3);
	  DC.LineTo(check.right+3,check.top-3);
	  DC.LineTo(check.right+3,check.bottom+3);
	  DC.LineTo(check.left-3,check.bottom+3);
	  DC.LineTo(check.left-3,check.top-3);
	  delete pen;
	}
}

    Функция Paint перерисовывает окно приложения. Изображения иконок, загруженных из файла, хранятся в массиве и выводятся на экран при каждом обращении к функции. Также рисуется красный прямоугольник, отмечающий выбранную иконку.

//-----------------Нажатие левой кнопки мыши в клиентском окне-----------------

void TCWndw::EvLButtonDown(UINT,TPoint &point)
{
	 for(int i=0;i<col-1;i++)
	 if((point.x>=rect[i]->left)&&(point.x<=rect[i]->right)&&
		(point.y>=rect[i]->top)&&(point.y<=rect[i]->bottom)) Invalidate();
	 check.SetEmpty();
}

    Если во время нажатия левой кнопки мыши курсор находился на какой-либо иконке, то происходит вызов функции перерисовки окна и красный прямоугольник исчезает.

//----------------Отпускание левой кнопки мыши в клиентском окне---------------

void TCWndw::EvLButtonUp(UINT,TPoint &point)
{
	 //***********************Выделение нужной иконки
	 for(int i=0;i<col-1;i++)
	 if((point.x>=rect[i]->left)&&(point.x<=rect[i]->right)&&
		(point.y>=rect[i]->top)&&(point.y<=rect[i]->bottom))
	 {
		 TDC *DC = new TClientDC(HWindow);
		 TPen *pen = new TPen(13,3,PS_SOLID);
		 DC->SelectObject(*pen);
		 DC->MoveTo(rect[i]->left-3,rect[i]->top-3);
		 DC->LineTo(rect[i]->right+3,rect[i]->top-3);
		 DC->LineTo(rect[i]->right+3,rect[i]->bottom+3);
		 DC->LineTo(rect[i]->left-3,rect[i]->bottom+3);
		 DC->LineTo(rect[i]->left-3,rect[i]->top-3);
		 delete pen;
		 delete DC;
		 Number=i+1;
		 check=*rect[i];
	 }
}

    Во время отпускания левой кнопки мыши, вокруг иконки, на которой находится курсор, рисуется красный прямоугольник. Номер выбранной иконки помещается в переменную Number.

//----------------------------------Выбор файла---------------------------------

void TCWndw::CmFileSelect()
{
  //**********************Вывод диалогового окна выбора файла
  char errorMsg[81];
  TOpenSaveDialog::TData fileData(OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|
       OFN_PATHMUSTEXIST, "Приложения(*.exe)|*.exe|",0,0,"*");
  TFileOpenDialog *dialog = new TFileOpenDialog(this, fileData,0,"Выбор файла");
  int result=dialog->Execute();
  if (result==IDOK)
  {
	  strcpy(filename,fileData.FileName);
	  strcat(strcpy(fileData.FileName,"Файл:  "),filename);
	  msgbar1->SetText(fileData.FileName);
  }
  else if (fileData.Error != 0)
  {
	  wsprintf(errorMsg,"Возникла ошибка #%ld.", fileData.Error);
	  MessageBox(errorMsg, "Ошибка",  MB_OK | MB_ICONEXCLAMATION);
  }
}

    При нажатии на кнопку Выбрать файл или при выборе соответствующего пункта меню, выводится диалоговое окно. Путь к выбранному файлу сохраняется в переменной filename и отображается в строке состояния.

//-----------------------------------Выбор иконки-------------------------------

void TCWndw::CmIconSelect()
{
  //**********************Вывод диалогового окна выбора иконки
  col=0;
  check.SetEmpty();
  Invalidate();
  char errorMsg[81];
  TOpenSaveDialog::TData fileData(OFN_FILEMUSTEXIST|OFN_HIDEREADONLY|
       OFN_PATHMUSTEXIST, "Библиотеки(*.dll)|*.dll|
       Файлы прилоежний (*.exe)|*.exe|",0,0,"*");
  TFileOpenDialog *dialog = new TFileOpenDialog(this,fileData,0,"Выбор иконки");
  int result=dialog->Execute();
  if (result==IDOK)
  {
	  strcpy(iconname,fileData.FileName);
	  strcat(strcpy(fileData.FileName,"Иконка:  "),iconname);
	  msgbar2->SetText(fileData.FileName);
	  //**************************Вывод иконок на экран
	  hinstance=LoadLibrary(iconname);
	  if(hinstance==NULL) MessageBox("Не удалось загрузить библилтеку!",
             "Сообщение",MB_OK|MB_ICONEXCLAMATION);
	  col=0;
	  int x=10,y=-32;
	  TDC *DC=new TClientDC(HWindow);
	  do
	  {
		 if(!(col%8)&&(col)) {x+=42; y=-32;}
		 hicon=ExtractIcon(hinstance,iconname,col);
		 if(hicon==NULL && !col) 
                      MessageBox("Не удалось загрузить иконки!","Сообщение",
			 MB_OK|MB_ICONEXCLAMATION);
		 y+=42;
		 DC->DrawIcon(x,y,hicon);
		 icons[col]=new TIcon(hicon);
		 rect[col]=new TRect(x,y,x+32,y+32);
		 col++;
	  } while (hicon!=NULL);
	  delete DC;
	  FreeLibrary(hinstance);
  }
  else if (fileData.Error != 0)
  {
	  wsprintf(errorMsg,"Возникла ошибка #%ld.", fileData.Error);
	  MessageBox(errorMsg, "Ошибка",  MB_OK | MB_ICONEXCLAMATION);
  }
}

    Данная функция вызывается при нажатии на кнопку Выбрать иконку либо при щелчке по соответствующему пункту меню. В открывшемся диалоговом окне можно выбрать файл, содержащий иконки. Есть возможность выбрать тип файла (exe или dll). Путь к нужному файлу сохраняется в переменной iconname и отображается в строке состояния. Загруженные иконки выводятся на экран с помощью функции ExtractIcon.

//-----------Замена иконки (редактирование ресурсов исполняемого файла)----------

BOOL TCWndw::ReplaceIcon(int Number)
{
  hinstance=LoadLibrary(iconname);
  if(hinstance == NULL) 
    {MessageBox("Ошибка при загрузке библиотеки!","",MB_OK); 
     return FALSE;}

  hrsrc = FindResource(hinstance,MAKEINTRESOURCE(NumIcon(Number)),
      MAKEINTRESOURCE(RT_ICON));
  if(hrsrc == NULL) 
    {MessageBox("Ошибка при поиске ресурсов!","",MB_OK); 
     return FALSE;}

  hglobal = LoadResource(hinstance,hrsrc);
  if(hglobal == NULL) 
  {MessageBox("Ошибка при загрузке ресурсов!","",MB_OK); 
   return FALSE;}

  lpvoid = LockResource(hglobal);
  if(lpvoid == NULL) 
  {MessageBox("Ошибка при фиксации ресурсов!","",MB_OK); 
   return FALSE;}

  handle = BeginUpdateResource(filename,false);
  if(handle == NULL) 
  {MessageBox("Ошибка при обновлении ресурсов","",MB_OK); 
   return FALSE;}

  result = UpdateResource(handle,MAKEINTRESOURCE(RT_ICON),
          MAKEINTRESOURCE(1),
  MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),
          lpvoid,SizeofResource(hinstance, hrsrc));
  if(result == FALSE) 
  {MessageBox("Ошибка при обновлении ресурсов","",MB_OK); 
   return FALSE;}

  if(!EndUpdateResource(handle, FALSE)) 
    return FALSE;
  if(!FreeLibrary(hinstance)) 
  {MessageBox("FreeLibrary","",MB_OK); 
   return FALSE;}
  return TRUE;
}

    После нажатия на кнопку Заменить иконку осуществляется проверка: выбрана ли иконка и файл, пиктограмму которого необходимо заменить. Если нет, то выводится соответствующее соообщение. Если все в порядке, то происходит вызов функции ReplaceIcon, где и осуществляется правка ресурсов выбранного exe-файла. Процесс редактирования ресурсов проходит в несколько этапов. Сначала необходимо загрузить библиотеку с иконками, затем найти в ней ресурсы нужного типа (в нашем случае это иконки), загрузить найденные иконки в память и, наконец, обновить ресурсы выбранного exe-файла. При работе с ресурсами используются функции WIN API. Вот краткая справка по используемым функциям.

    Функция LoadLibrary отображает заданный исполняемый модуль в адресное пространство вызывающего процесса. Синтаксис:

  HMODULE LoadLibrary (LPCTSTR lpFileName);
Параметры: Если функция завершается успешно, возвращаемое значение - дескриптор модуля. Если функция завершается ошибкой, возвращаемое значение - ПУСТО (NULL).

    Функция FindResource выясняет место ресурса с заданным типом и именем в указанном модуле. Синтаксис:

HRSRC FindResource (
    HMODULE hModule,
    LPCTSTR lpName,
    LPCTSTR lpType
);
Параметры: Если функция завершается успешно, возвращаемое значение - дескриптор информационного блока заданного ресурса. Если функция завершается ошибкой, возвращаемое значение - ПУСТО (NULL).

    Функция LoadResource загружает указанный ресурс в глобальную память. Синтаксис:

HGLOBAL LoadResource (
    HMODULE hModule,
    HRSRC hResInfo
);
Параметры: Если функция завершается успешно, возвращаемое значение - дескриптор данных, связанных с ресурсом. Если функция завершается ошибкой, возвращаемое значение - ПУСТО (NULL).

    Функция LockResource блокирует указанный ресурс в памяти. Синтаксис:

LPVOID LockResource (
    HGLOBAL hResData
);
Параметры: Если загруженный ресурс блокируется, возвращаемое значение - указатель на первый байт ресурса; или же, это - ПУСТО (NULL).

    Функция BeginUpdateResource возвращает дескриптор, который может использоваться функцией UpdateResource, которая добавляет, удаляет или заменяет ресурсы в исполняемом файле. Синтаксис:

HANDLE BeginUpdateResource (      
    LPCTSTR pFileName,
    BOOL bDeleteExistingResources
);
Параметры: Если функция завершается успешно, возвращаемое значение - дескриптор, который может использоваться функциями UpdateResource и EndUpdateResource. Возвращаемое значение - ПУСТО (NULL), если указанный файл - не исполняемый файл, исполняемый файл уже загружен, файл не существует или файл не может открыться для записи.

    Функция UpdateResource добавляет, удаляет или заменяет ресурс в исполняемом файле. Синтаксис:

BOOL UpdateResource (
    HANDLE hUpdate,
    LPCTSTR lpType,
    LPCTSTR lpName,
    WORD wLanguage,
    LPVOID lpData,
    DWORD cbData
);
Параметры Если функция завершается успешно, возвращаемое значение не нуль. Если функция завершается ошибкой, возвращаемое значение равняется нулю.

    Функция EndUpdateResource заканчивает модернизацию ресурса в исполняемом файле. Синтаксис:

BOOL EndUpdateResource (
    HANDLE hUpdate,
    BOOL fDiscard
);
Параметры: Если функция завершается успешно и накопленные модификации ресурса, определенные вызовами функции UpdateResource записываются в указанном исполняемом файле, то возвращаемое значение не нуль. Если функция завершается ошибкой, возвращаемое значение равняется нулю.

    Функция FreeLibrary уменьшает итоговое число ссылок на загруженные динамически подключаемые библиотеки (DLL). Когда итоговое число ссылок достигает нуля, модуль отменяет отображение в адресном пространстве вызывающего процесса, а дескриптор становится больше не допустим. Синтаксис:

BOOL FreeLibrary (
  HMODULE hModule
);
Параметры: Если функция завершается успешно, возвращаемое значение не нуль. Если функция завершается ошибкой, возвращаемое значение равняется нулю.

    Макрос MAKEINTRESOURCE преобразует целочисленное значение в тип ресурса, совместимого с функциями управления ресурсом. Этот макрос используется вместо символьной строки, содержащей имя ресурса. Синтаксис:

LPTSTR MAKEINTRESOURCE(
    WORD wInteger
);
Параметры: Возвращаемое значение - указанное значение в младшем слове и нуль в старшем слове.
/*----------------------Определение номера выбранной иконки---------------------

  Данная функция определяет номер иконки, под которым она числится в
  исполняемом файле */

int TCWndw::NumIcon(int i)
{
  if(strstr(iconname,"moricons.dll"))
  {
    switch(i)
    {
      case 67: case 68: case 69: case 49: case 26: case 27: case 28: case 29:
      case 30: case 23: case 21: case 17: case 15: case 13: case 11: case 6:
      case 96: case 97: case 98: case 99: case 100: case 101: case 102:
      case 103: case 104: case 105: case 106: case 107: return 2*i-1;
      case 108: return 220;
      case 109: return 225;
      case 110: return 228;
      case 111: return 231;
      case 112: return 234;
      case 113: return 237;
      case 114: return 246;
      default: return 2*i;
    }
  }
  else if(strstr(iconname,"progman.exe"))
  {
	 switch(i)
	 {
		 case 1: return 16;
		 case 2: return 12;
		 case 3: return 10;
		 case 4: return 4;
		 case 5: return 100;
		 case 7: return 26;
		 case 8: return 15;
		 case 9: return 2;
		 case 10: return 8;
		 case 11: return 22;
		 case 12: return 6;
		 case 49: return 103;
		 default: return 2*i+2;
	 }
  }
  else return i;
}

    В библиотеке иконок все иконки хранятся в нескольких вариантах (имеют разные размеры, количество цветов и т.д.). Некоторые функции автоматически определяет тип иконки, наиболее подходящий для данного устройства (например функция ExtractIcon выводит на экран иконки, наиболее подходящие для данного монитора). При правке ресурсов исполняемых файлов автоматический выбор нужных типов иконок не осуществляется. Функция NumIcon частично решает данную проблему. Если иконки загружены из библиотек moricons.dll или progman.exe, то функция, в зависимости от номера выбранной иконки, возвращает номер наиболее подходящей пиктограммы. Все иконки из этих библиотек были вручную просмотрены и выбраны подходящие соответствующие им номера. При работе с другими библиотеками возможно, что иконка в файле заменится не на ту, которую выбрал пользователь.

    Ещё одним недостатком данного приложения является то, что не у каждого exe-файла удается заменить иконку. Например, без проблем происходит замена иконок у файлов приложений, созданных в Delphi или других средах программирования. А если попытаться заменить иконку у какого-нибудь "серьёзного" приложения (т.е. не созданного самостоятельно), то скорее всего желаемый результат достигнут не будет.

    Мы закончили знакомиться с основными возможностями библиотеки Borland OWL.




Предыдущий шаг Содержание