Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Операционная система Microsoft Windows 3.1 для программиста

© Александр Фролов, Григорий Фролов
Том 12, М.: Диалог-МИФИ, 1993, 255 стр.

[Назад] [Содеожание] [Дальше]

1.3. Пиктограмма

В загрузочный модуль приложения Windows можно добавить ресурс, который называется пиктограмма (Icon).

Пиктограмма - это графическое изображение небольшого размера, состоящее из отдельных пикселов. Пиктограммы обычно используются для обозначения свернутого окна приложения. Окна групп приложения Program Manager содержат пиктограммы других приложений.

С помощью приложения Resource Workshop вы можете нарисовать свои собственные пиктограммы и использовать их для представления главного окна приложения в свернутом состоянии, для оформления внешнего вида окон приложения или для решения других задач.

Операционная система Windows содержит ряд встроенных пиктограмм, которые доступны приложениям.

Приложения Windows активно работают с графическими изображениями, состоящими из отдельных пикселов и имеющих прямоугольную или квадратную форму. Такие изображения называются bitmap (битовый образ). Для представления цвета отдельного пиксела в изображении может быть использовано различное количество бит памяти. Например, цвет пиксела черно-белого изображения может быть представлен одним битом, для представления цвета 16-цветного изображения нужно 4 бита. Цвет одного пиксела изображения в режиме TrueColor представляется 24 битами памяти.

Можно считать, что пиктограмма является упрощенным вариантом изображения bitmap. Пиктограммы хранятся в файлах с расширением имени *.ico (хотя можно использовать любое расширение). В одном файле обычно находится несколько вариантов пиктограмм. Когда Windows рисует пиктограмму, он выбирает из файла наиболее подходящий для текущего режима работы видеоадаптера.

Создание пиктограммы

Приложение Resource Workshop позволяет вам создать пиктограммы размером 32х16 пикселов (для отображения на мониторах CGA), 32х32 пиксела (для отображения в стандартном режиме VGA) и 64х64 пиксела (для режимов SVGA с большим разрешением). Вы можете создать монохромную или цветную пиктограмму. Цветная пиктограмма содержит 8, 16 или 256 цветов (Windows версии 3.0 не умеет работать с пиктограммами, содержащими 256 цветов).

В одном файле *.ico допускается хранить несколько пиктограмм различного размера и с различным количеством цветов. В этом случае при выводе пиктограммы Windows сделает правильный выбор для текущего режима работы видеоадаптера.

Для того чтобы создать файл *.ico, запустите Resource Workshop и из меню "File" выберите строку "New Project...". В появившейся диалоговой панели выберите переключатель ".ICO" и нажмите кнопку "OK". На экране появится диалоговая панель "New icon image" (рис. 1.8).

Рис. 1.8. Диалоговая панель "New icon image"

В этой диалоговой панели вы должны выбрать нужный вам размер пиктограммы (переключатель "Size") и количество цветов, используемых в пиктограмме (переключатель "Colors").

Сделав выбор, нажмите кнопку "OK". На экране появятся окна, показанные на рис. 1.9.

Рис. 1.9. Создание новой пиктограммы

Большое окно с заголовком "ICON:ICON_1 32x32 2 Colors" предназначено для редактирования графического изображения пиктограммы и имеет полосу с инструментами, аналогичными используемым в стандартном для Windows приложении Paint Brush.

Фактически для пиктограммы любого формата используется два битовых изображения. Одно изображение является маской, второе - собственно графическим изображением пиктограммы. Накладывая маску, вы можете создать пиктограмму произвольной формы (а не только прямоугольную).

При помощи левой клавиши мыши вы можете выбрать цвет для изображения (на рисунке обозначен как FG), а при помощи левой - для фона пиктограммы (на рисунке обозначен как BG). Можно выбрать слово "Transparent", в этом случае будет использоваться "прозрачный" цвет. Участки пиктограммы, нарисованные с использованием режима "Inverted" (инвертировать) будут инвертировать цвет фона окна, над которым находится пиктограмма.

Для того чтобы добавить в файл *.ico еще один вариант пиктограммы, сделайте текущим окно "ICON:ICON_1" и из меню "Images" (появится после того как указанное выше окно станет активным) выберите строку "New Image...". Выберите нужное вам разрешение и приступайте к созданию нового варианта пиктограммы. Для этого сделайте двойной щелчок левой клавишей мыши по новой строке, появившейся в окне "ICON:ICON_1".

