    Работа с пиктограммами, курсорами и растровыми изображениями 

    В этой главе объясняется, как управлять внешним видом двух элементов, 
связанных со всеми приложениями Windows. Речь идет о пиктограмме приложения и 
курсоре мыши. До сих пор в программах, которые мы создавали, использовались 
пиктограмма и курсор, заданные Windows по умолчанию. Теперь же мы узнаем, кок 
создавать собственные варианты этих элементов. Кроме того, будет рассказано, 
как работать с другими встроенными пиктограммами и курсорами, определенными в 
Windows. В этой главе рассматривается также вывод на экран растровых 
графических изображений. 
    
    163 

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

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

    Для последующих примеров нам потребуется создать собственную 
пользовательскую пиктограмму и курсор. Как уже было сказано, для этого 
необходим графический редактор. В нем пиктограмма или курсор отображаются в 
увеличенном виде. Это позволяет легко создавать новые изображения или изменять 
их внешний вид. Пример пользовательской пиктограммы и курсора, созданных с 
помощью редактора ресурсов фирмы Microsoft, показан на рис. 7.1. 

    Рис. 7.1. Пользовательская пиктограмма и курсор в редакторе ресурсов 


    164 MFC: основы программирования 

    Все курсоры имеют одинаковый размер: 32 на 32 пикселя. В Windows 3.1 
размер стандартной пиктограммы, связанной с приложением, также 32х32. При 
работе в Windows 95 необходимо создать две пиктограммы. Одна из них — 
стандартная (размер 32х32). Другая — малая (размер 16х16 пикселей). Малые 
пиктограммы не поддерживаются в старых версиях Windows. Стандартная 
пиктограмма (также называемая большой) используется везде, где требуются 
большие пиктограммы, например в окне программы Explorer, если установлена 
опция Large Icons, а также при перемещении пиктограммы на рабочий стол. Малая 
пиктограмма используется в программе Explorer в режиме Small Icons, а также 
отображается в виде пиктограммы системного меню приложения и в панели задач 
(task bar). При использовании редактора ресурсов, поставляемого фирмой 
Microsoft с Visual C++ версии 4 (и выше), большую и малую пиктограмму можно 
создавать в одном и том же файле. Если малая пиктограмма не определена, то, 
при необходимости, большая пиктограмма будет просто сжата до требуемого 
размера. Если определены обе пиктограммы, то MFC автоматически выберет нужную. 
В Windows 95 можно также создавать пиктограммы размером 48х48 пикселей, но для 
их использования нужно будет внести изменения в системную базу регистрации. 
    Когда изображения пиктограммы и курсора созданы, их необходимо добавить в 
файл ресурсов с помощью операторов ICON и CURSOR. Общий вид этих операторов следующий: 

    Имя пиктограммы ICON Имя файла 

    Имя курсора CURSOR Имя файла 

    Здесь параметры Имя_пиктограммы и Имя_курсора являются именами, 
идентифицирующими, соответственно, пиктограмму и курсор. Они используются 
программой при ссылке на соответствующие ресурсы. Параметр Имя_файла указывает 
на файл, в котором хранятся требуемые изображения. 
    В последующих примерах мы будем вызывать пиктограмму MY1CON и курсор 
MYCURSOR. Нарисуйте в гра4)ическом редакторе свою собственную пиктограмму и 
запишите се в файл ICON.ICO, а курсор — в файл CURSOR.CUR. После этого 
создайте такой файл ресурсов: 

    MYCURSOR CURSOR CURSOR.CUR 
    MY1CON ICON ICON.ICO 


    Регистрация пиктограммы и курсора 

    Класс окна приложения определяет атрибуты главного окна, включая вид 
пиктограммы приложения и курсора мыши. До сих пор мы просто использовали 
стандартный класс, автоматически генерируемый MFC при создании главного окна. 
Для того чтобы задать собственную пиктограмму и/или курсор, необходимо 
определить и свой собственный класс окна. Как упоминалось в главе 2, для этого 
используется функция AfxRegisterWiidClass(). Ее прототип таков: 

    LPCSTR AFXAPI AfxRegisterWndClass(UINT Style, 
    HCURSOR hCur=0, II дескриптор курсора 
    HBRUSH hBrush-^O, II дескриптор кисти 
    HICON hIcon^O); II дескриптор пиктограммы 


    7. Работа с пиктограммами, курсорами и растровыми изображениями 165 

    В случае успешного завершения функция возвращает имя созданного класса, 
