Skip to content Skip to footer

Перевод книги Julian’а Smart’а – Глава X – Работа с Изображениями – Часть 1

Скачать PDF-версию (942 КБ)

В этой главе рассматривается работа с растровыми изображениями. Изображения очень важны для “дизайна” вашего приложения, и могут использоваться с элементами управления, например с панелями инструментов, списками, вкладками, кнопками, HTML окнами, или при рисовании. Иногда их можно сделать невидимыми в приложении, например, когда нужно избежать мерцания во время прорисовки. В этой главе, мы рассмотрим разные классы изображений и методы перегрузки стандартных классов иконок и изображений, которые есть в wxWidgets.

Программирование с использованием wxBitmap

С помощью wxBitmap Вы можете делать несколько вещей:

  • Рисовать его в окне с помощью контекста устройства.
  • Использовать его, как изображение для таких классов, как wxBitmapButton, wxStaticBitmap, или wxToolBar.
  • Использовать его для рисования методом двойной буферизации (рисования в невидимом буфере wxMemoryDC, перед тем как рисовать в окне).

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

Перед тем, как мы обсудим создание wxBitmap и рисование с его помощью, давайте рассмотрим функции класса (Таблица 10-2).

  • wxBitmap – Растровое изображение может быть создано с заданными высотой и шириной, из другого растрового изображения, из wxImage, XPM данных (char**), битовых данных (char[]), или из файла, с указанием имя файла и его типа.
  • ConvertToImage – Конвертирует в wxImage, с сохранением прозрачности.
  • CopyFromIcon – Создает растровое изображение из wxIcon.
  • Create – Создает растровое изображения из данных, или заданного размера.
  • GetWidth, GetHeight – Возвращает размеры растрового изображения.
  • GetDepth – Возвращает глубину цвета изображения.
  • GetMask, SetMask – Возвращает wxMask объект или NULL.
  • GetSubBitmap – Возвращает область текущего изображения, как новое растровое изображение.
  • LoadFile, SaveFile – Загружает файл и (для некоторых форматов) сохраняет его.
  • Ok – Возвращает true, если объект содержит данные растрового изображения.

Создание wxBitmap

Есть несколько способов создать объект wxBitmap.
Вы можете создать неинициализированный объект (без данных изображения), используя конструктор по умолчанию. Вам нужно будет вызвать Create, LoadFile или назначить объекту существующее растровое изображение для того, что бы с ним работать.
Вы можете создать wxBitmap, задав ему размер, и глубину. Созданное растровое изображение будет заполнено произвольными данными, поэтому Вам придется на нем что-нибудь нарисовать. Снизу показан пример, который создает изображение 200 x 100 пикселей, и задает ему белый цвет фона.

// Создает изображение размером 200x100 пикселей с текущей глубиной дисплея.
wxBitmap bitmap(200, 100,  -1);

// Создаем контекст устройства памяти (memory device context, далее DC)
wxMemoryDC dc;

// Назначаем контексту устройства наше изображение
dc.SelectObject(bitmap);

// задаем белый фон
dc.SetBackground(*wxWHITE_BRUSH);

// Закрашиваем изображение белым (очищаем)
dc.Clear();

// Отключаем изображение от контекста
dc.SelectObject(wxNullBitmap);

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

// Загружаем картинку из файла
wxImage image(wxT("image.png"), wxBITMAP_TYPE_PNG);

// Конвертируем в растровое изображение
wxBitmap bitmap(image);

Растровое изображение так же можно создать, используя иконку, функцией CopyFromIcon:

// Загружаем иконку
wxIcon icon(wxT("image.xpm"), wxBITMAP_TYPE_XPM);

// Конвертируем иконку в растровое изображение
wxBitmap bitmap;
bitmap.CopyFromIcon(icon);

Или же можно загрузить изображение из файла:

// Load from a file
wxBitmap bitmap(wxT("picture.png", wxBITMAP_TYPE_PNG);
if (!bitmap.Ok())
{
    wxMessageBox(wxT("Sorry, could not load file."));
}

wxBitmap может загружать все типы файлов, которые может загружать wxImage (смотрите Таблицу 10-7), используя wxImage или более эффективную реализацию некоторых типов файлов для конкретной платформы. wxWidgets поддерживает наиболее популярные форматы PNG, JPEG, TIFF, BMP, и XPM, загрузка и сохранение которых поддерживается на всех платформах.
Таблица 10-7. Доступные Обработчики Форматов Изображений

  • wxBMPHandler – Для загрузки и сохранения Windows файлов растровых изображений.
  • wxPNGHandler – Для загрузки и сохранения файлов PNG. Поддерживаются изображения с прозрачностью и альфа каналом.
  • wxJPEGHandler – Для загрузки и сохранения файлов JPEG.
  • wxGIFHandler – GIF файлы: только для загрузки, из-за юридических вопросов.
  • wxPCXHandler – Для загрузки и сохранения PCX файлов. wxPCXHandler подсчитывает количество цветов в изображении; если в изображении 256 или меньше, оно будет сохранено в 8-битном формате; в противном случае в 24-битном.
  • wxPNMHandler – Для загрузки и сохранения PNM файлов. Загрузка PNMs работает только для ASCII или строковых RGB изображений. При сохранении в PNM формате, wxPNMHasndler всегда сохраняет в строковом RGB.
  • wxTIFFHandler – Для загрузки и сохранения TIFF файлов.
  • wxIFFHandler – Для загрузки IFF файлов.
  • wxXPMHandler – Для загрузки и сохранения XPM файлов.
  • wxICOHandler – Для загрузки и сохранения Windows иконок.
  • wxCURHandler – Для загрузки и сохранения файлов курсора Windows.
  • wxANIHandler – Для загрузки и сохранения анимированных файлов курсора Windows.

Также можно загрузить PICT ресурсы для Mac OS X, указав wxBITMAP_TYPE_PICT_RESOURCE.
Если Вы хотите загрузить специфические ресурсы для данной платформы, Вы можете использовать wxBITMAP макрос. Например:

#if !defined(__WXMSW__) & !defined(__WXPM__)
#include "picture.xpm"
#endif

wxBitmap bitmap(wxBITMAP(picture));

На Windows и OS/2 этот код будет загружать ресурс picture из исполняемого файла, на всех других платформах, он будет загружать переменную picture_xpm из XPM файла. В любом случае XPM поддерживается всеми платформами, поэтому необходимости в этом макросе нет.

Использование wxMask

Каждый объект wxBitmap может иметь wxMask, монохромное растровое изображение, которое указывает прозрачные области основного растрового изображения. Оно создается автоматически, когда Вы загружаете изображение с прозрачностью, например XPM, PNG, или GIF изображения, но Вы можете создать его программно, и назначить функцией SetMask. Создать wxMask можно из wxBitmap, или из wxBitmap, с заданием цвета, который будет указывать на прозрачную область.

Следующий пример создает монохромное прозрачное изображение mainBitmap, шириной в 32 пикселя и 32 пикселя высотой, из данных растрового изображения (imageBits) и маски (maskBits), где 1 это черный а 0 белый для битов изображения, и 1 непрозрачность а 0 прозрачность для маски.

static char imageBits[] = { 255, 255, 255, 255, 31,
  255, 255, 255, 31, 255, 255, 255, 31, 255, 255, 255,
  31, 255, 255, 255, 31, 255, 255, 255, 31, 255, 255,
  255, 31, 255, 255, 255, 31, 255, 255, 255, 25, 243,
  255, 255, 19, 249, 255, 255, 7, 252, 255, 255, 15, 254,
  255, 255, 31, 255, 255, 255, 191, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
  255 };

static char maskBits[] = { 240, 1, 0, 0, 240, 1,
  0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 240, 1,
  0, 0, 240, 1, 0, 0, 240, 1, 0, 0, 255, 31, 0, 0, 255,
  31, 0, 0, 254, 15, 0, 0, 252, 7, 0, 0, 248, 3, 0, 0,
  240, 1, 0, 0, 224, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0 };

wxBitmap mainBitmap(imageBits, 32, 32);
wxBitmap maskBitmap(maskBits, 32, 32);
mainBitmap.SetMask(new wxMask(maskBitmap));

Формат XPM

Если Вам нужны небольшие растровые изображения с прозрачностью, например для кнопок на панели инструментов или для изображений на вкладках и списках, в wxWidgets очень удобно использовать XPM формат. Преимущество этого формата в том, что он использует C/C++ синтаксис, таким образом он может подгружаться динамически, и компилироваться в вашу программу. Например:

// Также можно использовать #include "open.xpm"

static char *open_xpm[] = {
/* columns rows colors chars-per-pixel */
"16 15 5 1",
"  c None",
". c Black",
"X c Yellow",
"o c Gray100",
"O c #bfbf00",
/* pixels */
"                ",
"          ...   ",
"         .   . .",
"              ..",
"  ...        ...",
" .XoX.......    ",
" .oXoXoXoXo.    ",
" .XoXoXoXoX.    ",
" .oXoX..........",
" .XoX.OOOOOOOOO.",
" .oo.OOOOOOOOO. ",
" .X.OOOOOOOOO.  ",
" ..OOOOOOOOO.   ",
" ...........    ",
"                "
};

wxBitmap bitmap(open_xpm);

Как Вы видите, XPM файлы состоят из символьных данных. Перед данными собственно изображения, записана палитра, где к каждому символу привязан свой цвет, с использованием встроенного идентификатора цвета, или шести-цифровым числом в шестнадцатеричном формате, перед которым ставится шестнадцатеричный флаг “#”. Идентификатор None указывает на прозрачную область изображения. Формат XPM непопулярен в графических редакторах под Windows, но Вы можете сохранить изображение как PNG и конвертировать его в XPM с помощью ImageBlocks (поставляется с DialogBlocks), или можно самому написать свой конвертер, используя wxWidgets.

Рисование растровых изображений (Bitmaps)

Растровое изображение непосредственно можно нарисовать двумя разными способами. Вы можете ассоциировать (назначить) его контексту устройства памяти (wxMemoryDC) и потом использовать wxDC::Blit для того, что бы перенести содержимое растрового изображения в другой контекст устройства. Или же можно просто использовать wxDC::DrawBitmap. В обоих случаях, если изображение имеет прозрачность или альфа канал, Вы должны указать это, передав true в функцию.
В этом примере показаны оба метода:

// Рисование растрового изображения с wxMemoryDC
wxMemoryDC memDC;
memDC.SelectObject(bitmap);

// Рисуем в координатах 100, 100 на конечном DC
destDC.Blit(100, 100,                         // Draw at (100, 100)
    bitmap.GetWidth(), bitmap.GetHeight(),    // Draw full bitmap
    & memDC,                                  // Draw from memDC
    0, 0,                                     // Draw from bitmap origin
    wxCOPY,                                   // Logical operation
    true);                                    // Take mask into account
memDC.SelectObject(wxNullBitmap);

// Альтернативный способ: используем DrawBitmap
destDC.DrawBitmap(bitmap, 100, 100, true);

Более детально рисование растровых изображений описывается в Главе 5 “Рисование и Печать”.

Упаковка графических ресурсов

Если Вы программировали под Windows, Вы привыкли загружать растровые изображения из ресурсов исполняемых файлов. Вы можете не изменять своей привычке, и загружать их из ресурсов, используя wxBITMAP_TYPE_BMP_RESOURCE в конструкторе, но скорее всего Вы предпочитаете менее платформозависимый метод.
Очень удобный способ паковать ресурсы, будь то растровые изображения, HTML файлы, или другие файлы, используемые в приложении, хранить их в одном zip архиве отдельно от исполняемого файла или в отдельной директории данных. Также Вы можете использовать функциональность виртуальных файловых систем в wxWidgets, что бы загружать изображение прямо из zip архива, как показано в следующем примере.

// Создадим новый объект файловой системы
wxFileSystem*fileSystem = new wxFileSystem;

wxString archiveURL(wxT("myapp.bin"));
wxString filename(wxT("myimage.png"));
wxBitmapType bitmapType = wxBITMAP_TYPE_PNG;

// Создаем URL
wxString combinedURL(archiveURL + wxString(wxT("#zip:")) + filename);
wxImage image;
wxBitmap bitmap;

// Открываем архив
wxFSFile* file = fileSystem->OpenFile(combinedURL);
if (file)
{
    wxInputStream* stream = file->GetStream();

    // Load and convert to a bitmap
    if (image.LoadFile(* stream, bitmapType))
        bitmap = wxBitmap(image);

    delete file;
}
delete fileSystem;

if (bitmap.Ok())
{
    ...
}

Более подробно о виртуальных файловых системах, Вы сможете узнать в Главе 14, “Файлы и Потоки”.

Программирование с wxIcon

wxIcon это небольшое растровое изображение, у которого всегда есть маска. wxIcon можно использовать:

  • Как иконку для фрейма или диалога
  • Как иконку для wxTreeCtrl, wxListCtrl, или wxNotebook через wxImageList класс (смотрите дальше в этой главе)
  • Рисовать иконку в контексте устройства, используя wxDC::DrawIcon

Таблица 10-3 основные функции класса.

  • wxIcon – Иконка может быть создана с использованием другой иконки, XPM данных (char**), битовых данных (char[]), или из файла с заданным форматом.
  • CopyFromBitmap – Создает иконку из wxBitmap.
  • GetWidth, GetHeight – Возвращает размер иконки.
  • GetDepth – Возвращает глубину иконки.
  • LoadFile – Загружает иконку из файла.
  • Ok – Возвращает true, если присутствуют данные иконки.

Создание wxIcon

Объект wxIcon можно создать, используя XPM данные, подключенные к приложению, из объекта wxBitmap, из битовых данных, или загрузить ее из файла, например из XPM файла с прозрачностью. В wxWidgets есть wxICON макрос, аналогичный к wxBITMAP макросу, который был рассмотрен выше, для загрузки из ресурса, характерного для данной платформы либо из XPM данных.
В Windows, LoadFile и схожий конструктор будет работать для Windows растровых изображений (BMP) и иконок (ICO), ресурсов и файлов. Если Вы хотите работать с другим форматом, загрузите файл в wxBitmap и сконвертируйте в иконку.
На Mac OS X и Unix/Linux с использованием GTK+, wxIcon имеет те же возможности при загрузке из файла, что и wxBitmap.
В ниже поданном примере показано создание wxIcon объекта разными способами.

// Метод 1: загрузка из XPM данных
#include "icon1.xpm"
wxIcon icon1(icon1_xpm);

// Метод 2: загрузка из ICO ресурса (только для Window и OS/2)
wxIcon icon2(wxT("icon2"));

// Метод 3: загрузка из ICO файла (только для Window и OS/2)
// Вы можете указывать желаемый размер, так как файл
// может содержать несколько иконок.
wxIcon icon3(wxT("icon3.ico"), wxBITMAP_TYPE_ICO, 16, 16);

// Метод 4: создание из растрового изображения
wxIcon icon4;
wxBitmap bitmap(wxT("icon4.png"), wxBITMAP_TYPE_PNG);
icon4.CopyFromBitmap(bitmap);

Использование wxIcon

В этом коде показаны три разных способа использования иконки wxIcon: установка как иконки фрейма, добавление иконки в список изображений и рисование иконки в контексте устройства.

#include "myicon.xpm"
wxIcon icon(myicon_xpm);

// 1: Установка иконкой фрейма
frame->SetIcon(icon);

// 2: Добавление в wxImageList
wxImageList* imageList = new wxImageList(16, 16);
imageList->Add(icon);

// 3: Рисование иконки в точке (10, 10)
wxClientDC dc(window);
dc.DrawIcon(icon, 10, 10);

Назначение Иконки Приложению

Назначить иконку приложению (для того, что бы операционная система использовала ее как значок приложения), нельзя с помощью инструментов wxWidgets, это одно из немногих мест, где Вы должны использовать разные способы для разных платформ.
На Windows, нужно добавить скрипт ресурса (расширение .rc) в ваш makefile, или в файл проекта, и добавить выражение ICON в файле .rc, например:

aardvarkpro ICON aardvarkpro.ico
#include "wx/msw/wx.rc"

Здесь, aardvarkpro.ico это имя файла Windows иконки с разными разрешениями и глубиной (обычно разрешения 48×48, 32×32 и 16×16). Когда иконка показывается в Проводнике (Windows Explorer), Windows рассматривает иконки из ресурса в алфавитном порядке, таким образом, если в ресурсе у Вас несколько иконок, удостоверьтесь, что нужная иконка для приложения в алфавитном порядке первая в списке; иначе на рабочем столе или в директории будет не та иконка, которую Вы ожидали увидеть.
На Mac, Вам нужно подготовить пакет (bundle) для приложения, в которой есть ICNS файлы. Больше информации о пакетах Вы найдете в разделе об установке в Главе 20, “Сделаем Ваше приложение Идеальным”; нужная секция файла в пакете Info.plist например, может выглядеть вот так:

<key>CFBundleDocumentTypes</key>
  <array>
         <dict>
               <key>CFBundleTypeExtensions</key>
               <array>
                        <string>pjd</string>
                 </array>
                 <key>CFBundleTypeIconFile</key>
                 <string>dialogblocks-doc.icns</string>
                 <key>CFBundleTypeName</key>
                 <string>pjdfile</string>
                 <key>CFBundleTypeRole</key>
                 <string>Editor</string>
           </dict>
    </array>
    <key>CFBundleIconFile</key>
    <string>dialogblocks-app.icns</string>
...

Иконки для вашего приложения и документов вашего приложения описываются в CFBundleIconFile и CFBundleTypeIconFile свойствах. ICNS файлы Вы можете создать с помощью редактора иконок, которые поставляет Apple. Если Вы преимущественно работаете в другой операционной системе, Вам нужно создать несколько иконок с разрешением 16×16, 32×32, 48×48, и 128×128, сохранить их в PNG формате, скопировать их на Mac, потом скопировать их и вставить в нужном месте в редактор иконок. Удостоверьтесь, что каждый PNG файл содержит маску, которую редактор будет использовать при создании иконки.

В Linux’e, у GNOME и KDE свои способы для назначения иконок приложениям, эти способы коротко будут описаны в Главе 20.

Программирование с wxCursor

Курсор используется для указания позиция указателя мыши. Вы можете изменить курсор для отдельного окна, если хотите акцентировать пользователя на конкретной функции мыши в данном окне. Так же как и иконки, курсор это небольшое изображение с поддержкой прозрачности. Создать его можно с помощью как общих, так и с помощью специфических для данной платформы конструкторов. Некоторые из этих конструкторов берут актуальную позицию указателя как самую левую верхнюю точку изображения курсора, и именно эта точка по-умолчанию является “острием” вашего курсора.

Таблица 10-4 функции класса wxCursor.

  • wxCursor – Курсор может быть создан из wxImage, битовых данных (char[]), используя стандартный идентификатор курсора, или из файла с указанием формата файла.
  • Ok – Возвращает true, если объект содержит данные курсора.

Создание wxCursor

Самый простой способ задать курсор – это передать стандартный идентификатор конструктору объекта, как показано в примере ниже.

// Создание курсора, используя стандартный идентификатор
wxCursor cursor(wxCURSOR_WAIT);

Таблица 10-5 список доступных идентификаторов и их внешний вид (на разных платформах могут быть незначительные отличия).

Table 10-5. Идентификаторы Стандартных Курсоров

  • wxCURSOR_ARROW – Стандартный курсор стрелка.
  • wxCURSOR_RIGHT_ARROW – Стандартный курсор, указывающий вправо.
  • wxCURSOR_BLANK – Прозрачный (пустой) курсор.
  • wxCURSOR_BULLSEYE – Курсор мишень.
  • wxCURSOR_CROSS – Курсор крест.
  • wxCURSOR_HAND – Курсор в форме руки.
  • wxCURSOR_IBEAM – I-образный курсор (вертикальная линия).
  • wxCURSOR_LEFT_BUTTON – Изображение мыши с нажатой левой кнопкой (только в GTK+).
  • wxCURSOR_MAGNIFIER – Курсор увеличения.
  • wxCURSOR_MIDDLE_BUTTON – Изображение мыши с нажатой средней кнопкой (только в GTK+).
  • wxCURSOR_NO_ENTRY – Курсор в форме знака “входа нет”.
  • wxCURSOR_PAINT_BRUSH – Курсор в форме кисти для рисования.
  • wxCURSOR_PENCIL – Курсор карандаш.
  • wxCURSOR_POINT_LEFT – Курсор указывающий налево.
  • wxCURSOR_POINT_RIGHT – Курсор указывающий направо.
  • wxCURSOR_QUESTION_ARROW – Стрелка и знак вопроса.
  • wxCURSOR_RIGHT_BUTTON – Изображение мыши с нажатой правой кнопкой (только в GTK+).
  • wxCURSOR_SIZENESW – Курсор изменения размера в направлении СВ-ЮЗ.
  • wxCURSOR_SIZENS – Курсор изменения размера в направлении С-Ю.
  • wxCURSOR_SIZENWSE – Курсор изменения размера в направлении СЗ-ЮВ.
  • wxCURSOR_SIZEWE – Курсор изменения размера в направлении З-В.
  • wxCURSOR_SIZING – Курсор изменения размера (часто перемещения)
  • wxCURSOR_SPRAYCAN – Курсор пульвелизатора.
  • wxCURSOR_WAIT – Курсор ожидания.
  • wxCURSOR_WATCH – Курсор в форме часов.
  • wxCURSOR_ARROWWAIT – Курсор со стрелкой и песочными часами.

Так же можно использовать предопределенные курсоры wxSTANDARD_CURSOR, wxHOURGLASS_CURSOR, и wxCROSS_CURSOR.
wxCursor можно загрузить из Windows ресурсов в Windows или из Mac OS X ресурса курсоров в Mac OS X:

// Курсор из Windows ресурса
wxCursor cursor(wxT("cursor_resource"), wxBITMAP_TYPE_CUR_RESOURCE,
                 hotSpotX, hotSpotY);


// Курсор из Mac OS ресурса курсоров
wxCursor cursor(wxT("cursor_resource"), wxBITMAP_TYPE_MACCUR_RESOURCE);

Вы можете создать свой курсор, используя wxImage. Актуальную позицию указателя можно задать функцией wxImage::SetOptionInt, так как “острие” курсора может не совпадать с левой верхней точкой изображения. Например, у курсора в виде прицела актуальная позиция находится ровно по центру изображения. Вот пример кода, который загружает PNG изображение и использует его в качестве курсора:

// Создаем курсор из wxImage
wxImage image(wxT("cursor.png"), wxBITMAP_TYPE_PNG);
image.SetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_X, 5);
image.SetOptionInt(wxIMAGE_OPTION_CUR_HOTSPOT_Y, 5);
wxCursor cursor(image);

