From 5afb945835abd3e3e37213e108e79423407213dd Mon Sep 17 00:00:00 2001 From: David Webster Date: Thu, 22 Mar 2001 23:23:19 +0000 Subject: [PATCH] Ownerdrawn stuff. Text display done, image display next. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@9572 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/os2/dcmemory.h | 14 +-- src/os2/dc.cpp | 183 +++++++++++++++++++++++++++++++++++--- src/os2/dcclient.cpp | 23 +++++ src/os2/dcmemory.cpp | 31 ++++++- src/os2/ownerdrw.cpp | 147 ++++++++++++++++++++---------- src/os2/window.cpp | 63 +++++++++++-- 6 files changed, 392 insertions(+), 69 deletions(-) diff --git a/include/wx/os2/dcmemory.h b/include/wx/os2/dcmemory.h index 85191f6e45..fa9e983e1b 100644 --- a/include/wx/os2/dcmemory.h +++ b/include/wx/os2/dcmemory.h @@ -16,16 +16,18 @@ class WXDLLEXPORT wxMemoryDC: public wxDC { - DECLARE_DYNAMIC_CLASS(wxMemoryDC) + DECLARE_DYNAMIC_CLASS(wxMemoryDC) - public: +public: wxMemoryDC(void); - wxMemoryDC( wxDC *dc ); // Create compatible DC + wxMemoryDC(wxDC* pDC); // Create compatible DC ~wxMemoryDC(void); - virtual void SelectObject( const wxBitmap& bitmap ); - virtual void DoGetSize( int *width, int *height ) const; -}; + virtual void SelectObject(const wxBitmap& rBitmap); + virtual void DoGetSize( int* pWidth + ,int* pHeight + ) const; +}; // end of CLASS wxMemoryDC #endif // _WX_DCMEMORY_H_ diff --git a/src/os2/dc.cpp b/src/os2/dc.cpp index 5a22aabc73..a2926a2788 100644 --- a/src/os2/dc.cpp +++ b/src/os2/dc.cpp @@ -1326,19 +1326,178 @@ wxCoord wxDCBase::LogicalToDeviceYRel(wxCoord y) const // bit blit // --------------------------------------------------------------------------- -bool wxDC::DoBlit( wxCoord xdest - ,wxCoord ydest - ,wxCoord width - ,wxCoord height - ,wxDC *source - ,wxCoord xsrc - ,wxCoord ysrc - ,int rop - ,bool useMask - ) +bool wxDC::DoBlit( + wxCoord vXdest +, wxCoord vYdest +, wxCoord vWidth +, wxCoord vHeight +, wxDC* pSource +, wxCoord vXsrc +, wxCoord vYsrc +, int nRop +, bool bUseMask +) { - // TODO - return(TRUE); + wxMask* pMask = NULL; + CHARBUNDLE vCbnd; + COLORREF vOldTextColor; + COLORREF vOldBackground = ::GpiQueryBackColor(m_hPS); + POINTL aPoint[4] = { vXdest, vYdest + ,vXdest + vWidth, vYdest + vHeight + ,vXsrc, vYsrc + ,vXsrc + vWidth, vYsrc + vHeight + }; + + if (bUseMask) + { + const wxBitmap& rBmp = pSource->m_vSelectedBitmap; + + pMask = rBmp.GetMask(); + if (!(rBmp.Ok() && pMask && pMask->GetMaskBitmap())) + { + bUseMask = FALSE; + } + } + + ::GpiQueryAttrs( m_hPS + ,PRIM_CHAR + ,CBB_COLOR + ,&vCbnd + ); + vOldTextColor = (COLORREF)vCbnd.lColor; + + if (m_textForegroundColour.Ok()) + { + vCbnd.lColor = (LONG)m_textForegroundColour.GetPixel(); + ::GpiSetAttrs( m_hPS // presentation-space handle + ,PRIM_CHAR // Char primitive. + ,CBB_COLOR // sets color. + ,0 + ,&vCbnd // buffer for attributes. + ); + } + if (m_textBackgroundColour.Ok()) + { + ::GpiSetBackColor(m_hPS, (LONG)m_textBackgroundColour.GetPixel()); + } + + LONG lRop = ROP_SRCCOPY; + + switch (nRop) + { + case wxXOR: lRop = ROP_SRCINVERT; break; + case wxINVERT: lRop = ROP_DSTINVERT; break; + case wxOR_REVERSE: lRop = 0x00DD0228; break; + case wxAND_REVERSE: lRop = ROP_SRCERASE; break; + case wxCLEAR: lRop = ROP_ZERO; break; + case wxSET: lRop = ROP_ONE; break; + case wxOR_INVERT: lRop = ROP_MERGEPAINT; break; + case wxAND: lRop = ROP_SRCAND; break; + case wxOR: lRop = ROP_SRCPAINT; break; + case wxEQUIV: lRop = 0x00990066; break; + case wxNAND: lRop = 0x007700E6; break; + case wxAND_INVERT: lRop = 0x00220326; break; + case wxCOPY: lRop = ROP_SRCCOPY; break; + case wxNO_OP: lRop = ROP_NOTSRCERASE; break; + case wxSRC_INVERT: lRop = ROP_SRCINVERT; break; + case wxNOR: lRop = ROP_NOTSRCCOPY; break; + default: + wxFAIL_MSG( wxT("unsupported logical function") ); + return FALSE; + } + + bool bSuccess; +#if 0 + if (bUseMask) + { + // + // Blit bitmap with mask + // + + // + // Create a temp buffer bitmap and DCs to access it and the mask + // + HDC dc_mask = ::CreateCompatibleDC(GetHdcOf(*source)); + HDC dc_buffer = ::CreateCompatibleDC(GetHdc()); + HBITMAP buffer_bmap = ::CreateCompatibleBitmap(GetHdc(), width, height); + ::SelectObject(dc_mask, (HBITMAP) mask->GetMaskBitmap()); + ::SelectObject(dc_buffer, buffer_bmap); + + // copy dest to buffer + if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height, + GetHdc(), xdest, ydest, SRCCOPY) ) + { + wxLogLastError(wxT("BitBlt")); + } + + // copy src to buffer using selected raster op + if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height, + GetHdcOf(*source), xsrc, ysrc, dwRop) ) + { + wxLogLastError(wxT("BitBlt")); + } + + // set masked area in buffer to BLACK (pixel value 0) + COLORREF prevBkCol = ::SetBkColor(GetHdc(), RGB(255, 255, 255)); + COLORREF prevCol = ::SetTextColor(GetHdc(), RGB(0, 0, 0)); + if ( !::BitBlt(dc_buffer, 0, 0, (int)width, (int)height, + dc_mask, xsrc, ysrc, SRCAND) ) + { + wxLogLastError(wxT("BitBlt")); + } + + // set unmasked area in dest to BLACK + ::SetBkColor(GetHdc(), RGB(0, 0, 0)); + ::SetTextColor(GetHdc(), RGB(255, 255, 255)); + if ( !::BitBlt(GetHdc(), xdest, ydest, (int)width, (int)height, + dc_mask, xsrc, ysrc, SRCAND) ) + { + wxLogLastError(wxT("BitBlt")); + } + ::SetBkColor(GetHdc(), prevBkCol); // restore colours to original values + ::SetTextColor(GetHdc(), prevCol); + + // OR buffer to dest + success = ::BitBlt(GetHdc(), xdest, ydest, + (int)width, (int)height, + dc_buffer, 0, 0, SRCPAINT) != 0; + if ( !success ) + { + wxLogLastError(wxT("BitBlt")); + } + + // tidy up temporary DCs and bitmap + ::SelectObject(dc_mask, 0); + ::DeleteDC(dc_mask); + ::SelectObject(dc_buffer, 0); + ::DeleteDC(dc_buffer); + ::DeleteObject(buffer_bmap); + } + } +#endif +// else // no mask, just BitBlt() it +// { + bSuccess = (::GpiBitBlt( m_hPS + ,pSource->GetHPS() + ,4L + ,aPoint + ,lRop + ,BBO_IGNORE + ) != GPI_ERROR); + if (!bSuccess ) + { + wxLogLastError(wxT("BitBlt")); + } +// } + vCbnd.lColor = (LONG)vOldTextColor; + ::GpiSetAttrs( m_hPS // presentation-space handle + ,PRIM_CHAR // Char primitive. + ,CBB_COLOR // sets color. + ,0 + ,&vCbnd // buffer for attributes. + ); + ::GpiSetBackColor(m_hPS, (LONG)vOldBackground); + return bSuccess; } void wxDC::DoGetSize( int* width, int* height ) const diff --git a/src/os2/dcclient.cpp b/src/os2/dcclient.cpp index bc20d8ac52..1875e60cfb 100644 --- a/src/os2/dcclient.cpp +++ b/src/os2/dcclient.cpp @@ -123,7 +123,17 @@ wxWindowDC::wxWindowDC( sError = wxPMErrorToStr(vError); wxLogError("Unable to set current color table. Error: %s\n", sError); } + ::GpiCreateLogColorTable( m_hPS + ,0L + ,LCOLF_RGB + ,0L + ,0L + ,NULL + ); SetBackground(wxBrush(m_pCanvas->GetBackgroundColour(), wxSOLID)); + ::WinQueryWindowRect( GetWinHwnd(m_pCanvas) + ,&m_vRclPaint + ); } wxWindowDC::~wxWindowDC() @@ -190,6 +200,13 @@ wxClientDC::wxClientDC( sError = wxPMErrorToStr(vError); wxLogError("Unable to set current color table. Error: %s\n", sError); } + ::GpiCreateLogColorTable( m_hPS + ,0L + ,LCOLF_RGB + ,0L + ,0L + ,NULL + ); // // Default mode is BM_LEAVEALONE so we make no call Set the mix // @@ -197,6 +214,12 @@ wxClientDC::wxClientDC( ,wxSOLID ) ); + // + // Set the DC/PS rectangle + // + ::WinQueryWindowRect( GetWinHwnd(m_pCanvas) + ,&m_vRclPaint + ); } // end of wxClientDC::wxClientDC wxClientDC::~wxClientDC() diff --git a/src/os2/dcmemory.cpp b/src/os2/dcmemory.cpp index d9d6a2201f..a0aeef01b2 100644 --- a/src/os2/dcmemory.cpp +++ b/src/os2/dcmemory.cpp @@ -28,6 +28,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC, wxDC) wxMemoryDC::wxMemoryDC(void) { + ERRORID vError; + wxString sError; HDC hDC; HPS hPS; DEVOPENSTRUC vDOP = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; @@ -48,6 +50,33 @@ wxMemoryDC::wxMemoryDC(void) m_bOwnsDC = TRUE; SetBrush(*wxWHITE_BRUSH); SetPen(*wxBLACK_PEN); + if (!::GpiCreateLogColorTable( m_hPS + ,0L + ,LCOLF_CONSECRGB + ,0L + ,(LONG)wxTheColourDatabase->m_nSize + ,(PLONG)wxTheColourDatabase->m_palTable + )) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + wxLogError("Unable to set current color table. Error: %s\n", sError); + } + // + // Set the color table to RGB mode + // + if (!::GpiCreateLogColorTable( m_hPS + ,0L + ,LCOLF_RGB + ,0L + ,0L + ,NULL + )) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + wxLogError("Unable to set current color table. Error: %s\n", sError); + } } else { @@ -155,7 +184,7 @@ void wxMemoryDC::SelectObject( m_vSelectedBitmap.SetSelectedInto(this); hBmp = (WXHBITMAP)::GpiSetBitmap(m_hPS, (HBITMAP)hBmp); - if (hBmp != HBM_ERROR) + if (hBmp == HBM_ERROR) { wxLogLastError(wxT("SelectObject(memDC, bitmap)")); wxFAIL_MSG(wxT("Couldn't select a bitmap into wxMemoryDC")); diff --git a/src/os2/ownerdrw.cpp b/src/os2/ownerdrw.cpp index a270099a34..1f58781ed9 100644 --- a/src/os2/ownerdrw.cpp +++ b/src/os2/ownerdrw.cpp @@ -75,6 +75,7 @@ bool wxOwnerDrawn::OnMeasureItem( wxString sStr = wxStripMenuCodes(m_strName); +#if 0 wxString sTgt = "\t"; size_t nIndex; @@ -85,7 +86,7 @@ bool wxOwnerDrawn::OnMeasureItem( nIndex = sStr.Find(sTgt.c_str()); if (nIndex != -1) sStr.Replace(sTgt.c_str(), "", TRUE); - +#endif vDC.GetTextExtent( sStr ,(long *)pWidth ,(long *)pHeight @@ -120,6 +121,7 @@ bool wxOwnerDrawn::OnDrawItem( wxColour vColBack; wxColour vColText; COLORREF vRef; + RECTL vRect = {rRect.x + 4, rRect.y + 1, rRect.x + (rRect.width - 2), rRect.y + rRect.height}; char zMsg[128]; // @@ -133,17 +135,18 @@ bool wxOwnerDrawn::OnDrawItem( { ::GpiSetCharSet(hPS, LCID_DEFAULT); } + + // + // Base on the status of the menu item pick the right colors + // if (eStatus & wxODSelected) { - vRef = (ULONG)::WinQuerySysColor( HWND_DESKTOP - ,SYSCLR_MENUHILITEBGND // Light gray - ,0L - ); - vColBack.Set( GetRValue(vRef) - ,GetGValue(vRef) - ,GetBValue(vRef) - ); - vColText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_MENUTEXT); + wxColour vCol2("WHITE"); + vColBack.Set( (unsigned char)0 + ,(unsigned char)0 + ,(unsigned char)160 + ); // no dark blue in color table + vColText = vCol2; } else if (eStatus & wxODDisabled) { @@ -186,24 +189,14 @@ bool wxOwnerDrawn::OnDrawItem( ,GetBValue(vRef) ); } - vRef = vColBack.GetPixel(); - vCbnd.lBackColor = (LONG)vRef; - - vRef = vColText.GetPixel(); - vCbnd.lColor = (LONG)vRef; + rDC.SetTextBackground(vColBack); + rDC.SetTextForeground(vColText); + rDC.SetBackgroundMode(wxTRANSPARENT); - sprintf(zMsg, "Color: %ld", vRef); - wxMessageBox( "wxWindows Menu Sample" - ,zMsg - ,wxICON_INFORMATION - ); - - ::GpiSetAttrs( hPS - ,PRIM_CHAR - ,CBB_COLOR | CBB_BACK_COLOR - ,0 - ,&vCbnd - ); + // + // Paint the background + // + ::WinFillRect(hPS, &vRect, vColBack.GetPixel()); // // Determine where to draw and leave space for a check-mark. @@ -215,34 +208,99 @@ bool wxOwnerDrawn::OnDrawItem( // drawing methods like ::DrawState that can cleanly handle accel // pneumonics and deal, automatically, with various states, so we have // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn - // strings either. + // strings either. We cannot handle mneumonics either. We display + // it, though, in hopes we can figure it out some day. + // // - // Manually replace the tab with spaces + // Display main text and accel text separately to allign better // wxString sTgt = "\t"; - wxString sReplace = " "; + wxString sFullString = m_strName; // need to save the original text + wxString sAccel; size_t nIndex; + size_t nWidth; + size_t nCharWidth; + size_t nHeight; + bool bFoundMneumonic = FALSE; + bool bFoundAccel = FALSE; - nIndex = m_strName.Find(sTgt.c_str()); + // + // Deal with the tab, extracting the Accel text + // + nIndex = sFullString.Find(sTgt.c_str()); if (nIndex != -1) - m_strName.Replace(sTgt.c_str(), sReplace.c_str(), TRUE); + { + bFoundAccel = TRUE; + sAccel = sFullString.Mid(nIndex + 1); + sFullString.Remove(nIndex); + } + + // + // Deal with the mneumonic character + // sTgt = "~"; - nIndex = m_strName.Find(sTgt.c_str()); + nIndex = sFullString.Find(sTgt.c_str()); if (nIndex != -1) - m_strName.Replace(sTgt.c_str(), "", TRUE); + { + wxString sTmp = sFullString; + + bFoundMneumonic = TRUE; + sTmp.Remove(nIndex); + rDC.GetTextExtent( sTmp + ,(long *)&nWidth + ,(long *)&nHeight + ); + sTmp = sFullString[nIndex + 1]; + rDC.GetTextExtent( sTmp + ,(long *)&nCharWidth + ,(long *)&nHeight + ); + sFullString.Replace(sTgt.c_str(), "", TRUE); + } + + // + // Draw the main item text sans the accel text + rDC.DrawText( sFullString + ,nX + ,rRect.y + 4 + ); + if (bFoundMneumonic) + { + // + // Underline the mneumonic -- still won't work, but at least it "looks" right + // + wxPen vPen; + POINTL vPntStart = {nX + nWidth - 1, rRect.y + 2}; // Make it look pretty! + POINTL vPntEnd = {nX + nWidth + nCharWidth - 3, rRect.y + 2}; //CharWidth is bit wide + + vPen = wxPen(vColText, 1, wxSOLID); // Assuming we are always black + rDC.SetPen(vPen); + ::GpiMove(hPS, &vPntStart); + ::GpiLine(hPS, &vPntEnd); + } - POINTL vPoint; + // + // Now draw the accel text + // + if (bFoundAccel) + { + size_t nWidth; + size_t nHeight; - vPoint.x = nX; - vPoint.y = rRect.y + 4; - ::GpiCharStringAt( hPS - ,&vPoint - ,m_strName.length() - ,(PCH)m_strName.c_str() - ); + rDC.GetTextExtent( sAccel + ,(long *)&nWidth + ,(long *)&nHeight + ); + // + // Back off the starting position from the right edge + // + rDC.DrawText( sAccel + ,rRect.width - (nWidth + 7) // this seems to mimic the default OS/2 positioning + ,rRect.y + 4 + ); + } -#if 0 // // Draw the bitmap // --------------- @@ -316,7 +374,7 @@ bool wxOwnerDrawn::OnDrawItem( }; LINEBUNDLE vLine; - vLine.lColor = lColBack; + vLine.lColor = vColBack.GetPixel(); ::GpiSetAttrs( hPS ,PRIM_LINE ,LBB_COLOR @@ -332,7 +390,6 @@ bool wxOwnerDrawn::OnDrawItem( } } } -#endif return TRUE; } // end of wxOwnerDrawn::OnDrawItem diff --git a/src/os2/window.cpp b/src/os2/window.cpp index e3b48ba2e7..b9729c7770 100644 --- a/src/os2/window.cpp +++ b/src/os2/window.cpp @@ -2663,6 +2663,8 @@ bool wxWindow::OS2OnDrawItem( // if (vId == 0) { + ERRORID vError; + wxString sError; POWNERITEM pMeasureStruct = (POWNERITEM)pItemStruct; wxFrame* pFrame = (wxFrame*)this; wxMenuItem* pMenuItem = pFrame->GetMenuBar()->FindItem(pMeasureStruct->idItem, pMeasureStruct->hItem); @@ -2676,6 +2678,36 @@ bool wxWindow::OS2OnDrawItem( ,FALSE ); vDc.SetHPS(pMeasureStruct->hps); + // + // Load the wxWindows Pallete and set to RGB mode + // + if (!::GpiCreateLogColorTable( pMeasureStruct->hps + ,0L + ,LCOLF_CONSECRGB + ,0L + ,(LONG)wxTheColourDatabase->m_nSize + ,(PLONG)wxTheColourDatabase->m_palTable + )) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + wxLogError("Unable to set current color table. Error: %s\n", sError); + } + // + // Set the color table to RGB mode + // + if (!::GpiCreateLogColorTable( pMeasureStruct->hps + ,0L + ,LCOLF_RGB + ,0L + ,0L + ,NULL + )) + { + vError = ::WinGetLastError(vHabmain); + sError = wxPMErrorToStr(vError); + wxLogError("Unable to set current color table. Error: %s\n", sError); + } wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); @@ -2719,11 +2751,32 @@ bool wxWindow::OS2OnDrawItem( } else { - // - // For now we don't care about doing our own highlighting so we'll - // just ignore the entie message! - // - return TRUE; + if (pMeasureStruct->fsAttribute & MIA_HILITED) + { + eAction = wxOwnerDrawn::wxODDrawAll; + eStatus |= wxOwnerDrawn::wxODSelected; + // + // Keep the system from trying to highlight with its bogus colors + // + pMeasureStruct->fsAttributeOld = pMeasureStruct->fsAttribute &= ~MIA_HILITED; + } + else if (!(pMeasureStruct->fsAttribute & MIA_HILITED)) + { + eAction = wxOwnerDrawn::wxODDrawAll; + eStatus = 0; + // + // Keep the system from trying to highlight with its bogus colors + // + pMeasureStruct->fsAttribute = pMeasureStruct->fsAttributeOld &= ~MIA_HILITED; + } + else + { + // + // For now we don't care about anything else + // just ignore the entire message! + // + return TRUE; + } } // // Now redraw the item -- 2.45.2