wxMSW: wxDC destructor
Nusret Taşçı
nusi at sofha.de
Thu Sep 21 13:39:58 PDT 2006
I was about to derive from wxBitmapButton, so that I have a bitmap
button which draws it's labels and works within XP-themes.
I thought the best place would be to implement virtual MSWOnDraw() and
call the baseclass implementation. After that I'd like to draw the text
myself.
However, if I do it like this, I'd need to copy/paste most of the code
of wxBitmapButton::MSWOnDraw, because the destructor of wxDC breaks my neck.
Following example doesn't work:
bool myBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
{
wxBitmapButton::MSWOnDraw(item);
// if wxBU_TOP etc etc etc
{
wxClientDC dst;
dst.SetHDC((WXHDC) lpDIS->hDC, false);
dst.SetFont(GetParent()->GetFont());
int nWidth = 0;
int nHeight = 0;
dst.GetTextExtent(GetLabel(), &nWidth, &nHeight);
dst.DrawText(GetLabel(),
((lpDIS->rcItem.right - lpDIS->rcItem.left) -
nWidth) / 2,
lpDIS->rcItem.bottom - nHeight);
}
}
GetTextExtent() and DrawText() show following error:
22:26:02: ..\..\src\msw\dc.cpp(1745): 'GetTextExtentPoint32()' failed
with error 0x00000057 (falscher Parameter.).
22:26:03: ..\..\src\msw\dc.cpp(1328): 'TextOut' failed with error
0x00000057 (falscher Parameter.).
22:26:03: ..\..\src\msw\dc.cpp(1745): 'GetTextExtentPoint32()' failed
with error 0x00000057 (falscher Parameter.).
If the code would look like this, (no call to baseclass and my own code
called twice), than I'd get the same errors in the 2nd run of the loop:
bool myBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
{
for (size_t i=0; i<2; ++i)
{
wxClientDC dst;
dst.SetHDC((WXHDC) lpDIS->hDC, false);
dst.SetFont(GetParent()->GetFont());
int nWidth = 0;
int nHeight = 0;
dst.GetTextExtent(GetLabel(), &nWidth, &nHeight);
dst.DrawText(GetLabel(),
((lpDIS->rcItem.right - lpDIS->rcItem.left) -
nWidth) / 2,
lpDIS->rcItem.bottom - nHeight);
}
}
I think it's related to the destructor of wxDC, which calles
::ReleaseDC() on the external HDC though it shouldn't.
wxBitmapButton::MSWOnDraw does use wxClientDC, too, so my first example
is a simlar problem as my second example.
For your convenience (see point of interest):
wxDC::~wxDC()
{
if ( m_hDC != 0 )
{
SelectOldObjects(m_hDC);
// if we own the HDC, we delete it, otherwise we just release it
if ( m_bOwnsDC )
{
::DeleteDC(GetHdc());
}
else // we don't own our HDC
{
if (m_canvas)
{
::ReleaseDC(GetHwndOf(m_canvas), GetHdc());
}
else
{
// Must have been a wxScreenDC
::ReleaseDC((HWND) NULL, GetHdc()); // <-- POI
}
}
}
}
Is my understanding right? I need to copy/paste the code?
Nusi.
More information about the wx-users
mailing list