int GetMarginX() const { return m_marginX; }
int GetMarginY() const { return m_marginY; }
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- { SetBackgroundColour(bg); }
-
-
protected:
// function called when any of the bitmaps changes
virtual void OnSetBitmap() { InvalidateBestSize(); Refresh(); }
}
}
- // override some base class virtuals
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- { SetBackgroundColour(bg); }
- virtual bool ProvidesBackground() const { return true; }
-
protected:
// remove the page and return a pointer to it
virtual wxWindow *DoRemovePage(size_t page) = 0;
#ifdef __WXUNIVERSAL__
virtual bool IsCanvasWindow() const { return true; }
- virtual bool ProvidesBackground() const { return true; }
#endif
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- { SetBackgroundColour(bg); }
-
WX_DECLARE_CONTROL_CONTAINER();
virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
virtual bool MSWCommand(WXUINT param, WXWORD id);
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- {
- // avoide switching into owner-drawn mode
- wxControl::SetBackgroundColour(bg);
- }
-
-#ifdef __WIN32__
// coloured buttons support
virtual bool SetBackgroundColour(const wxColour &colour);
virtual bool SetForegroundColour(const wxColour &colour);
private:
void MakeOwnerDrawn();
-#endif // __WIN32__
protected:
// send a notification event, return true if processed
protected:
virtual wxSize DoGetBestSize() const;
- virtual WXHBRUSH MSWGetDefaultBgBrush();
virtual void DoSet3StateValue(wxCheckBoxState value);
virtual wxCheckBoxState DoGet3StateValue() const;
const wxArrayLong& GetSubcontrols() const { return m_subControls; }
+ // default handling of WM_CTLCOLORxxx: this is public so that wxWindow
+ // could call it
+ virtual WXHBRUSH MSWControlColor(WXHDC pDC);
+
protected:
// choose the default border for this window
virtual wxBorder GetDefaultBorder() const;
// default style for the control include WS_TABSTOP if it AcceptsFocus()
virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
- // default handling of WM_CTLCOLORxxx
- virtual WXHBRUSH MSWControlColor(WXHDC pDC);
-
// call this from the derived class MSWControlColor() if you want to show
// the control greyed out (and opaque)
WXHBRUSH MSWControlColorDisabled(WXHDC pDC);
- // call this from the derived class MSWControlColor() if you want to always
- // paint the background (as all opaque controls do)
- WXHBRUSH MSWControlColorSolid(WXHDC pDC)
- {
- return DoMSWControlColor(pDC, GetBackgroundColour());
- }
-
// common part of the 3 functions above: pass wxNullColour to use the
// appropriate background colour (meaning ours or our parents) or a fixed
// one
virtual WXHBRUSH DoMSWControlColor(WXHDC pDC, wxColour colBg);
- // another WM_CTLCOLOR-related function: override this to return the brush
- // which should be used to paint the control background by default
- //
- // for most controls, the default behaviour of returning 0 and letting the
- // system do it is correct, but for some -- e.g. checkboxes -- we actually
- // have to return transparent brush from here to prevent the system from
- // overwriting background with solid colour
- virtual WXHBRUSH MSWGetDefaultBgBrush() { return 0; }
-
// this is a helper for the derived class GetClassDefaultAttributes()
// implementation: it returns the right colours for the classes which
// contain something else (e.g. wxListBox, wxTextCtrl, ...) instead of
protected:
WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
- virtual WXHBRUSH MSWControlColor(WXHDC pDC)
- {
- return MSWControlColorSolid(pDC);
- }
-
// free memory (common part of Clear() and dtor)
void Free();
return true;
}
-
- virtual WXHBRUSH MSWGetBgBrushForChild(WXHDC hDC, wxWindow *win);
- virtual wxColour MSWGetBgColourForChild(wxWindow *win);
#endif // wxUSE_UXTHEME
protected:
// remove one page from the notebook, without deleting
virtual wxNotebookPage *DoRemovePage(size_t nPage);
+ // get the page rectangle for the current notebook size
+ //
+ // returns empty rectangle if an error occurs, do test for it
+ wxRect GetPageSize() const;
+
// set the size of the given page to fit in the notebook
void AdjustPageSize(wxNotebookPage *page);
// creates the brush to be used for drawing the tab control background
void UpdateBgBrush();
- // paint themed children background here
- virtual bool MSWPrintChild(wxWindow *win, WXWPARAM wParam, WXLPARAM lParam);
+ // return the themed brush for painting our children
+ virtual WXHBRUSH MSWGetBgBrushForChild(WXHDC hDC, wxWindow *win);
+
+ // draw child background
+ virtual bool MSWPrintChild(WXHDC hDC, wxWindow *win);
+
+ // common part of QueryBgBitmap() and MSWPrintChild()
+ //
+ // if child == NULL, draw background for the entire notebook itself
+ bool DoDrawBackground(WXHDC hDC, wxWindow *child = NULL);
#endif // wxUSE_UXTHEME
// the current selection (-1 if none)
// Lines are drawn differently for WinCE and regular WIN32
WXDLLEXPORT void wxDrawLine(HDC hdc, int x1, int y1, int x2, int y2);
+// fill the client rect of the given window on the provided dc using this brush
+inline void wxFillRect(HWND hwnd, HDC hdc, HBRUSH hbr)
+{
+ RECT rc;
+ ::GetClientRect(hwnd, &rc);
+ ::FillRect(hdc, &rc, hbr);
+}
+
// ----------------------------------------------------------------------------
// 32/64 bit helpers
// ----------------------------------------------------------------------------
int sizeFlags = wxSIZE_AUTO);
virtual wxSize DoGetBestSize() const;
+#ifndef __WXWINCE__
virtual WXHRGN MSWGetRegionWithoutChildren();
- virtual WXLRESULT MSWWindowProc(WXUINT nMsg,
- WXWPARAM wParam,
- WXLPARAM lParam);
+#endif // __WXWINCE__
// the buttons we contain
// implementation only from now on
virtual bool MSWCommand(WXUINT param, WXWORD id);
virtual void Command(wxCommandEvent& event);
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- { SetBackgroundColour(bg); }
-
+ virtual bool HasTransparentBackground() { return true; }
protected:
virtual wxSize DoGetBestSize() const;
virtual wxBorder GetDefaultBorder() const;
virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
+
+#ifndef __WXWINCE__
virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
// return the region with all the windows inside this static box excluded
// region which is embedded in a rectangle (0, 0)-(w, h)
virtual void MSWGetRegionWithoutSelf(WXHRGN hrgn, int w, int h);
- // paint the given rectangle with our background colour
+ // paint the given rectangle with our background brush/colour
void PaintBackground(wxDC& dc, const struct tagRECT& rc);
void OnPaint(wxPaintEvent& event);
DECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticBox)
+#endif // !__WXWINCE__
};
#endif // _WX_MSW_STATBOX_H_
int sizeFlags = wxSIZE_AUTO);
virtual wxSize DoGetBestSize() const;
virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle = NULL) const;
- virtual WXHBRUSH DoMSWControlColor(WXHDC pDC, wxColour colBg);
+
DECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticText)
};
// called when the window is about to be destroyed
virtual void MSWDestroyWindow();
- // this function should return the brush to paint the window background
- // with or 0 for the default brush
- virtual WXHBRUSH MSWControlColor(WXHDC hDC);
// this function should return the brush to paint the children controls
// background or 0 if this window doesn't impose any particular background
// on its children
//
- // the base class version uses MSWGetBgColourForChild() and returns a solid
- // brush if we have a non default background colour or 0 otherwise
- virtual WXHBRUSH MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), wxWindow *child)
- {
- return MSWGetSolidBgBrushForChild(child);
- }
+ // the base class version returns a solid brush if we have a non default
+ // background colour or 0 otherwise
+ virtual WXHBRUSH MSWGetBgBrushForChild(WXHDC hDC, wxWindow *child);
- // return the background colour of this window under the given child
- // (possible grand child)
- //
- // this is a hack as if the background is themed, there is no single colour
- // representing it, but sometimes we can't use the pattern brush returned
- // by MSWGetBgBrushForChild() anyhow and then this function is used as
- // fallback
+ // return the background brush to use for painting the given window by
+ // quering the parent windows via their MSWGetBgBrushForChild() recursively
//
- // the base class version returns bg colour if it had been explicitely set
- // or wxNullColour otherwise
- virtual wxColour MSWGetBgColourForChild(wxWindow *child);
-
- // convenience function: returns a solid brush of the colour returned by
- // MSWGetBgColourForChild() or 0
- WXHBRUSH MSWGetSolidBgBrushForChild(wxWindow *child);
-
- // normally just calls MSWGetBgBrushForChild() on the parent window but may
- // be overridden if the default background brush is not suitable for some
- // reason (e.g. wxStaticBox uses MSWGetSolidBgBrushForChild() instead)
- virtual WXHBRUSH MSWGetBgBrushForSelf(wxWindow *parent, WXHDC hDC);
-
- // return the background brush to use for this window by quering the parent
- // windows via their MSWGetBgBrushForChild() recursively
- WXHBRUSH MSWGetBgBrush(WXHDC hDC);
-
- // overriding this method gives the parent window the opportunity to
- // process WM_PRINTCLIENT for its children: this is currently used by
- // wxNotebook to draw themed background for them
+ // winToPaint is normally NULL meaning this window itself, but it can also
+ // be a child of this window which is used by the static box and could be
+ // potentially useful for other transparent controls
+ WXHBRUSH MSWGetBgBrush(WXHDC hDC, wxWindow *winToPaint = NULL);
+
+ // gives the parent the possibility to draw its children background, e.g.
+ // this is used by wxNotebook to do it using DrawThemeBackground()
//
- // return true if the message was processed or false to use default logic
- // for it (currently this means handling it just as WM_PAINT i.e. render
- // the control into the provided DC)
- virtual bool MSWPrintChild(wxWindow *win, WXWPARAM wParam, WXLPARAM lParam);
+ // return true if background was drawn, false otherwise
+ virtual bool MSWPrintChild(WXHDC WXUNUSED(hDC), wxWindow * WXUNUSED(child))
+ {
+ return false;
+ }
// Responds to colour changes: passes event on to children.
// virtual function for implementing internal idle
// behaviour
- virtual void OnInternalIdle() ;
+ virtual void OnInternalIdle();
protected:
// the window handle
// default OnEraseBackground() implementation, return true if we did erase
- // the background, false otherwise
- bool DoEraseBackground(wxDC& dc);
+ // the background, false otherwise (i.e. the system should erase it)
+ bool DoEraseBackground(WXHDC hDC);
private:
// common part of all ctors
// send a notification event, return true if processed
bool SendClickEvent();
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- {
- // avoide switching into owner-drawn mode
- wxControl::SetBackgroundColour(bg);
- }
-
protected:
// default button handling
int GetNumVer() const;
int GetNumHor() const;
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- { SetBackgroundColour(bg); }
-
protected:
// we can't compute our best size before the items are added to the control
virtual void SetInitialBestSize(const wxSize& WXUNUSED(size)) { }
// send a notification event, return true if processed
bool SendClickEvent();
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- { SetBackgroundColour(bg); }
-
-
protected:
virtual wxSize DoGetBestSize() const;
virtual int GetSelStart() const { return GetMax(); }
virtual void SetSelection(int WXUNUSED(min), int WXUNUSED(max)) { }
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- { SetBackgroundColour(bg); }
-
protected:
// adjust value according to wxSL_INVERSE style
// overriden base class virtuals
virtual bool AcceptsFocus() const { return false; }
- virtual void ApplyParentThemeBackground(const wxColour& bg)
- { SetBackgroundColour(bg); }
protected:
// set the right size for the right dimension
virtual bool Destroy();
virtual bool IsTopLevel() const { return true; }
virtual wxSize GetMaxSize() const;
- virtual bool ProvidesBackground() const { return true; }
// event handlers
void OnCloseWindow(wxCloseEvent& event);
void SetSelectionBackground(const wxColour& col);
- virtual void ApplyParentThemeBackground(const wxColour& WXUNUSED(bg))
- { /* do nothing */ }
-
-
virtual wxVisualAttributes GetDefaultAttributes() const
{
return GetClassDefaultAttributes(GetWindowVariant());
virtual void SetThemeEnabled(bool enableTheme) { m_themeEnabled = enableTheme; }
virtual bool GetThemeEnabled() const { return m_themeEnabled; }
- // Returns true if this class should have the background colour
- // changed to match the parent window's theme. For example when a
- // page is added to a notebook it and its children may need to have
- // the colours adjusted depending on the current theme settings, but
- // not all windows/controls can do this without looking wrong.
- virtual void ApplyParentThemeBackground(const wxColour& WXUNUSED(bg))
- { /* do nothing */ }
-
// focus and keyboard handling
// ---------------------------
return m_hasBgCol;
}
- // if the window shouldn't inherit its colour from the parent, override
- // this function to return true
- //
- // this is currently only used by wxMSW and wxUniv but should be useful for
- // the other ports too
- virtual bool ProvidesBackground() const { return false; }
-
virtual bool SetForegroundColour(const wxColour& colour);
void SetOwnForegroundColour(const wxColour& colour)
{
bool oneShot;
volatile bool timerDeleted;
wxTimerTick_t now = GetMillisecondsTime();
- wxTimerDesc *desc;
- while ( m_timers && m_timers->shotTime <= now )
+ for ( wxTimerDesc *desc = m_timers; desc; desc = desc->next )
{
- desc = m_timers;
- oneShot = desc->timer->IsOneShot();
- RemoveTimer(desc);
-
- timerDeleted = false;
- desc->deleteFlag = &timerDeleted;
- desc->timer->Notify();
-
- if ( !timerDeleted )
+ if ( desc->running && desc->shotTime <= now )
{
- wxLogTrace( wxT("timer"),
- wxT("notified timer %p sheduled for %")
- wxTimerTickFmtSpec,
- desc->timer,
- wxTimerTickPrintfArg(desc->shotTime) );
-
- desc->deleteFlag = NULL;
- if ( !oneShot )
- QueueTimer(desc, now + desc->timer->GetInterval());
+ desc = m_timers;
+ oneShot = desc->timer->IsOneShot();
+ RemoveTimer(desc);
+
+ timerDeleted = false;
+ desc->deleteFlag = &timerDeleted;
+ desc->timer->Notify();
+
+ if ( !timerDeleted )
+ {
+ wxLogTrace( wxT("timer"),
+ wxT("notified timer %p sheduled for %")
+ wxTimerTickFmtSpec,
+ desc->timer,
+ wxTimerTickPrintfArg(desc->shotTime) );
+
+ desc->deleteFlag = NULL;
+ if ( !oneShot )
+ QueueTimer(desc, now + desc->timer->GetInterval());
+ }
}
}
}
return wxSize(wCheckbox, hCheckbox);
}
-WXHBRUSH wxCheckBox::MSWGetDefaultBgBrush()
-{
- return ::GetStockObject(NULL_BRUSH);
-}
-
void wxCheckBox::SetValue(bool val)
{
- if (val)
- {
- Set3StateValue(wxCHK_CHECKED);
- }
- else
- {
- Set3StateValue(wxCHK_UNCHECKED);
- }
+ Set3StateValue(val ? wxCHK_CHECKED : wxCHK_UNCHECKED);
}
bool wxCheckBox::GetValue() const
{
- return (Get3StateValue() != wxCHK_UNCHECKED);
+ return Get3StateValue() != wxCHK_UNCHECKED;
}
void wxCheckBox::Command(wxCommandEvent& event)
wxCheckBoxState wxCheckBox::DoGet3StateValue() const
{
-#ifdef __WIN32__
return (wxCheckBoxState) ::SendMessage(GetHwnd(), BM_GETCHECK, 0, 0);
-#else
- return (wxCheckBoxState) ((::SendMessage(GetHwnd(), BM_GETCHECK, 0, 0)
- & 0x001) == 0x001);
-#endif
-
}
#endif // wxUSE_CHECKBOX
if ( !IsEnabled() )
return MSWControlColorDisabled(hDC);
- return wxChoiceBase::MSWControlColorSolid(hDC);
+ return wxChoiceBase::MSWControlColor(hDC);
}
#endif // wxUSE_CHOICE && !(__SMARTPHONE__ && __WXWINCE__)
::SetTextColor(hdc, wxColourToRGB(GetForegroundColour()));
}
+ WXHBRUSH hbr = 0;
+ if ( !colBg.Ok() )
+ {
+ hbr = MSWGetBgBrush(pDC);
+
+ // if the control doesn't have any bg colour, foreground colour will be
+ // ignored as the return value would be 0 -- so forcefully give it a
+ // non default background brush in this case
+ if ( !hbr && m_hasFgCol )
+ colBg = GetBackgroundColour();
+ }
+
// use the background colour override if a valid colour is given
- WXHBRUSH hbr;
if ( colBg.Ok() )
{
::SetBkColor(hdc, wxColourToRGB(colBg));
hbr = (WXHBRUSH)brush->GetResourceHandle();
}
- else // use our own background colour and recurse upwards if necessary
- {
- hbr = MSWGetBgBrush(pDC);
- }
return hbr;
}
WXHBRUSH wxControl::MSWControlColor(WXHDC pDC)
{
- // by default consider that the controls text shouldn't erase the
- // background under it (this is true for all static controls, check boxes,
- // radio buttons, ...)
- ::SetBkMode((HDC)pDC, TRANSPARENT);
+ wxColour colBg;
+
+ if ( HasTransparentBackground() )
+ ::SetBkMode((HDC)pDC, TRANSPARENT);
+ else // if the control is opaque it shouldn't use the parents background
+ colBg = GetBackgroundColour();
- return DoMSWControlColor(pDC, wxNullColour);
+ return DoMSWControlColor(pDC, colBg);
}
WXHBRUSH wxControl::MSWControlColorDisabled(WXHDC pDC)
#endif
IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxNotifyEvent)
-// ----------------------------------------------------------------------------
-// local functions
-// ----------------------------------------------------------------------------
-
-#ifndef __WXWINCE__
-// apparently DrawThemeBackground() modifies the rect passed to it and if we
-// don't call this function there are some drawing artifacts which are only
-// visible with some non default themes; so modify the rect here so that it
-// still paints the correct area
-static void AdjustRectForThemeBg(RECT& rc)
-{
- // magic numbers needed to compensate for DrawThemeBackground()
- rc.left -= 2;
- rc.top -= 2;
- rc.right += 4;
- rc.bottom += 5;
-}
-#endif
-
// ============================================================================
// implementation
// ============================================================================
if (style & wxNB_FLAT)
style |= wxBORDER_SUNKEN;
#endif
-
+
// comctl32.dll 6.0 doesn't support non-top tabs with visual styles (the
// control is simply not rendered correctly), so disable them in this case
const int verComCtl32 = wxApp::GetComCtl32Version();
else if ( style & wxNB_LEFT )
tabStyle |= TCS_VERTICAL;
else if ( style & wxNB_RIGHT )
- tabStyle |= TCS_VERTICAL | TCS_RIGHT;
+ tabStyle |= TCS_VERTICAL | TCS_RIGHT;
// ex style
if ( exstyle )
// wxNotebook size settings
// ----------------------------------------------------------------------------
+wxRect wxNotebook::GetPageSize() const
+{
+ wxRect r;
+
+ RECT rc;
+ ::GetClientRect(GetHwnd(), &rc);
+
+ // This check is to work around a bug in TabCtrl_AdjustRect which will
+ // cause a crash on win2k, or on XP with themes disabled, if the
+ // wxNB_MULTILINE style is used and the rectangle is very small, (such as
+ // when the notebook is first created.) The value of 20 is just
+ // arbitrarily chosen, if there is a better way to determine this value
+ // then please do so. --RD
+ if ( !HasFlag(wxNB_MULTILINE) || (rc.right > 20 && rc.bottom > 20) )
+ {
+ TabCtrl_AdjustRect(m_hwnd, false, &rc);
+
+ wxCopyRECTToRect(rc, r);
+ }
+
+ return r;
+}
+
void wxNotebook::SetPageSize(const wxSize& size)
{
// transform the page size into the notebook size
{
wxCHECK_RET( page, _T("NULL page in wxNotebook::AdjustPageSize") );
- RECT rc;
- rc.left =
- rc.top = 0;
-
- // get the page size from the notebook size
- GetSize((int *)&rc.right, (int *)&rc.bottom);
-
- // This check is to work around a bug in TabCtrl_AdjustRect which will
- // cause a crash on win2k, or on XP with themes disabled, if the
- // wxNB_MULTILINE style is used and the rectangle is very small, (such as
- // when the notebook is first created.) The value of 20 is just
- // arbitrarily chosen, if there is a better way to determine this value
- // then please do so. --RD
- if (rc.right > 20 && rc.bottom > 20)
+ const wxRect r = GetPageSize();
+ if ( !r.IsEmpty() )
{
- TabCtrl_AdjustRect(m_hwnd, false, &rc);
- page->SetSize(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
+ page->SetSize(r);
}
}
#if wxUSE_UXTHEME
-WXHBRUSH wxNotebook::QueryBgBitmap()
+bool wxNotebook::DoDrawBackground(WXHDC hDC, wxWindow *child)
{
+ wxUxThemeHandle theme(child ? child : this, L"TAB");
+ if ( !theme )
+ return false;
+
+ // get the notebook client rect (we're not interested in drawing tabs
+ // themselves)
+ wxRect r = GetPageSize();
+ if ( r.IsEmpty() )
+ return false;
+
RECT rc;
- ::GetClientRect(GetHwnd(), &rc);
+ wxCopyRectToRECT(r, rc);
+
+ // map rect to the coords of the window we're drawing in
+ if ( child )
+ ::MapWindowPoints(GetHwnd(), GetHwndOf(child), (POINT *)&rc, 2);
+
+
+ // apparently DrawThemeBackground() modifies the rect passed to it and if we
+ // don't do these adjustments, there are some drawing artifacts which are
+ // only visible with some non default themes; so modify the rect here using
+ // the magic numbers below so that it still paints the correct area
+ rc.left -= 2;
+ rc.top -= 2;
+ rc.right += 4;
+ rc.bottom += 5;
+
+
+ wxUxThemeEngine::Get()->DrawThemeBackground
+ (
+ theme,
+ hDC,
+ 9 /* TABP_PANE */,
+ 0,
+ &rc,
+ NULL
+ );
+
+ return true;
+}
- // adjust position
- TabCtrl_AdjustRect(GetHwnd(), false, &rc);
+WXHBRUSH wxNotebook::QueryBgBitmap()
+{
+ wxRect r = GetPageSize();
+ if ( r.IsEmpty() )
+ return 0;
WindowHDC hDC(GetHwnd());
MemoryHDC hDCMem(hDC);
- CompatibleBitmap hBmp(hDC, rc.right, rc.bottom);
+ CompatibleBitmap hBmp(hDC, r.x + r.width, r.y + r.height);
SelectInHDC selectBmp(hDCMem, hBmp);
- wxUxThemeHandle theme(this, L"TAB");
- if ( theme )
- {
- AdjustRectForThemeBg(rc);
-
- wxUxThemeEngine::Get()->DrawThemeBackground
- (
- theme,
- (WXHDC)hDCMem,
- 9 /* TABP_PANE */,
- 0,
- &rc,
- NULL
- );
- }
+ if ( !DoDrawBackground((WXHDC)(HDC)hDCMem) )
+ return 0;
return (WXHBRUSH)::CreatePatternBrush(hBmp);
}
{
m_hbrBackground = QueryBgBitmap();
}
- else // no themes
+ else // no themes or we've got user-defined solid colour
{
m_hbrBackground = NULL;
}
return wxNotebookBase::MSWGetBgBrushForChild(hDC, win);
}
-wxColour wxNotebook::MSWGetBgColourForChild(wxWindow *WXUNUSED(win))
-{
- if ( m_hasBgCol )
- return GetBackgroundColour();
-
- // Experimental: don't do this since we're doing it in wxPanel
-#if 0 // defined(__POCKETPC__) || defined(__SMARTPHONE__)
- // For some reason, the pages will be grey by default.
- // Normally they should be white on these platforms.
- // (However the static control backgrounds are painted
- // in the correct colour, just not the rest of it.)
- // So let's give WinCE a hint.
- else if (!win->m_hasBgCol)
- return *wxWHITE;
-#endif
-
- if ( !wxUxThemeEngine::GetIfActive() )
- return wxNullColour;
-
- return GetThemeBackgroundColour();
-}
-
-bool
-wxNotebook::MSWPrintChild(wxWindow *win,
- WXWPARAM wParam,
- WXLPARAM WXUNUSED(lParam))
+bool wxNotebook::MSWPrintChild(WXHDC hDC, wxWindow *child)
{
- // Don't paint the theme for the child if we have a solid background
- if ( m_hasBgCol )
- return false;
-
-
- RECT rc;
- ::GetClientRect(GetHwnd(), &rc);
+ // solid background colour overrides themed background drawing
+ if ( !UseBgCol() && DoDrawBackground(hDC, child) )
+ return true;
- // adjust position
- TabCtrl_AdjustRect(GetHwnd(), false, &rc);
-
- wxUxThemeHandle theme(win, L"TAB");
- if ( theme )
- {
- // map from this client to win client coords
- ::MapWindowPoints(GetHwnd(), GetHwndOf(win), (POINT *)&rc, 2);
-
- AdjustRectForThemeBg(rc);
- wxUxThemeEngine::Get()->DrawThemeBackground
- (
- theme,
- (WXHDC)wParam,
- 9 /* TABP_PANE */,
- 0,
- &rc,
- NULL
- );
- }
-
- return true;
+ return wxNotebookBase::MSWPrintChild(hDC, child);
}
#endif // wxUSE_UXTHEME
}
}
+// ----------------------------------------------------------------------------
+// radio box drawing
+// ----------------------------------------------------------------------------
+
+#ifndef __WXWINCE__
+
+WXHRGN wxRadioBox::MSWGetRegionWithoutChildren()
+{
+ RECT rc;
+ ::GetWindowRect(GetHwnd(), &rc);
+ HRGN hrgn = ::CreateRectRgn(rc.left, rc.top, rc.right + 1, rc.bottom + 1);
+
+ const size_t count = GetCount();
+ for ( size_t i = 0; i < count; ++i )
+ {
+ ::GetWindowRect((*m_radioButtons)[i], &rc);
+ AutoHRGN hrgnchild(::CreateRectRgnIndirect(&rc));
+ ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
+ }
+
+ return (WXHRGN)hrgn;
+}
+
+#endif // __WXWINCE__
+
// ---------------------------------------------------------------------------
// window proc for radio buttons
// ---------------------------------------------------------------------------
break;
}
+ break;
#endif // !__WXWINCE__
}
return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, message, wParam, lParam);
}
-WXHRGN wxRadioBox::MSWGetRegionWithoutChildren()
-{
- RECT rc;
- ::GetWindowRect(GetHwnd(), &rc);
- HRGN hrgn = ::CreateRectRgn(rc.left, rc.top, rc.right + 1, rc.bottom + 1);
-
- const size_t count = GetCount();
- for ( size_t i = 0; i < count; ++i )
- {
- ::GetWindowRect((*m_radioButtons)[i], &rc);
- AutoHRGN hrgnchild(::CreateRectRgnIndirect(&rc));
- ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
- }
-
- return (WXHRGN)hrgn;
-}
-
-WXLRESULT wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
-{
-#ifndef __WXWINCE__
- if ( nMsg == WM_PRINTCLIENT )
- {
- // first check to see if a parent window knows how to paint us better
- for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
- if ( win->MSWPrintChild(this, wParam, lParam) )
- return true;
-
- // nope, so lets do it ourselves
- RECT rc;
- WXHBRUSH hbr = DoMSWControlColor((HDC)wParam, wxNullColour);
- if ( !hbr )
- {
- wxBrush *brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID);
- hbr = (WXHBRUSH)brush->GetResourceHandle();
- }
-
- ::GetClientRect(GetHwnd(), &rc);
- ::FillRect((HDC)wParam, &rc, (HBRUSH)hbr);
-
- return true;
- }
-#endif
- // __WXWINCE__
-
- return wxStaticBox::MSWWindowProc(nMsg, wParam, lParam);
-}
#endif // wxUSE_RADIOBOX
#ifndef __WXWINCE__
Connect(wxEVT_PAINT, wxPaintEventHandler(wxStaticBox::OnPaint));
-#endif
+#endif // !__WXWINCE__
return true;
}
return wxSize(wBox, hBox);
}
-WXLRESULT wxStaticBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+void wxStaticBox::GetBordersForSizer(int *borderTop, int *borderOther) const
{
+ wxStaticBoxBase::GetBordersForSizer(borderTop, borderOther);
+
+ // need extra space, don't know how much but this seems to be enough
+ *borderTop += GetCharHeight()/3;
+}
+
+// all the hacks below are not necessary for WinCE
#ifndef __WXWINCE__
+
+WXLRESULT wxStaticBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+{
if ( nMsg == WM_NCHITTEST )
{
// This code breaks some other processing such as enter/leave tracking
s_useHTClient = wxSystemOptions::GetOptionInt(wxT("msw.staticbox.htclient"));
if (s_useHTClient == 1)
{
- int xPos = LOWORD(lParam); // horizontal position of cursor
- int yPos = HIWORD(lParam); // vertical position of cursor
+ int xPos = GET_X_LPARAM(lParam);
+ int yPos = GET_Y_LPARAM(lParam);
ScreenToClient(&xPos, &yPos);
return (long)HTCLIENT;
}
}
-#endif // !__WXWINCE__
return wxControl::MSWWindowProc(nMsg, wParam, lParam);
}
-void wxStaticBox::GetBordersForSizer(int *borderTop, int *borderOther) const
-{
- wxStaticBoxBase::GetBordersForSizer(borderTop, borderOther);
+// ----------------------------------------------------------------------------
+// static box drawing
+// ----------------------------------------------------------------------------
- // need extra space, don't know how much but this seems to be enough
- *borderTop += GetCharHeight()/3;
-}
+/*
+ We draw the static box ourselves because it's the only way to prevent it
+ from flickering horribly on resize (because everything inside the box is
+ erased twice: once when the box itself is repainted and second time when
+ the control inside it is repainted) without using WS_EX_TRANSPARENT style as
+ we used to do and which resulted in other problems.
+ */
// MSWGetRegionWithoutSelf helper: removes the given rectangle from region
static inline void
return (WXHRGN)hrgn;
}
-// helper for OnPaint()
+// helper for OnPaint(): really erase the background, i.e. do it even if we
+// don't have any non default brush for doing it (DoEraseBackground() doesn't
+// do anything in such case)
void wxStaticBox::PaintBackground(wxDC& dc, const RECT& rc)
{
- // note that static box should be transparent, so it should show its
- // parents colour, not its own
- wxWindow * const parent = GetParent();
-
- HBRUSH hbr = (HBRUSH)parent->MSWGetBgBrush(dc.GetHDC());
+ // note that we do not use the box background colour here, it shouldn't
+ // apply to its interior for several reasons:
+ // 1. wxGTK doesn't do it
+ // 2. controls inside the box don't get correct bg colour because they
+ // are not our children so we'd have some really ugly colour mix if
+ // we did it
+ // 3. this is backwards compatible behaviour and some people rely on it,
+ // see http://groups.google.com/groups?selm=4252E932.3080801%40able.es
+ wxWindow *parent = GetParent();
+ HBRUSH hbr = (HBRUSH)parent->MSWGetBgBrush(dc.GetHDC(), this);
+
+ // if there is no special brush for painting this control, just use the
+ // solid background colour
+ wxBrush brush;
if ( !hbr )
{
- wxBrush *brush =
- wxTheBrushList->FindOrCreateBrush(parent->GetBackgroundColour());
- if ( brush )
- hbr = GetHbrushOf(*brush);
+ brush = wxBrush(parent->GetBackgroundColour());
+ hbr = GetHbrushOf(brush);
}
- if ( hbr )
- ::FillRect(GetHdcOf(dc), &rc, hbr);
+ ::FillRect(GetHdcOf(dc), &rc, hbr);
}
void wxStaticBox::OnPaint(wxPaintEvent& WXUNUSED(event))
{
- wxPaintDC dc(this);
RECT rc;
::GetClientRect(GetHwnd(), &rc);
- // draw the entire box in a memory DC, but only blit the bits not redrawn
- // either by our children windows nor by FillRect() painting the background
- // below
+ // draw the entire box in a memory DC
wxMemoryDC memdc;
wxBitmap bitmap(rc.right, rc.bottom);
memdc.SelectObject(bitmap);
PaintBackground(memdc, rc);
+
+ // NB: neither setting the text colour nor transparent background mode
+ // doesn't change anything: the static box def window proc still
+ // draws the label in its own colours, so if we want to have control
+ // over this we really have to draw everything ourselves
MSWDefWindowProc(WM_PAINT, (WPARAM)GetHdcOf(memdc), 0);
+
+ // now only blit the static box border itself, not the interior, to avoid
+ // flicker when background is drawn below
+ //
+ // note that it seems to be faster to do 4 small blits here and then paint
+ // directly into wxPaintDC than painting background in wxMemoryDC and then
+ // blitting everything at once to wxPaintDC, this is why we do it like this
+ wxPaintDC dc(this);
int borderTop, border;
GetBordersForSizer(&borderTop, &border);
dc.Blit(rc.right - border, 0, rc.right, rc.bottom,
&memdc, rc.right - border, 0);
+
+ // create the region excluding box children
AutoHRGN hrgn((HRGN)MSWGetRegionWithoutChildren());
RECT rcWin;
::GetWindowRect(GetHwnd(), &rcWin);
::OffsetRgn(hrgn, -rcWin.left, -rcWin.top);
-
- // now remove the box itself
+ // and also the box itself
MSWGetRegionWithoutSelf((WXHRGN) hrgn, rc.right, rc.bottom);
+ HDCClipper clipToBg(GetHdcOf(dc), hrgn);
- // and paint the inside of the box (excluding child controls)
- ::SelectClipRgn(GetHdcOf(dc), hrgn);
+ // paint the inside of the box (excluding box itself and child controls)
PaintBackground(dc, rc);
- ::SelectClipRgn(GetHdcOf(dc), NULL);
}
+#endif // !__WXWINCE__
+
#endif // wxUSE_STATBOX
return msStyle;
}
-WXHBRUSH wxStaticText::DoMSWControlColor(WXHDC pDC, wxColour colBg)
-{
- // If this control has a non-standard fg colour but still has the standard
- // bg then we need to also give it a non-standard bg otherwise the fg
- // setting has no effect.
- WXHBRUSH hbr = wxControl::DoMSWControlColor(pDC, colBg);
- if (!hbr && m_hasFgCol)
- {
- hbr = MSWGetBgBrushForChild(pDC, this);
- if (!hbr)
- {
- HDC hdc = (HDC)pDC;
- wxColour bg = GetBackgroundColour();
- ::SetBkColor(hdc, wxColourToRGB(bg));
- wxBrush *brush = wxTheBrushList->FindOrCreateBrush(bg, wxSOLID);
- hbr = (WXHBRUSH)brush->GetResourceHandle();
- }
- }
- return hbr;
-}
-
wxSize wxStaticText::DoGetBestSize() const
{
wxClientDC dc(wx_const_cast(wxStaticText *, this));
if ( !IsEnabled() && !HasFlag(wxTE_MULTILINE) )
return MSWControlColorDisabled(hDC);
- return wxTextCtrlBase::MSWControlColorSolid(hDC);
+ return wxTextCtrlBase::MSWControlColor(hDC);
}
bool wxTextCtrl::AdjustSpaceLimit()
processed = HandleKillFocus((WXHWND)(HWND)wParam);
break;
- case WM_PAINT:
+ case WM_PRINTCLIENT:
+ // we receive this message when DrawThemeParentBackground() is
+ // called from def window proc of several controls under XP and we
+ // must draw properly themed background here
+ //
+ // note that naively I'd expect filling the client rect with the
+ // brush returned by MSWGetBgBrush() work -- but for some reason it
+ // doesn't and we have to call parents MSWPrintChild() which is
+ // supposed to call DrawThemeBackground() with appropriate params
+ //
+ // also note that in this case lParam == PRF_CLIENT but we're
+ // clearly expected to paint the background and nothing else!
{
- if ( wParam )
- {
- // cast to wxWindow is needed for wxUniv
- wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
- processed = HandlePaint();
- }
- else
+ for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
{
- processed = HandlePaint();
- }
- break;
- }
+ if ( win->MSWPrintChild((WXHDC)wParam, (wxWindow *)this) )
+ {
+ processed = true;
+ break;
+ }
-#ifdef WM_PRINT
- case WM_PRINTCLIENT:
- if ( GetParent() &&
- GetParent()->MSWPrintChild((wxWindow *)this, wParam, lParam) )
- {
- processed = true;
+ if ( win->IsTopLevel() || win->InheritsBackgroundColour() )
+ break;
+ }
}
break;
- case WM_PRINT:
+ case WM_PAINT:
+ if ( wParam )
{
- if ( lParam & PRF_ERASEBKGND )
- HandleEraseBkgnd((WXHDC)(HDC)wParam);
-
wxPaintDCEx dc((wxWindow *)this, (WXHDC)wParam);
processed = HandlePaint();
}
+ else // no DC given
+ {
+ processed = HandlePaint();
+ }
break;
-#endif // WM_PRINT
case WM_CLOSE:
#ifdef __WXUNIVERSAL__
// Universal uses its own wxFrame/wxDialog, so we don't receive
// close events unless we have this.
Close();
- processed = true;
- rc.result = TRUE;
-#else
+#endif // __WXUNIVERSAL__
+
// don't let the DefWindowProc() destroy our window - we'll do it
// ourselves in ~wxWindow
processed = true;
rc.result = TRUE;
-#endif
break;
case WM_SHOWWINDOW:
bool wxWindowMSW::HandleCtlColor(WXHBRUSH *brush, WXHDC pDC, WXHWND pWnd)
{
#if wxUSE_CONTROLS
- wxWindow *item = FindItemByHWND(pWnd, true);
+ wxControl *item = wxDynamicCast(FindItemByHWND(pWnd, true), wxControl);
+
if ( item )
*brush = item->MSWControlColor(pDC);
else
#endif // __WXMICROWIN__
-WXHBRUSH wxWindowMSW::MSWControlColor(WXHDC WXUNUSED(hDC))
-{
- return (WXHBRUSH)0;
-}
-
bool wxWindowMSW::HandlePaletteChanged(WXHWND hWndPalChange)
{
#if wxUSE_PALETTE
// do default background painting
- if ( !DoEraseBackground(*event.GetDC()) )
+ if ( !DoEraseBackground(GetHdcOf(*event.GetDC())) )
{
// let the system paint the background
event.Skip();
}
}
-bool wxWindowMSW::DoEraseBackground(wxDC& dc)
+bool wxWindowMSW::DoEraseBackground(WXHDC hDC)
{
- HBRUSH hBrush = (HBRUSH)MSWGetBgBrush(dc.GetHDC());
- if ( !hBrush )
+ HBRUSH hbr = (HBRUSH)MSWGetBgBrush(hDC);
+ if ( !hbr )
return false;
- RECT rc;
- ::GetClientRect(GetHwnd(), &rc);
- ::FillRect(GetHdcOf(dc), &rc, hBrush);
+ wxFillRect(GetHwnd(), (HDC)hDC, hbr);
return true;
}
-WXHBRUSH wxWindowMSW::MSWGetSolidBgBrushForChild(wxWindow *child)
-{
- wxColour col = MSWGetBgColourForChild(child);
- if ( col.Ok() )
- {
- // draw children with the same colour as the parent
- wxBrush *brush = wxTheBrushList->FindOrCreateBrush(col, wxSOLID);
-
- return (WXHBRUSH)brush->GetResourceHandle();
- }
-
- return 0;
-}
-
-wxColour wxWindowMSW::MSWGetBgColourForChild(wxWindow *child)
+WXHBRUSH
+wxWindowMSW::MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), wxWindow *child)
{
if ( m_hasBgCol )
{
// our background colour applies to:
// 1. this window itself, always
// 2. all children unless the colour is "not inheritable"
- // 3. immediate transparent children which should show the same
- // background as we do, but not for transparent grandchildren
- // which use the background of their immediate parent instead
- if ( m_inheritBgCol ||
- child == this ||
+ // 3. even if it is not inheritable, our immediate transparent
+ // children should still inherit it -- but not any transparent
+ // children because it would look wrong if a child of non
+ // transparent child would show our bg colour when the child itself
+ // does not
+ if ( child == this ||
+ m_inheritBgCol ||
(child->HasTransparentBackground() &&
child->GetParent() == this) )
{
- return GetBackgroundColour();
+ // draw children with the same colour as the parent
+ wxBrush *
+ brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour());
+
+ return (WXHBRUSH)GetHbrushOf(*brush);
}
}
- return wxNullColour;
+ return 0;
}
-WXHBRUSH wxWindowMSW::MSWGetBgBrushForSelf(wxWindow *parent, WXHDC hDC)
+WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, wxWindow *winToPaint)
{
- return parent->MSWGetBgBrushForChild(hDC, (wxWindow *)this);
-}
+ if ( !winToPaint )
+ winToPaint = this;
-WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC)
-{
- for ( wxWindow *win = (wxWindow *)this; win; win = win->GetParent() )
+ for ( wxWindowMSW *win = this; win; win = win->GetParent() )
{
- WXHBRUSH hBrush = MSWGetBgBrushForSelf(win, hDC);
+ WXHBRUSH hBrush = win->MSWGetBgBrushForChild(hDC, winToPaint);
if ( hBrush )
return hBrush;
- // background is not inherited beyond the windows which have their own
- // fixed background such as top level windows and notebooks and for
- // windows for which a custom colour had been explicitly set with
- // SetOwnBackgroundColour() and so shouldn't affect its children
- if ( win->ProvidesBackground() ||
- (win->UseBgCol() && !win->InheritsBackgroundColour()) )
+ // background is not inherited beyond top level windows
+ if ( win->IsTopLevel() )
break;
}
return 0;
}
-bool
-wxWindowMSW::MSWPrintChild(wxWindow * WXUNUSED(win),
- WXWPARAM WXUNUSED(wParam),
- WXLPARAM WXUNUSED(lParam))
-{
- return false;
-}
-
// ---------------------------------------------------------------------------
// moving and resizing
// ---------------------------------------------------------------------------