После создания файла пиктограммы сохраните его, выбрав из меню "File" строку "Save file as...". В появившейся диалоговой панели вам нужно указать путь и имя файла, использовав расширение имени *.ico.

Включение пиктограммы в файл описания ресурсов

Для включения пиктограммы в файл описания ресурсов используется оператор ICON (для включения пиктограмм в диалоговые панели используется другой формат, который мы сейчас не будем рассматривать):

IconID ICON [параметры загрузки] [тип памяти] имя файла

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

AppIcon ICON myicon.ico

Идентификатор пиктограммы IconID можно указывать как символическое имя (см. предыдущую строку) или как целое число - идентификатор ресурса:

456 ICON great.ico

После сборки проекта файл пиктограммы будет вставлен в исполняемый файл приложения Windows.

Использование пиктограммы при регистрации класса окна

Во всех приложениях, описанных в предыдущем томе "Библиотеки системного программиста", для класса главного окна приложения мы определяли встроенную в Windows пиктограмму с идентификатором IDI_APPLICATION. Для этого мы вызывали функцию LoadIcon:

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

Эта функция имеет следующий прототип:

HICON WINAPI LoadIcon(HINSTANCE hInst, LPCSTR lpszIcon);

Параметр hInst является идентификатором текущей копии приложения.

Параметр lpszIcon - идентификатор ресурса или дальний указатель на строку, идентифицирующую ресурс.

Функция LoadIcon возвращает идентификатор загруженной пиктограммы или NULL при ошибке.

Если в файле описания ресурсов идентификатор пиктограммы представлен в виде текстовой строки, в качестве второго параметра функции LoadIcon следует передать указатель на эту строку.

Следующая строка задает для класса главного окна приложения пиктограмму, определенную в файле описания ресурсов под именем AppIcon:

wc.hIcon = LoadIcon(hInstance, "AppIcon");

Если же для идентификатора пиктограммы используется целое число, второй параметр следует определить с использованием макрокоманды MAKEINTRESOURCE, определенной в файле windows.h:

#define MAKELP(sel, off) ((void FAR*)MAKELONG((off), (sel)))
#define MAKEINTRESOURCE(i) ((LPCSTR)MAKELP(0, (i)))

Например, пусть в файле описания ресурсов определена пиктограмма с целым числом в качестве идентификатора:

456 ICON great.ico

В этом случае загрузка пиктограммы должна выполняться следующим образом:

wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(456));

Возможен еще один вариант:

wc.hIcon = LoadIcon(hInstance, "#456");

Для Windows символ "#" означает, что значение 456 является текстовой строкой.

Если пиктограмма, загруженная с помощью функции LoadIcon, вам больше не нужна, вы можете освободить занимаемую ей память, вызвав функцию DestroyIcon:

BOOL WINAPI DestroyIcon(HICON hIcon);

Функция DestroyIcon уничтожает пиктограмму, идентификатор которой задан параметром hIcon и освобождает ранее занимаемую этой пиктограммой память.

Встроенные пиктограммы

Операционная система Windows содержит пять встроенных пиктограмм, которые вы можете использовать при необходимости в своих приложениях. Приведем список идентификаторов встроенных пиктограмм.

Пиктограмма Идентификатор Применение
IDI_APPLICATION Пиктограмма, назначаемая главному окну приложения по умолчанию
IDI_ASTERISK Используется в информирующих сообщениях
IDI_EXCLAMATION Используется в предупреждающих сообщениях
IDI_HAND Используется в критических предупреждающих сообщениях
IDI_QUESTION Означает вопрос или запрос дополнительных данных

С идентификатором IDI_APPLICATION вы уже встречались при регистрации класса окна:

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

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

Идентификаторы встроенных пиктограмм определены в файле windows.h следующим образом:

#define IDI_APPLICATION  MAKEINTRESOURCE(32512)
#define IDI_HAND         MAKEINTRESOURCE(32513)
#define IDI_QUESTION     MAKEINTRESOURCE(32514)
#define IDI_EXCLAMATION  MAKEINTRESOURCE(32515)
#define IDI_ASTERISK     MAKEINTRESOURCE(32516)

Изображение пиктограммы в окне приложения

После того как вы загрузили пиктограмму функцией LoadIcon, вы можете нарисовать ее в любом месте окна. Для этого вам достаточно вызвать функцию DrawIcon:

