Для каждой платформы класс QWidget поддерживает функцию winId(), которая возвращает идентификатор или описатель окна. QWidget также обеспечивает статическую функцию find(), которая возвращает QWidget с идентификатором конкретного окна. Мы можем передавать этот идентификатор функциям «родного» программного интерфейса для достижения эффектов, зависимых от платформы. Например, в следующем программном коде используется функция winId() для отображения слева заголовка панели инструментов, используя «родные» функции Mac OS X:
#ifdef Q_WS_MAC
ChangeWindowAttributes(HIViewGetWindow(HIViewRef(toolWin.winId())),
kWindowSideTitlebarAttribute, kWindowNoAttributes);
#endif
Рис. 20.1. Окно панели инструментов Mac OS X с отображением заголовка сбоку.
Ниже показано, как в системе X11 мы можем модифицировать свойство окна:
#ifdef Q_WS_X11
Atom atom = XInternAtom(QX11Info::display(), "MY_PROPERTY", False);
long data = 1;
XChangeProperty(QX11Info::display(), window->winId(), atom, atom,
32, PropModeReplace, reinterpret_cast<uchar *>(&data), 1);
#endif
Использование директив #ifdef и #endif вокруг зависимого от платформы программного кода гарантирует компиляцию приложения на других платформах.
Приведенный ниже пример показывает, как в приложениях, предназначенных только для Windows, можно использовать вызовы GDI для рисования на виджете Qt:
01 void GdiControclass="underline" :paintEvent(QPaintEvent * /* event */)
02 {
03 RECT rect;
04 GetClientRect(winId(), &rect);
05 HDC hdc = GetDC(winId());
06 FillRect(hdc, &rect, HBRUSH(COLOR_WINDOW + 1));
07 SetTextAlign(hdc, TA_CENTER | TA_BASELINE);
08 TextOutW(hdc, width() / 2, height() / 2,
09 text.utf16(), text.size());
10 ReleaseDC(winId(), hdc);
11 }
Чтобы это сработало, мы должны также переопределить функцию QPaintDevice::paintEngine() для возврата нулевого указателя и установить атрибут Qt::WA_PaintOnScreen в конструкторе виджета.
Следующий пример показывает, как можно сочетать QPainter и GDI в обработчике события рисования, используя функции getDC() и releaseDC() класса QPaintEngine:
01 void MyWidget::paintEvent(QPaintEvent * /* event */)
02 {
03 QPainter painter(this);
04 painter.fillRect(rect().adjusted(20, 20, -20, -20), Qt::red);
05 #ifdef Q_WS_WIN
06 HDC hdc = painter.paintEngine()->getDC();
07 Rectangle(hdc, 40, 40, width() - 40, height() - 40);
08 painter.paintEngine()->releaseDC();
09 #endif
10 }
Подобное совмещение вызовов QPainter и GDI иногда может дать странный результат, особенно когда вызовы QPainter выполняются после вызовов GDI, потому что QPainter делает некоторые предположения о состоянии базового уровня рисования.
Qt определяет один из следующих четырех символов оконной системы: Q_WS_WIN, Q_WS_X11, Q_WS_MAC и Q_WS_QWS (Qtopia). Мы должны обеспечить включение хотя бы одного заголовка Qt перед их использованием в приложениях. Qt также обеспечивает препроцессорные символы для идентификации операционной системы:
• Q_OS_AIX
• Q_OS_BSD4
• Q_OS_BSDI
• Q_OS_CYGWIN
• Q_OS_DGUX
• Q_OS_DYNIX
• Q_OS_FREEBSD
• Q_OS_HPUX
• Q_OS_HURD
• Q_OS_IRIX
• Q_OS_LINUX
• Q_OS_LYNX
• Q_OS_MAC
• Q_OS_NETBSD
• Q_OS_OPENBSD
• Q_OS_OS2EMX
• Q_OS_OSF
• Q_OS_QNX6
• Q_OS_QNX
• Q_OS_RELIANT
• Q_OS_SCO
• Q_OS_SOLARIS
• Q_OS_ULTRIX
• Q_OS_UNIXWARE
• Q_OS_WIN32
• Q_OS_WIN64
Мы можем считать, что по крайней мере один из этих символов будет определен. Для удобства Qt также определяет Q_OS_WIN, когда обнаруживается Win32 или Win64, и Q_OS_UNIX, когда обнаруживается любая операционная система типа Unix (включая Linux и Mac OS X). Во время выполнения приложений мы можем проверить QSysInfo::WindowsVersion или QSysInfo::MacintoshVersion для установки отличий между различными версиями Windows (2000, ME и так далее) или Mac OS X (10.2, 10.3 и так далее).
Кроме макросов операционной и оконной систем существует также ряд макросов компилятора. Например, Q_CC_MSVC определяется в том случае, если компилятором является Visual С++ компании Microsoft. Такие макросы полезны, когда приходится обходить ошибки компилятора.