Использование wxCursor

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

window->SetCursor(wxCursor(wxCURSOR_WAIT));

Использование wxSetCursorEvent

В Windows и Mac OS X есть подводные камни, которых Вы должны остерегаться, в частности, когда Вы рисуете нестандартное окно. Скажем, Вы рисуете окно с разделителем так, что на самом деле видима очень маленькая часть самого окна; например так рисуются окна с плавающим разделителем, так называемым “переплетом”. Далее Вы устанавливаете курсор для переплета (скажем, wxCURSOR_WE) таким образом, пользователь видит, что границу-разделитель можно тянуть. И если для окон-потомков не установлен собственный курсор, то будет применяться курсор, установленный нашему основному окну, в нашем случае курсор, предназначенный только переплету.
Для того, что бы указать, что нужно использовать заданный курсор только для разделителя, а в остальных случаях рисовать стандартный, Вы должны определить обработчик событий с помощью wxSetCursorEvent. Это событие вызывается в Windows и Mac OS X, когда должен изменятся курсор (обычно, когда указатель мыши двигается над окном). Ваш обработчик события должен вызывать wxSetCursorEvent::SetCursor, если Вы хотите изменять курсор в частности для данного окна:

BEGIN_EVENT_TABLE(wxSplitterWindow, wxWindow)
    EVT_SET_CURSOR(wxSplitterWindow::OnSetCursor)