BOOL WINAPI DrawIcon(HDC hDC, int x, int y, HICON hIcon);

Параметр hDC - идентификатор контекста отображения, полученный для рисования.

Пиктограмма с идентификатором hIcon будет нарисована в точке с координатами (x,y), определяемыми параметрами x и y.

Функция DrawIcon возвращает значение TRUE при успешном завершении и FALSE при ошибке.

Приложение ICO

Наше следующее приложение называется ICO. Оно демонстрирует способ назначения главному окну приложения пиктограммы, используемой для отображения окна в свернутом состоянии. Кроме этого, приложение ICO рисует в своем главном окне несколько встроенных пиктограмм и одну пиктограмму, определенную в файле описания ресурсов.

Исходный текст приложения приведен в листинге 1.5.


Листинг 1.5. Файл ico\ico.cpp


// ----------------------------------------
// Изображение пиктограмм
// ----------------------------------------
#define STRICT
#include <windows.h>
#include <mem.h>
#include "ico.hpp"

void Error(void);
BOOL InitApp(HINSTANCE);
LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);

char szClassName[80];
char szWindowTitle[80];
HINSTANCE hInst;

// =====================================
// Функция WinMain
// =====================================
#pragma argsused

int PASCAL
WinMain(HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        LPSTR     lpszCmdLine,
        int       nCmdShow)
{
  MSG  msg;   // структура для работы с сообщениями
  HWND hwnd;  // идентификатор главного окна приложения
  int  cb;

  hInst = hInstance;

  // Загружаем текстовые строки 
  cb = LoadString(hInstance, IDS_CLASSNAME,
    szClassName, sizeof(szClassName));

  if(!cb)
  {
    Error(); return -1;
  }

  cb = LoadString(hInstance, IDS_WINDOWTITLE,
    szWindowTitle, sizeof(szWindowTitle));

  if(!cb)
  {
    Error(); return -1;
  }

  if(!InitApp(hInstance))
      return FALSE;

  hwnd = CreateWindow(
    szClassName,         // имя класса окна
    szWindowTitle,       // заголовок окна
    WS_OVERLAPPEDWINDOW, // стиль окна
    CW_USEDEFAULT,       // задаем размеры и расположение
    CW_USEDEFAULT,       // окна, принятые по умолчанию 
    CW_USEDEFAULT,
    CW_USEDEFAULT,
    0,                   // идентификатор родительского окна
    0,                   // идентификатор меню
    hInstance,           // идентификатор приложения
    NULL);               // указатель на дополнительные
                         // параметры
  if(!hwnd)
    return FALSE;

  ShowWindow(hwnd, nCmdShow);
  UpdateWindow(hwnd);

  while(GetMessage(&msg, 0, 0, 0))
  {
    DispatchMessage(&msg);
  }
  return msg.wParam;
}

// =====================================
// Функция InitApp
// =====================================

BOOL
InitApp(HINSTANCE hInstance)
{
  ATOM aWndClass; // атом для кода возврата
  WNDCLASS wc;    // структура для регистрации
                  // класса окна

  memset(&wc, 0, sizeof(wc));

  // Загружаем пиктограмму, которая будет использована
  // для отображения главного окна в свернутом виде
  wc.hIcon = LoadIcon(hInstance, "AppIcon");

  wc.style = 0;
  wc.lpfnWndProc = (WNDPROC) WndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  wc.lpszMenuName = (LPSTR)NULL;
  wc.lpszClassName = (LPSTR)szClassName;

  aWndClass = RegisterClass(&wc);
  return (aWndClass != 0);
}

// --------------------------------------------
// Функция обработки ошибки загрузки ресурса
// --------------------------------------------
void Error(void)
{
  MessageBox(NULL, "Ошибка при загрузке ресурса",
    "Error", MB_OK | MB_ICONSTOP);
}

Функция WinMain сохраняет идентификатор приложения в глобальной переменной hInst. Содержимое этой переменной будет впоследствии использовано для загрузки ресурсов из exe-файла приложения.

Далее функция WinMain загружает из ресурсов приложения строки с идентификаторами IDS_CLASSNAME (имя класса для главного окна приложения) и IDS_WINDOWTITLE (заголовок главного окна приложения).

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

wc.hIcon = LoadIcon(hInstance, "AppIcon");

