Updating to the Latest Version of wxWidgets

From WxWiki
Jump to navigation Jump to search

Every new version of wxWidgets inevitably introduces changes that will affect pre-existing code. The idea of this page is to document the commoner reasons for failure to build, and their solutions; and what substitutes to use for newly deprecated methods.

For more details, and less common changes, see the full wx changelog.


wx3.0

Major changes are documented in Changes since wxWidgets 2.8 For a lot more detail, see docs/changes.txt

Unicode

The biggest change is the use internally of unicode strings, usually UTF-8. There is now little or no reason to try to create an ansi build. One consequence of this is that it's no longer necessary to use the wxT() or _T() macros (though they can still be kept for backward-compatibility). However _() is still needed for translations.

See Potential Unicode Pitfalls for some of the issues that may result. Two common ones are:

  • It's no longer possible to do:
wxString foo; if (foo) { ... }

Instead do:

if (!foo.empty()) { ... }
  • Though it normally doesn't matter if you use wxT() around a string literal, this isn't true for wxCmdLineEntryDesc. There are two ways to overcome this:
    • For code that will compile in versions later than wx2.8.12 and wx2.9.2, use the wxT_2 macro.
    • If you want code that is backward-compatible with earlier wx2.8 versions, you'll have to duplicate the strings inside version guards.

wxGridSizer and wxFlexGridSizer

In wx2.8 and earlier, if you create a 2x2 gridsizer and then add 5 items to it, wx would roll its eyes but quietly make a 5-item grid. In wx3.0 the same code will still work, but will also assert. The best solution is to ask for a 0x2 gridsizer instead. This specifies that the sizer will always have 2 columns, and the number of rows will be calculated automatically. (Alternatively a 2x0 gridsizer will specify always 2 rows.)


Release versus Debug

Debug information is now built in to 'release' wx builds as well as 'debug' ones (in fact, except on MSWin, all builds are 'debug' ones). This also results in wx asserts happening in all builds, unless you go out of your way to stop them. See this wxBlog entry


wxUSE_STL

For a short time wx 2.9 built with wxUSE_STL==1 by default. This is not the case for any of the official releases and is not the case for 3.0.

However if you want to be able to build your code in wxUSE_STL==1 mode, you need to know that wxList::Node no longer exists. So:

wxWindowListNode* node = GetChildren().GetFirst();

must be replaced with wxList<T>::compatibility_iterator (which works in 2.8 too):

wxWindowList::compatibility_iterator node = GetChildren().GetFirst();

The wx-config script

wx-config --libs now only gives the standard libs. For e.g. aui you need to do: wx-config --libs std,aui. Alternatively, wx-config --libs all returns all available libraries.

The naming of libraries has changed (see above): on Unix platforms there are no longer 'debug' libraries, so the 'd' suffix is no longer used (so libwx_baseud-2.8 becomes libwx_baseu-3.0). wx-config has been changed to cope with this, which is another good reason always to use it!


Miscellaneous

  • WindowIDs

Trying to use an ID >32K will now assert (as it would fail on Windows XP).

  • Sending Events

wxWindow::ProcessEvent and wxWindow::AddPendingEvent are now protected, so code that does things like:

pMyWindow->ProcessEvent(event)

will fail to compile, and needs to be changed to either:

pMyWindow->ProcessWindowEvent(event);

or

pMyWindow->GetEventHandler()->ProcessEvent(event);

(Doing this was always a good idea anyway, in case the window's default event handler wasn't the correct one to use.)

And code that does:

pMyWindow->AddPendingEvent(event)

should be changed to:

wxPostEvent(pMyWindow, event);
  • Vararg checking

The arguments of variadic functions are now checked for correctness. So e.g. the following code will now assert:

size_t n=1;
wxString foo = wxString::Format("Pretend it's an int: %i", n);

In this case you'd need to cast to int, or change the parameter to %zu (which is unfortunately still not universally supported).

  • wxXmlProperty

This is deprecated in favour of wxXmlAttribute, and code using it will only compile in a WXWIN_COMPATIBILITY_2_8 build. Usage is identical, just the name has changed. Similarly wxXmlNode::GetPropVal and wxXmlNode::GetAttribute.

  • wxDC::BeginDrawing and wxDC::EndDrawing

These were deprecated halfway through the wx2.8 series. They did nothing anway, so just remove them from your code.

  • Deprecated macros:

These are still available, but there are now alternatives that new code should use.