END_EVENT_TABLE()

// Указываем, что курсор должен изменятся только для переплета
void wxSplitterWindow::OnSetCursor(wxSetCursorEvent&amp; event)
{
    // Если мы этого не сделаем, курсор изменения размера будет использоваться
    // и в окнах-потомках. Здесь мы указываем, что наш курсор
    // не должен использоваться для дочерних окон.

    if ( SashHitTest(event.GetX(), event.GetY(), 0) )
    {
        // Вызываем обработчик по-умолчанию
        event.Skip();
    }
    //else: Ничего не делать, в частности не вызывать Skip()
}

В этом примере, если курсор мыши двигается над переплетом, SashHitTest возвращает true и вызывается Skip, который прерывает обработку события. Это равнозначно тому, что событие не обрабатывалось вообще, и wxWidgets отображает курсор (wxCURSOR_WE) как он задан для окна. Если SashHitTest возвращает false, наш указатель двигается в пределах дочернего окна, значит мы не заменяем стандартный курсор. Если позволить завершится обработчику (не вызывая Skip), не задавая курсор окну, это укажет wxWidgets обрабатывать наше окно-разделитель, как не имеющее заданного курсора. В итоге дочернее окно не унаследует родительский курсор, даже если дочернее окно не имеет собственного курсора (например, если дочернее окно wxTextCtrl, реализация которого имеет свой курсор, но wxWidgets не знает этого).

Читать вторую часть главы

3 Comments

Leave a comment

0.0/5