которое может быть передано в качестве параметра функции CreateQ при создании окна. 
    Параметр Style задает дополнительные установки стиля окна. В большинстве 
случаев используется стиль по умолчанию. Поэтому вначале можно задать параметр 
Style равным нулю. В следующих параметрах содержатся дескрипторы трех 
элементов, которые определяются классом окна, а именно: курсора, кисти* и 
пиктограммы системного меню. Т.е. ИСчг задает дескриптор курсора, hBrush — 
дескриптор кисти, используемой для заполнения фона рабочей области окна, a 
hicon — дескриптор пиктограммы системного меню. Необходимо помнить, что 
дескрипторы не являются объектами. Они широко используются в традиционных 
Windows-программах для идентификации различных элементов. В MFC дело обстоит 
иначе. Поскольку большинство элементов описывается с помощью объектов, то 
необходимость в дескрипторах отпадает. Но они все же требуются в функции 
AfxRegisterWndClass(). К счастью, в MFC их значения получить достаточно 
просто. Как это сделать, мы рассмотрим в следующих двух параграфах. 

    Загрузка пиктограммы и курсора 

    Чтобы использовать собственную пиктограмму и курсор, их необходимо 
загрузить и получить их дескрипторы. Для этого используются функции Loadlcon() 
и LoadCursor(), являющиеся членами класса CWinApp. Прототипы тех вариантов 
данных функций, которые используются в этой главе, таковы: 

    HICON CWinApp::LoadIcon(LPCSTR IpszIconName} const; 
    HCURSOR CWinApp::LoadCursor(LPCSTR IpszCursorName) const; 

    Параметр Ips^IconName определяет имя ресурса пиктограммы в файле ресурсов 
Параметр IpszCursorName определяет имя ресурса курсора. Функция LoadIconQ 
загружает указанную пиктограмму и возвращает ее дескриптор. То же самое, но 
для курсора, делает функция LoadCursorQ. Обе функции возвращают NULL, если 
ресурсы не могут быть загружены. 
    Поскольку обе функции в качестве результата возвращают дескрипторы 
соответствующих элементов, они могут быть использованы в качестве параметров 
функции AfxRegisterWndClass(). 

    Кисти и стили заполнения 

    Подробное описание кистей (и стилей заполнения вообще) мы отложим до главы 
9, в которой объясняется работа с различными GDI-объектами. Поэтому ниже 
объясняются лишь основные моменты. 
    Чтобы зарегистрировать класс окна, необходимо указать в качестве параметра 
д дескриптор кисти, используемой для заполнения фоновым цветом рабочей области 
1 окна. Стиль заполнения, называемый кистью (brush), — это ресурс, 
предназначенный для рисования на экране различных графических объектов и 
использующий готовую , маску с определенным шаблоном заполнения, размером и 
цветом. Приложение | может определить либо свою собственную кисть, либо 
использовать одну из стан- | дартных кистей. В данной главе используется 
последний вариант (позднее мы i рассмотрим, как создавать собственные кисти). 
Кисти описываются классом CBrush, который порождается от класса CGdiObject. 

    *  Специальный шаблон заполнения, см. ниже. — Примеч. ред. 


    166                                        MFC: основы программирования 

    Получить стандартную кисть можно с помощью функции CreateStockObjectQ, 
являющейся членом класса CGdiObject. Ее прототип таков: 

    BOOL CGdiObject::CreateStockObject(int Item}; 

    Здесь параметр Item обозначает готовый GDI-элемент, который необходимо 
получить (таким элементом может быть одна из готовых кистей). Вот названия 
некоторых стандартных кистей, которые могут использоваться в программе (табл. 7.1): 

    Таблица 7.1. Некоторые стандартные кисти 

    Константа	Тип фона 

    BLACKBRUSH	Черный 
    DKGRAYJBRUSH	Темно-серый 
    HOLLOWBRUSH	"Прозрачный" 
    LTGRAYBRUSH	Светло-серый 
    WHITEBRUSH	Белый 

    Функция возвращает ненулевое значение, если стандартный элемент может быть 