Old version New version (note the semicolons)
DECLARE_DYNAMIC_CLASS and similar wxDECLARE_DYNAMIC_CLASS; and similar
IMPLEMENT_DYNAMIC_CLASS and similar wxIMPLEMENT_DYNAMIC_CLASS; and similar
DECLARE_EVENT_TYPE(MyNewEventtype, wxID_ANY ) wxDECLARE_EVENT(MyNewEventtype, wxCommandEvent); or similar
DEFINE_EVENT_TYPE(MyNewEventtype) wxDEFINE_EVENT(MyNewEventtype, wxCommandEvent); or similar
DECLARE_EVENT_TABLE() wxDECLARE_EVENT_TABLE();
BEGIN_EVENT_TABLE(myFoo, wxFoo) wxBEGIN_EVENT_TABLE(myFoo, wxFoo)
END_EVENT_TABLE() wxEND_EVENT_TABLE()
IMPLEMENT_APP() wxIMPLEMENT_APP();
DECLARE_APP() wxDECLARE_APP();
  • wxArrayString

The operator[] does not return references anymore.

  • wxLogStatus

If you called "::wxLogStatus", now it's a macro that starts with if(..). Therefore you should remove :: to get your code building.

wx2.8

wxFileDialog flags

These have changed from wxOPEN, wxSAVE etc to wxFD_OPEN, wxFD_SAVE etc. Code using the old flags will only compile in a WXWIN_COMPATIBILITY_2_6 build.

Keycodes

WXK_PRIOR and WXK_NEXT (and their _NUMPAD_ equivalents) are now called WXK_PAGEUP and WXK_PAGEDOWN. Using the old keycodes will only compile in a WXWIN_COMPATIBILITY_2_6 build.

wxDialog::OnOk()

This function has now been removed for a couple reasons: 1) It was never needed in the first place, and 2) It's existence only encouraged wrong use and flow of wxDialog. Changes.txt suggests using SetAffirmativeId() instead. To elaborate a little more on this change since many are still confused: You never needed to call OnOK() from your own code even if you used a different ID other than the standard wxID_OK (to indicate a positive closing result, or otherwise), and should have been using wxDialog::SetAffirmativeId() for those cases anyway.

There are two methods that many developers have been known to abuse wxDialog::OnOK(). The first is by calling OnOK() from other event handlers or functions as the method of closing the dialog:

DoSomeStuff();
Dialog::OnOK( event );

Instead, you should be designing your dialogs to use the standard wxID_OK and wxID_CANCEL window IDs for wxButtons with labels that indicate the appropriate action. The above code promotes closing the dialog upon completion of some action separate of clicking an "OK" button, and this isn't the type of behavior users expect of dialogs, it should only close when they push the "OK" or "Cancel" buttons or the close button on the frame (which closes the dialog with wxID_CANCEL).

The second method of abuse is overriding OnOK in your derived wxDialog to perform additional actions before the dialog closes (any actions after it closes can be handled by the code that created the dialog in the first place). If you honestly have code that must be called before the dialog closes (ie: you do your own value validation instead of using wxValidators, or likewise), then you should implement a new button event handler tied to your wxID_OK button (you should have one of these buttons or you're guilty of both forms of abuse of wxDialog::OnOK()) which should look something like this:

void MyDialog::OnButtonOk( wxCommandEvent &event ) {
    if( DoSomeSpecializedStuff() ) {
        event.Skip();
    }
}

The "event.Skip()" call tells wxWidgets to continue processing the default behavior for wxID_OK (or another button ID if you like so long as you've called SetAffirmativeId() in your wxDialog constructor), which will call all wxValidators, handle any data transfer with those validators, and close the dialog.

See this wxForum discussion and this wx-dev mailing list post for additional information.

GetCount() changes

GetCount() defined in many classes have changed from returning an int to a size_t (usually defined as an unsigned int on most platforms) as well as many other item index related functions. All virtual function implementations or function overrides will need to be updated to use size_t as well. Shouldn't cause any problems and is more of a semantic change.

wxSystemSettings::GetSystemColour()

This function has gone. Use GetColour() instead.

wxApp::GetTopWindow()

Previously code like:

wxTheApp->GetTopWindow()->SetTitle( MyString );

Would work whatever the top window. With 2.8.0 you should now dynamically cast the top window to a wxTopLevelWindow first. Perhaps GetTopWindow() should return a wxTopLevelWindow *, assuming that is the only thing it is allowed to return? On the other hand perhaps not, as not doing so encourages the writer of application code to check for a NULL value after doing the dynamic cast themselves.

wx2.6

See this document

  • wxPathExists() is deprecated, use wxDirExists() instead.
  • wxEvent doesn't have public members any more. You must use accessor methods instead.
  • There is now some type-checking for the event system. This means that, if you catch e.g. a wxCommandEvent in an event table, you can't pass it to a function with a different parameter e.g wxMouseEvent&.
  • Use wxTreeItemId instead of relying on its implicit conversion to long.