В главный файл приложения и файл описания ресурсов включается файл ico.hpp (листинг 1.6), в котором определены символические константы для идентификации строк таблицы STRINGTABLE.


Листинг 1.6. Файл ico\ico.hpp


#define IDS_CLASSNAME    1
#define IDS_WINDOWTITLE  2

Файл описания ресурсов приведен в листинге 1.7.


Листинг 1.7. Файл ico\ico.rc


#include "ico.hpp"

/* Таблица строк */
STRINGTABLE
BEGIN
IDS_CLASSNAME,   "ICOAppClass"
IDS_WINDOWTITLE, "ICO Demo"
END

/* Пиктограмма */
AppIcon ICON ico.ico

В этом файле наряду с оператором STRINGTABLE, описывающим таблицу строк, имеется оператор ICON, ссылающийся на файл пиктограммы ico.ico (листинг 1.8).


Листинг 1.8. Файл ico\ico.ico



Основная задача функции главного окна приложения (листинг 1.9) - вывод в окно встроенных пиктограмм и пиктограммы ico.ico, загруженной из ресурсов приложения (рис. 1.10).

Рис. 1.10. Главное окно приложения ICO


Листинг 1.9. Файл ico\wndproc.cpp


// =====================================
// Функция WndProc
// =====================================

#define STRICT
#include <windows.h>
#include <stdio.h>

extern HINSTANCE hInst;

LRESULT CALLBACK _export
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  HDC hdc;             // индекс контекста устройства
  PAINTSTRUCT ps;      // структура для рисования

  // Размеры пиктограммы
  static int xIcon, yIcon;

  // Идентификатор пиктограммы
  HICON hIcon;

  switch (msg)
  {
    case WM_CREATE:
    {
      // Определяем размеры пиктограммы
      xIcon = GetSystemMetrics(SM_CXICON);
      yIcon = GetSystemMetrics(SM_CYICON);
      break;
    }

    case WM_PAINT:
    {
      hdc = BeginPaint(hwnd, &ps);

      // Загружаем и рисуем встроенные пиктограммы
      hIcon = LoadIcon(0, IDI_APPLICATION);
      DrawIcon(hdc, xIcon/2, yIcon/2, hIcon);

      hIcon = LoadIcon(0, IDI_ASTERISK);
      DrawIcon(hdc, xIcon/2 + xIcon*2, yIcon/2, hIcon);

      hIcon = LoadIcon(0, IDI_EXCLAMATION);
      DrawIcon(hdc, xIcon/2 + xIcon*4, yIcon/2, hIcon);

      hIcon = LoadIcon(0, IDI_HAND);
      DrawIcon(hdc, xIcon/2 + xIcon*6, yIcon/2, hIcon);

      hIcon = LoadIcon(0, IDI_QUESTION);
      DrawIcon(hdc, xIcon/2 + xIcon*8, yIcon/2, hIcon);

      // Загружаем и рисуем свою пиктограмму,
      // указанную в файле описания ресурсов
      hIcon = LoadIcon(hInst, "AppIcon");
      DrawIcon(hdc, xIcon/2, yIcon/2 + yIcon*2, hIcon);

      EndPaint(hwnd, &ps);
      return 0;
    }

    case WM_DESTROY:
    {
      PostQuitMessage(0);
      return 0;
    }
  }
  return DefWindowProc(hwnd, msg, wParam, lParam);
}

При создании окна в функцию окна поступает сообщение WM_CREATE, по которому определяются размеры пиктограммы:

xIcon = GetSystemMetrics(SM_CXICON);
yIcon = GetSystemMetrics(SM_CYICON);

Эти размеры будут использованы для размещения пиктограмм в окне.

При обработке сообщения WM_PAINT функция окна загружает и рисует пиктограммы. Для загрузки пиктограмм используется функция LoadIcon, для рисования - DrawIcon.

Файл определения модуля приложения ICO представлен в листинге 1.10.


Листинг 1.10. Файл ico\ico.def


; =============================
; Файл определения модуля
; =============================
NAME        ICO
DESCRIPTION 'Приложение ICO, (C) 1994, Frolov A.V.'
EXETYPE     windows
STUB        'winstub.exe'
STACKSIZE   5120
HEAPSIZE    1024
CODE        preload moveable discardable
DATA        preload moveable multiple

[Назад] [Содеожание] [Дальше]