получен, и ноль — в противном случае. 
    Чтобы создать кисть, которая затем будет передана в функцию 
Aft(RegisterWndClass(), можно использовать такую конструкцию: 

    CBrush bkbrush; 
    // стандартный фон 
    bkbrush.CreateStockObject(WHITE_BRUSH) ; 

    Здесь создается объект кисти, который затем связывается со стандартной 
белой кистью. Теперь объект bkbrush можно использовать в качестве параметра 
hBrush в функции AfxRegisterWndClassQ, поскольку класс CBrush поддерживает 
преобразование типа CBrush в тип HBRUSH. 
    При использовании стандартного класса окна, заданного в MFC, фон 
создаваемого окна будет белым. Ему соответствует стандартная кисть 
WHITE_BRUSH. Она же используется в последующих примерах данной главы. Можете 
поэкспериментировать с другими типами кистей. 

    Пример программы, использующей собственную пиктограмму и курсор 

    В следующей программе используются собственная пиктограмма и курсор. 
Пиктограмма отображается всякий раз, когда программа представлена в 
соответствующей форме (т.е. в виде пиктограммы). Если запустить программу в 
Windows 95, то для системного меню будет использована малая пиктограмма, 
которая также будет представлять программу в панели задач. Когда вы помещаете 
программу на рабочий стол, она отображается большой пиктограммой, которая 
также будет показана в окне программы Explorer в режиме Large Icons. 
Собственный курсор программы появляется при попадании курсора мыши в пределы 
окна этой программы. Таким образом, 

    7. Работа с пиктограммами, курсорами и растровыми изображениями    167 

    в границах данного окна форма курсора мыши будет автоматически меняться на 
ту, которая задана в программе- При перемещении курсора за пределы окна 
автоматически будет восстановлена стандартная форма курсора. 
    Перед компиляцией программы не забудьте, что сначала необходимо с помощью 
графического редактора создать образ пиктограммы (или пиктограмм, для Windows 
95) и курсора, а затем добавить их в файл ресурсов программы. 
    Ниже приведен текст файла IC.H, содержащего объявления порождаемых классов программы: 

    // IC.H 
    // Это класс для создания главного окна 
    class CMainWin : public CFrameWnd 
    { 
    public: 
    CMainWin(LPCSTR ClassName); // в качестве параметра 
    // указывается имя класса окна 
    DECLARE_MESSAGE_MAP() 
    }; 
    // Это класс для создания приложения 
    class CApp : public CWinApp 
    { 
    public: 
    BOOL Initlnstance () ; 
    }; 

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

    // Программа, использующая собственный курсор и пиктограмму 
    ftinclude <afxwin.h> 
    #include "ic.h" 
    // Создание окна, имеющего заданный пользователем класс 
    CMainWin::CMainWin(LPCSTR ClassName) 
    ( 
    Create(ClassName, "Custom Icon and Cursor"); 
    // Инициализация приложения 
    BOOL CApp::Initlnstance() 
    ( 
    CBrush bkbrush; 
    // стандартный фон 
    bkbrush.CreateStockObject(WHITE_BRUSH) ; 


    168                                    MFC: основы программирования 


    LPCSTP, cname = AfxRegisterWndClass(0, 
    LoadCursor("MYCURSOR" 
    bkbrush, 
    Loadlcon("MYICON")) ; 
    m pMainWnd = new CMainWin(cname); 
    m pMainWnd->ShowWindow(m nCmdShow) ; 
    m pMainWnd->UpdateWindow(); 
    return TRUE; 
    // Это очередь сообщений приложения 
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) 
    END_MESSAGE_MAP() 
    CApp App; // создание экземпляра приложения 

    Внимательно посмотрите на текст функции CApp::InitInstaiice(). Вначале в 
ней создается объект кисти, который затем привязывается к стандартной белой 
кисти. После этого регистрируется класс окна с указанием пользовательской 
пиктограммы и курсора, а также созданной кисти. Имя класса, возвращаемое 
функцией AfxRegisterWndClassQ, передается в качестве параметра конструктору 
CMainWinQ, который создает главное окно приложения. Окно будет создано 
согласно атрибутам, связанным с именем класса, указанного в качестве параметра 
функции CreateQ. 
    Созданная нами пиктограмма показана на рис. 7.2. (Конечно, это всего лишь 
пример. Ваши пиктограммы, естественно, будут другими. Кроме того, в Windows 95 
создается также малая пиктограмма.) В программе используется собственный 
курсор, который появляется, если курсор мыши находится в пределах окна 
программы. Проверьте, как она работает, прежде чем читать дальше. 

    Рис. 7.2. Пользовательская пиктограмма 


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

    В Windows определены несколько системных пиктограмм и курсоров, которые 
вполне можно использовать в своей программе. Но для этого применяются уже не 
функции Loadlcon() и LoadCursorQ, а функции LoadStandardIcon() и 
LoadStandardCursor(). Их прототипы таковы: 

    HICON CWinApp::LoadStandardIcon(LPCSTR Ipszlcon) const.; 
    HCURSOR CWinApp::LoadStandardCursor(LPCSTR IpszCursor) const; 


    7. Работа с пиктограммами, курсорами и растровыми изображениями    169 

    Здесь параметр Ips^lcon указывает на встроенную пиктограмму и должен 
принимать одно из следующих значений (табл. 7.2): 

    Таблица 7.2. Встроенные пиктограммы Windows 

    КонстантаIDIAPPLICATION IDIASTERISK IDIEXCLAMATION IDIHAND IDIQUESTION 
IDIWINLOGO	Вид пиктограммыСтандартная системная пиктограмма Информационная 
пиктограмма с буквой "I" Пиктограмма с восклицательным знаком Пиктограмма с 
надписью "Stop" Пиктограмма с вопросительным знаком Пиктограмма с логотипом 
Windows 95 
    Параметр /pszCursor определяет имя встроенного курсора. Наиболее 
распространенные значения параметра таковы (табл. 7.3): 

    Таблица 7.3. Некоторые из встроенных курсоров Windows 

    КонстантаIDCARROW IDCCROSS I DC J BEAM IDC WAIT	Форма курсораСтандартный 
указатель типа "стрелка" Перекрестие Текстовый курсор Песочные часы 
    \JU\^    4/J ПГЧ-l.ytfl    U\J^JLl^ft.lLU,l.l,l\J 1    11^/1 1^'^1^/1-И-/^ 
  ^lILl^^/llfl»-'   J 1 ^/»•*    J »>-H ^ 1-1-1 « H-*i?l    ->U iJ\/J-/l-l-l 
V/I If in    П         , 
    NULL — в противном случае.                                                 | 

    Далее описывается программа, в которой используется встроенная пиктограмма 
 j и курсор. Вот текст файла SYSIC.H, содержащего объявления порождаемых 
классов:  ! 

    // SYSIC.H                                                            | 
    // Это класс для создания главного окна 
    class CMainWin : public CFrameWnd 
    { 
    public: 
    CMainWin(LPCSTR ClassName); // в качестве параметра 
    // указывается имя класса окна 
    DECLARE_MESSAGE_MAP () 
    ); 
    // Это класс для создания приложения 
    class CApp : public CWinApp 
    ( 
    public: 
    BOOL Initlnstance() ; 
    ); 


    170                                    MFC: основы программирования 

    Вот текст самой программы: 

    // Программа, использующая стандартный курсор и пиктограмму 
    itinclude <afxwin.h> 
    tinclude "sysic.h" 
    // Создание окна, имеющего заданный пользователем класс 
    CMainWin::CMainWin(LPCSTR ClassName) 
    ( 
    Create(ClassName, "Using a Predefined Icon and Cursor"); 
    } 
    // Инициализация приложения 
    BOOL CApp::Initlnstance() ( 
    CBrush bkbrush; 
    // стандартный фон 
    bkbrush.CreateStockObj ect(WHITE_BRUSH) ; 
    LPCSTR cname = AfxRegisterWndClass(0, 
    LoadStandardCursor(IDC_CROSS), 
    bkbrush, 
    LoadStandardIcon(IDI_QUESTION)) ; 
    m_pMainWnd = new CMainWin(cname) ; 
    m_pMainWnd->ShowWindow(m_nCmdShow) ; 
    m_pMainWnd->UpdateWindow() ; 
    return TRUE; 
    1 
    // Это очередь сообщений приложения 
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) 
    END_MESSAGE_MAP() 
    CApp App; // создание экземпляра приложения 

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

    Работа с растровыми изображениями 

    Различные растровые образы являются графическими изображениями. Поскольку 
Windows является графической операционной системой, то имеет смысл 
использовать такие изображения в программах. С помошью богатого набора 
графических функций, содержащихся в API и инкапсулируемых в MFC, можно 
создавать линии, окружности, прямоугольники и более сложные изображения, 
состоящие из этих элементов. Но нужно также понимать, что растровые образы 
представляют собой 

    7. Работа с пиктограммами, курсорами и растровыми изображениями    171 

    другой тип графики и используют иной механизм отображения на экране. 
Растровый образ является самостоятельным графическим ресурсом, который 
используется в программе как единое целое. Он содержит побитовое описание 
изображения, выводимое на экран без изменений. Другими словами, растровый 
образ содержит полное изображение, которое программа обычно выводит на экран 
целиком. Растровые изображения в MFC описываются классом CBitmap. 

    Создание растрового изображения 

    Поскольку следующая наша программа будет выводить на экран растровое 
изображение, то сначала необходимо создать соответствующий ресурс. Для этого 
можно использовать тот же самый графический редактор, что и для других 
графических ресурсов. Но, в отличие от пиктограмм и курсоров, имеющих 
фиксированный размер, размер растрового изображения зависит от его создателя. 
В следующем i примере используется изображение размером 64х64 пикселя. Назовем 
этот файл ВР.ВМР. Затем необходимо создать файл ресурсов, содержащий следующую строку: 

    MYBPl BITMAP ВР.ВМР 

    Нетрудно догадаться, что оператор BITMAP задаст ресурс растрового 
изображения. Общий вид оператора следующий: 

    Имя изображения BITMAP Имя файла 

    Здесь параметр Имя_чзображения является именем, идентифицирующим данный 
ресурс. Это имя используется в программе при ссылке на изображение. Второ); 
параметр определяет имя файла, в котором содержится само изображение.      

    ; 
    Вывод растрового изображения на экран 

    Когда растровое изображение создано и помешено в файл ресурсов, его можно 
выводить на экран сколько угодно раз. Однако этот процесс немного сложнее, чем 
при работе с пиктограммами или курсорами. 
    Сначала необходимо создать объект типа CBitmap и с помощью функции 
LoadBitmapO загрузить в него растровое изображение, указанное в файле 
ресурсов. Прототип функции таков: 

    BOOL CBitmap::LoadBitmap(LPCSTR IpszBitmapName) ; 

    Параметр Ips^BitmapName определяет имя растрового изображения. Функция 
возвращает ненулевое значение при успешном завершении и ноль — в противном случае. 
    В следующем фрагменте создастся объект растрового образа, в который 
загружается изображение, названное "MYBIT": 

    CBitmap bit; 
    bit.LoadBitmap("MYBIT") ; 

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

    172                                    MFC: основы программирования 

    2. Получить совместимый с ним контекст устройства для области памяти 
(memory device context), в которой будет храниться растровое изображение до 
момента вывода на экран. 
    3. Выбрать требуемое изображение из файла ресурсов в контекст области памяти. 
    4. И наконец, скопировать изображение из контекста области памяти в 
контекст окна. В результате изображение будет выведено на экран.* 
    Чтобы увидеть, как реализуются эти действия, рассмотрим следующий фрагмент 
программы. В нем растровое изображение выводится на экран после каждого щелчка 
левой кнопкой мыши. (Предполагается, что изображение уже загружено и хранится 
    в объекте типа CBitmap, называющемся m_bmpl.) 

    // Вывод изображения на экран 
    afx_msg void CMainWin::OnLButtonDown(UINT flags, CPoint loc) 
    ( 
    CClientDC DC (this) ; 
    CDC memDC; 
    // создание совместимого контекста устройства 
    memDC.CreateCompatibleDC(&DC) ; 
    // выбор изображения в контекст области памяти 
    memDC.SelectObject(&m_bmpl) ; 
    // копирование изображения в контекст окна 
    DC.BitBit (loc.x, loc.у, 64, 64, SmernDC, 0, О, SRCCOPY) ; 
    } 

    Давайте пошагово проследим выполнение данного фрагмента. Сначала 
объявляются два контекста устройств. Первый, DC, связан с текущим окном. 
Второй, memDC, не инициализирован и предназначен для области памяти, в которой 
будет храниться изображение. Затем с помощью функции CreateCompatibIeDC(), 
являющейся членом класса CDC, этот контекст объявляется совместимым с 
контекстом окна. Данная функция имеет следующий прототип: 

    virtual BOOL CDC::CreateCompatibleDC(CDC *pDC); 

    Эта функция создает контекст для области памяти, совместимый с контекстом, 
на который указывает параметр pDC. Данная область памяти используется для 
построения изображения перед его выводом на экран. Функция возвращает 
ненулевое значение при успешном завершении и ноль — в противном случае. 
    Перед тем как изображение будет выведено на экран, оно должно быть выбрано 
в контекст устройства, связанный с областью памяти, путем вызова функции 
SelectObject(). Это необходимо потому, что в приложении может использоваться несколько 

    *   Читателям, которые в результате таких объяснений окончательно 
запутались в том, что же такое контекст устройства, поясним: это не область 
памяти, в которую или из которой можно что-то скопировать, а структура данных. 
Поэтому пункт 3 следует понимать так, что в контекст устройства, связанный с 
областью памяти, передается ссылка на изображение, а не само изображение. 
Пункт 4 следует понимать так, что ссылка на контекст, связанный с областью 
памяти, передается в контекст, связанный с окном вывода. — Примеч. ред. 


    7. Работа с пиктограммами, курсорами и растровыми изображениями    173 

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

    CBitmap *CDC::SelectObject(CBitmap *pBltmap); 

    Здесь параметр pBitmap является указателем на объект изображения, 
выбираемого в контекст устройства. Функция возвращает указатель на ранее 
выбранный объект, что позволяет позже выбрать его еще раз. В случае ошибки 
возвращается NULL. Нужно четко представлять, что изображение может быть 
выбрано только в контекст, связанный с областью памяти. Его нельзя, например, 
выбрать непосредственно в контекст окна. 
    Для отображения на экране содержимого выбранного объекта используется 
функция BitBltQ, которая копирует изображение из исходного контекста 
устройства в контекст, связанный с вызывающим функцию объектом. Прототип этой 
функции таков: 

    BOOL CDC::BitBlt (int X, int У, int Width, ink Height, 
    CDC *pSourceDC, ink SourceX, int SourceY, 
    DWORD dwRasterOp); 

    Параметры Х и У определяют координаты точки начала изображения. Размеры 
изображения задаются параметрами Width и Height. Параметр pSourceDC является 
указателем на исходный контекст устройства, которым в данном случае будет 
контекст области памяти, получаемый с помощью функции CreateCompatibleDC(). 
Параметры SourceX и Source Y задают координаты верхнего левого угла 
изображения. Обычно они равны 0. Значение dwRasterOp определяет режим 
побитовой передачи изображения из памяти на экран. Наиболее распространенные 
значения этого параметра следующие (табл. 7.4): 

    Таблица 7.4. Битовые режимы 

    Константа  Эффект

SRCAND
SRCCOPY 
SRCINVERT 
SRCPAINT	
Над содержимым области памяти и содержимым экрана выполняется операция побитового И (AND)
Содержимое области памяти копируется без изменений, стирая существующее изображение
Над содержимым области памяти и содержимым экрана выполняется операция исключающего ИЛИ (XOR)
Над содержимым области памяти и содержимым экрана выполняется операция побитового ИЛИ (OR) 

    Функция возвращает ненулевое значение при успешном завершении и ноль — в 
противном случае. 
    В данном примере при вызове функции BitBItQ изображение целиком копируется 
в область окна, где была нажата кнопка мыши. 

    174                                    MFC: основы программирования 

    Растровое изображение является ресурсом, который должен быть удален из 
памяти до завершения работы приложения. Обычно это выполняется автоматически 
при уничтожении объекта типа CBitmap. Но можно выполнять это программным путем 
с помощью функции CGdiObject::DeleteObject(), которая имеет такой прототип: 

    II BOOL CGdiObject::DeleteObject (); 

    Функция возвращает ненулевое значение при успешном завершении и ноль — в 
противном случае. 

    Пример программы работы с растровым изображением 

    В данной программе при каждом щелчке левой кнопкой мыши на экран выводится 
растровое изображение, созданное пользователем. Изображение будет размещено в 
позиции, на которую указывал курсор мыши. Пример работы программы представлен 
на рис. 7.3. Вот текст файла ВМР.Н, содержащего объявления порождаемых классов: 

    //  ВМР.Н 
    // Это класс для создания главного окна 
    class CMainWin : public CFrameWnd 
    ( 
    public: 
    CBitmap m bmpi; // объект растрового изображения 
    CMainWin () ; 
    afx_msg void OnLButtonDown(UINT flags, CPoint loc) ; 
    DECLARE_MESSAGE_MAP() 
    }; 
    // Это класс для создания приложения 
    class CApp : public CWinApp 
    ( 
    public: 
    BOOL Initlnstance() ; 
    ); 

    Обратите внимание, что в класс CMainWin добавлена переменная in_bmpl. Это 
объект типа CBitmap, который используется для хранения изображения. С 
технической точки зрения данная переменная не обязательно должна являться 
членом класса CMainWin (и вообще какого-либо класса), просто логичнее 
разместить ее именно здесь. 

    7. Работа с пиктограммами, курсорами и растровыми изображениями    175 

    H Display a Bitmap 

    Рис. 7.3. Пример работы с растровым изображением 

    Это текст самой программы: 

    // Программа, выводящая на экран растровое изображение 
    ftinclude <afxwin.h> 
    #include "bmp.h" 
    // Создание окна 
    CMainWin::CMainWin() 
    { 
    Create(NULL, "Display a Bitmap"); 
    // загрузка изображения 
    m_bmpl.LoadBitmap("MYBPl") ; 
    // Инициализация приложения 
    BOOL CApp::Initlnstance () 
    { 
    m pMainWnd = new CMainWin(); 
    m_pMainWnd->ShowWindow(m__nCmdShow) ; 
    m_pMainWnd->UpdateWindow() ; 
    return TRUE; 
    // Это очередь сообщений приложения 
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) 
    ON_WM_LBUTTONDOWN() 


    176 MFC: основы программирования 


    END_MESSAGE_MAP() 
    // Вывод изображения на экран 
    afx_msg void CMainWin::OnLButtonDown(UINT flags, CPoint loc) 
    ( 
    CClientDC DC(this); 
    CDC memDC; 
    // создание совместимого контекста устройства 
    memDC.CreateCompatibleDC(&DC) ; 
    // выбор изображения в контекст области памяти 
    memDC.SelectObject(&m bmpi); 
    // копирование изображения в контекст окна 
    DC.BitBIt(loc.x, loc.у, 64, 64, &memDC, 0, О, SRCCOPY) ; 
    ) 
    САрр Арр; // создание экземпляра приложения 

    Как видите, изображение загружается внутри конструктора CMainWin(). 
Поскольку оно будет отображаться при каждом щелчке левой кнопкой мыши, 
целесообразно загрузить его один раз, при запуске программы. Конечно, это 
можно делать всякий раз при возникновении такой необходимости. Но если заранее 
известно, что ресурс, такой как растровое изображение, будет использоваться 
неоднократно, лучше все-таки загружать его один раз. 

    Работа с несколькими изображениями 

    Прежде чем завершить тему растровых изображений, необходимо подчеркнуть 
один важный момент. В программе допускается использование нескольких 
изображений. Количество их не ограничивается. Когда нужно отобразить одно из 
них, его можно просто выбрать согласно методике, описанной в предыдущем параграфе. 
    Чтобы продемонстрировать это, давайте добавим еще одно изображение в 
предыдущую программу. Оно будет отображаться при нажатии правой кнопки мыши. 
Сначала добавьте такую строку в ({)айл ресурсов: 

    MYBP2 BITMAP BP2.BMP 

    Затем с помощью графического редактора создайте изображение размером 64х64 
пикселя и запишите его в файл ВР2.Н. 
    После этого наберите обновленную версию файла, содержащего объявления 
порождаемых классов, назвав его ВМР2.Н: 

    // ВМР2.Н 
    // Это класс для создания главного окна 
    class CMainWin : public CFrameWnd 
    ( 
    public: 
    CBitmap m bmpi, m bmp2; // объекты растровых изображений 
    CMainWin() ; 
    afx msg void OnLButtonDown(UINT flags, CPoint loc); 


    7. Работа с пиктограммами, курсорами и растровыми изображениями    177 


    afx_msg void OnRButtonDown(UINT flags, CPoint loc) ; 
    DECLARE_MESSAGE_MAP() 
    ) ; 
    // Это класс для создания приложения 
    class CApp : public CWinApp 
    ( 
    public: 
    BOOL Initlnstance(); 
    }; 

    В этой версии файла в класс CMainWin добавлена переменная inJbmp2 и 
обработчик OnRButtonDown(). 
    Ниже приводится обновленный текст программы. В ней загружается второе j 
изображение, в очередь сообщений добавлена макрокоманда ON_WM_RBUTTON- J 
DOWN(), а также включена реализация обработчика OnRButtonDown().           

    // Программа, выводящая на экран два изображения 
    ^include <afxwin.h                                                   , 
    #include "bmp2.h"                                                    ! 
    // Создание окна 
    CMainWin::CMainWin () 
    { 
    Create(NULL, "Display Two Bitmaps"); 
    m_bmpl.LoadBitmap("MYBP1") ; 
    m_bmp2.LoadBitmap("MYBP2") ; 
    ) 
    // Инициализация приложения                                           j 
    BOOL CApp::Initlnstance () 
    { 
    m_pMainWnd = new CMainWin(); 
    m_pMainWnd-ShowWindow(m_nCmdShow) ; 
    m pMainWnd-UpdateWindow() ; 
    return TRUE; 
    // Это очередь сообщений приложения 
    BEGIN_MESSAGE_MAP(CMainWin, CFrameWnd) 
    ON_WM_LBUTTONDOWN() 
    ON_WM_RBUTTONDOWN() 
    END_MESSAGE_MAP() 
    // Вывод на экран первого изображения 
    afx_insg void CMainWin::OnLButtonDown(UINT flags, CPoint loc) 
    ( 
    CClientDC DC (this); 
    CDC memDC; 


    178                                    MFC: основы программирования 


    // создание совместимого контекста устройства 
    meniDC.CreateCompatibleDC (&DC) ; 
    // выбор изображения в контекст области памяти 
    memDC.SelectObject(&m_bmpl) ; 
    // копирование изображения в контекст окна 
    DC.BitBIt(loc.x, loc.y, 64, 64, &memDC, О, 0, SRCCOPY); 
    // Вывод на экран второго изображения 
    afx_msg void CMainWin::OnRButtonDown(UINT flags, CPoint loc) 
    ( 
    CClientDC DC(this); 
    CDC memDC; 
    // создание совместимого контекста устройства 
    memDC.CreateCompatibleDC(&DC) ; 
    // выбор изображения в контекст области памяти 
    memDC.SelectObject(&m_bmp2) ; 
    // копирование изображения в контекст окна 
    DC.BitBIt (loc.x, loc.y, 64, 64, &memDC, О, О, SRCCOPY); 
    САрр Арр; // создание экземпляра приложения 

    Теперь программа работает таким образом, что по нажатию левой кнопки мыши 
на экран выводится первое изображение, а по нажатию правой кнопки мыши — 
второе изображение. Пример работы программы представлен на рис. 7.4. 

    В Llisplau Two Bitmap! 

    Рис. 7.4. Пример работы с несколькими изображениями 

    7. Работа с пиктограммами, курсорами и растровыми изображениями 179 
