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