|
Programming with wxCursorA cursor is used to give feedback on the mouse pointer position. You can change the cursor for a given windowusing different cursors gives a cue to the user to expect specific mouse behavior. Like icons, cursors are small, transparent images that can be created using platform-specific as well as generic constructors. Some of these constructors take a hotspot position relative to the top-left corner of the cursor image, with which you specify the location of the actual pointer "tip." Table 10-4 shows the cursor functions.
Creating a wxCursorThe easiest way to create a cursor is to pass a stock cursor identifier to the cursor constructor, as the following example shows. // Create a cursor from a stock identifier wxCursor cursor(wxCURSOR_WAIT); Table 10-5 lists the available identifiers and their appearances (subject to some variation between platforms).
You can also use the predefined cursor pointers wxSTANDARD_CURSOR, wxHOURGLASS_CURSOR, and wxCROSS_CURSOR. wxCursor can load a Windows cursor resource on Windows or a Mac OS X cursor resource on Mac OS X: // Cursor from a Windows resource wxCursor cursor(wxT("cursor_resource"), wxBITMAP_TYPE_CUR_RESOURCE, hotSpotX, hotSpotY); // Cursor from a Mac OS cursor resource wxCursor cursor(wxT("cursor_resource"), wxBITMAP_TYPE_MACCUR_RESOURCE); You can create a custom cursor by specifying a wxImage object. The "hotspot" position needs to be specified using wxImage::SetOptionInt because the actual mouse pointer position may not correspond to the top-left corner of the cursor image. For example, a cross-hair cursor would have the hotspot in the center of the image. Here's some code that loads a PNG image and makes a cursor out of it: // Create a cursor from a 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); Using wxCursorEach window can have an associated cursor, which will be shown when the mouse pointer moves into the window. If there is no associated cursor, the cursor for an ancestor window will be shown, and if there is no ancestor with a cursor set, the standard cursor will be shown. Set the cursor for a window like this: window->SetCursor(wxCursor(wxCURSOR_WAIT)); Using wxSetCursorEventOn Windows and Mac OS X, there is a little wrinkle that you may need to be aware of, particularly if you implement your own container windows. Say you implement your own splitter window that arranges its children such that only a small part of the splitter window is visible; this is used as the draggable divider or "sash." You then set an appropriate cursor for the splitter (say, wxCURSOR_WE) so the sash indicates that it can be dragged. If the children of the splitter window don't have cursors specified, they may inappropriately show the parent's cursor that is intended only for the sash. To indicate that the cursor should only be used when the mouse pointer is over the sash and that no cursor should be set otherwise, you need to define an event handler for wxSetCursorEvent. This event is generated on Windows and Mac OS X when the cursor should be set (normally as the mouse pointer moves over the window). Your event handler should call wxSetCursorEvent::SetCursor if you want to indicate a particular cursor for this window, as follows: BEGIN_EVENT_TABLE(wxSplitterWindow, wxWindow) EVT_SET_CURSOR(wxSplitterWindow::OnSetCursor) END_EVENT_TABLE() // Indicate that the cursor should only be set for the sash void wxSplitterWindow::OnSetCursor(wxSetCursorEvent& event) { // If we don't do this, the resizing cursor might be set for // child windows. Here, we explicitly say that our cursor // should not be used for child windows that overlap us. if ( SashHitTest(event.GetX(), event.GetY(), 0) ) { // Use default processing event.Skip(); } //else: Do nothing, in particular, don't call Skip() } In this example, if the mouse pointer is over the sash, SashHitTest returns true, and Skip is called, which makes the event handler "fail." This is equivalent to defining no cursor event handler at all, and it causes wxWidgets to display the window's cursor (wxCURSOR_WE) as normal. If SashHitTest returns false, however, it means the cursor is over a child window, and the cursor for the splitter window should not be used. Allowing the handler to "succeed" (by not calling Skip) without setting a cursor indicates to wxWidgets that we should treat the splitter window as having no cursor. As a result, the child window will correctly not inherit the parent's cursor, even if it has no known cursor of its own. (If the child window is a wxTextCtrl, for example, the native implementation will provide its own cursor, but wxWidgets has no knowledge of it.) |
|