Interfacing with Native APIs

Qt provides a comprehensive API that caters for most needs on all platforms. But in some circumstances, we may want to use the underlying, platform-specific APIs. In this section, we will show how to use the native APIs for the different platforms supported by Qt to accomplish particular tasks.

On every platform, QWidget provides a winId() function that returns the window ID (the HWND on Windows). QWidget also provides a static function called find() that returns the QWidget with a particular window ID. We can pass this ID to native API functions to achieve platform-specific effects. For example, the following code uses winId() to make a QLabel semi-transparent on Mac OS X using native Core Graphics functions:[*]

[*] Qt 3.3 will probably provide a function to achieve this without resorting to native API calls.

include 
#include 
#include 

int main(int argc, char *argv[])
{
 QApplication app(argc, argv);
 QLabel *label = new QLabel("Hello Qt!", 0);
 app.setMainWidget(label);

 CGSWindowRef winRef =
 GetNativeWindowFromWindowRef((WindowRef)label->winId());
 CGSSetWindowAlpha(_CGSDefaultConnection(), winRef, 0.5);

 label->show();
 return app.exec();
}

Here's how to achieve the same effect on Windows, using the Win32 API:

#define _WIN32_WINNT 0x0501

#include 
#include 

int main(int argc, char *argv[])
{
 QApplication app(argc, argv);
 QLabel *label = new QLabel("Hello Qt!", 0);
 app.setMainWidget(label);

 int exstyle = GetWindowLong(label->winId(), GWL_EXSTYLE);
 exstyle |= WS_EX_LAYERED;
 SetWindowLong(label->winId(), GWL_EXSTYLE, exstyle);
 SetLayeredWindowAttributes(label->winId(), 0, 128,
 LWA_ALPHA);

 label->show();
 return app.exec();
}

This code assumes that the platform is Windows 2000 or XP. If we wanted the application to compile and run on older versions of Windows that don't support semi-transparency, we could use QLibrary to resolve the SetLayeredWindowAttributes symbol at run-time instead of at link-time:

typedef BOOL (__stdcall *PSetLayeredWindowAttributes)
 (HWND, COLORREF, BYTE, DWORD);
PSetLayeredWindowAttributes pSetLayeredWindowAttributes =
 (PSetLayeredWindowAttributes) QLibrary::resolve("user32",
 "SetLayeredWindowAttributes");
if (pSetLayeredWindowAttributes) {
 int exstyle = GetWindowLong(label->winId(), GWL_EXSTYLE);
 exstyle |= WS_EX_LAYERED;
 SetWindowLong(label->winId(), GWL_EXSTYLE, exstyle);
 pSetLayeredWindowAttributes(label->winId(), 0, 128,
 LWA_ALPHA);
}

Qt/Windows uses this technique internally to ensure that Qt applications take advantage of advanced features such as native Unicode support and font transformations where they are available, while still being able to run on old Windows versions.

On X11, there is no standard way to achieve transparency. However, here's how we would modify an X11 window property:

Atom atom = XInternAtom(win->x11Display(), "MY_PROPERTY", False);
long data = 1;
XChangeProperty(win->x11Display(), win->winId(), atom, atom,
 32, PropModeReplace, (unsigned char *)&data, 1);

Qt/Embedded differs from the other Qt versions in that it is implemented directly on top of the Linux frame buffer, with no native API in between. It also provides its own window system, QWS, which can be configured by subclassing Qt/Embedded-specific classes like QWSDecoration and QWSInputMethod. Another difference of Qt/Embedded is that its size can be reduced by compiling out unused classes and features. For more information about Qt/Embedded, see http://www.trolltech.com/products/embedded/ and http://doc.trolltech.com/ 3.2/winsystem.html.

If we want to use platform-specific code in an otherwise portable Qt application, we can surround the native code with #if and #endif. For example:

#if defined(Q_WS_MAC)
 CGSWindowRef winRef =
 GetNativeWindowFromWindowRef((WindowRef)label->winId());
 CGSSetWindowAlpha(_CGSDefaultConnection(), winRef, 0.5);
#endif

Qt defines one of the following four window system symbols: Q_WS_WIN, Q_WS_X11, Q_WS_MAC, and Q_WS_QWS. We must make sure to include at least one Qt header before we use them in applications. Qt also provides preprocessor symbols to identify the operating system:

  • Q_OS_WIN32
  • Q_OS_WIN64
  • Q_OS_CYGWIN
  • Q_OS_MAC
  • Q_OS_AIX
  • Q_OS_BSDI
  • 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_NETBSD
  • Q_OS_OPENBSD
  • Q_OS_OSF
  • Q_OS_QNX
  • Q_OS_QNX6
  • Q_OS_RELIANT
  • Q_OS_SCO
  • Q_OS_SOLARIS
  • Q_OS_ULTRIX
  • Q_OS_UNIXWARE

We can assume that at most one of these will be defined. For convenience, Qt defines Q_OS_WIN when either Win32 or Win64 is detected, and Q_OS_UNIX when any Unix-based operating system (including Mac OS X) is detected. At runtime, we can call QApplication::winVersion() or QApplication::macVersion() to distinguish between different versions of Windows (95, 98, etc.) or Mac OS X (10.0, 10.1, etc.).

Several of Qt's GUI-related classes provide a platform-specific handle() function that returns a low-level handle to the object. Figure 18.1 lists the return type of handle() on different platforms.

Figure 18.1. Platform-specific handle types

graphics/18fig01.gif

The QWidget, QPixmap, QPrinter, and QPicture classes all inherit from QPaintDevice. On X11 and Mac OS X, handle() means the same thing as winId() on a QWidget. On Windows, handle() returns the device context, whereas winId() returns the window handle. Similarly, QPixmap provides a hbm() function that returns a bitmap handle (HBITMAP) on Windows.

On X11, QPaintDevice provides many functions that return various pointers or handles, including x11Display() and x11Screen(). We can use these to set up an X11 graphics context on a QWidget or QPixmap, for example.

Qt applications that need to interface with other toolkits or libraries frequently need to access the low-level events (XEvents on X11, MSGs on Windows and Mac OS X, QWSEvents on Qt/Embedded) before they are converted into QEvents. We can do this by subclassing QApplication and reimplementing the relevant platform-specific event filter, one of winEventFilter(), x11EventFilter(), macEventFilter(), and qwsEventFilter().

We can access the platform-specific events that are sent to a given QWidget by reimplementing one of winEvent(), x11Event(), macEvent(), and qwsEvent(). This can be useful for handling certain types of events that Qt normally ignores, such as joystick events.

For more information about platform-specific issues, including how to get started with Qt/Embedded and how to deploy Qt applications on different platforms, see http://doc.trolltech.com/3.2/winsystem.html.

Part I: Basic Qt

Getting Started

Creating Dialogs

Creating Main Windows

Implementing Application Functionality

Creating Custom Widgets

Part II: Intermediate Qt

Layout Management

Event Processing

2D and 3D Graphics

Drag and Drop

Input/Output

Container Classes

Databases

Networking

XML

Internationalization

Providing Online Help

Multithreading

Platform-Specific Features



C++ GUI Programming with Qt 3
C++ GUI Programming with Qt 3
ISBN: 0131240722
EAN: 2147483647
Year: 2006
Pages: 140

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net