Allow to not create wxPaintDC in EVT_PAINT handler in wxMSW.

Failure to create a wxPaintDC in EVT_PAINT handler resulted in many serious
and difficult to debug problems under wxMSW. We used to document that the user
shouldn't do it but this wasn't enough (see #11648). We could also assert if
we detected that a handler didn't create a wxPaintDC but it seems better to
just handle this case gracefully for consistency with the other platforms.

Add wxDidCreatePaintDC global variable which is reset before generating
wxPaintEvent and set to true when ::BeginPaint() is called from wxPaintDC
ctor and validate the update region of the window ourselves if it wasn't set
(meaning that wxPaintDC wasn't created).

Update the documentation to emphasize the link between EVT_PAINT handlers and
wxPaintDC but without saying that wxPaintDC object must always be created in
the handler as this is not true any more.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63229 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2010-01-23 13:22:25 +00:00
parent 975fb32b5c
commit 7ca106e860
4 changed files with 37 additions and 10 deletions

View File

@@ -4796,6 +4796,14 @@ wxColour wxWindowMSW::MSWGetThemeColour(const wchar_t *themeName,
// painting
// ---------------------------------------------------------------------------
// this variable is used to check that a paint event handler which processed
// the event did create a wxPaintDC inside its code and called BeginPaint() to
// validate the invalidated window area as otherwise we'd keep getting an
// endless stream of WM_PAINT messages for this window resulting in a lot of
// difficult to debug problems (e.g. impossibility to repaint other windows,
// lack of timer and idle events and so on)
extern bool wxDidCreatePaintDC = false;
bool wxWindowMSW::HandlePaint()
{
HRGN hRegion = ::CreateRectRgn(0, 0, 0, 0); // Dummy call to get a handle
@@ -4810,11 +4818,20 @@ bool wxWindowMSW::HandlePaint()
m_updateRegion = wxRegion((WXHRGN) hRegion);
wxDidCreatePaintDC = false;
wxPaintEvent event(m_windowId);
event.SetEventObject(this);
bool processed = HandleWindowEvent(event);
if ( processed && !wxDidCreatePaintDC )
{
// do call MSWDefWindowProc() to validate the update region to avoid
// the problems mentioned above
processed = false;
}
// note that we must generate NC event after the normal one as otherwise
// BeginPaint() will happily overwrite our decorations with the background
// colour