From 402e2f7cf8f05f93846258f658865d780342925a Mon Sep 17 00:00:00 2001 From: David Webster Date: Wed, 31 Jan 2001 05:33:10 +0000 Subject: [PATCH] Ownerdrawn stuff for OS/2 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@9234 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/os2/ownerdrw.cpp | 361 ++++++++++++++++++++++++++++--------------- src/os2/window.cpp | 139 ++++++++++------- 2 files changed, 324 insertions(+), 176 deletions(-) diff --git a/src/os2/ownerdrw.cpp b/src/os2/ownerdrw.cpp index 1be1044bda..c4a073c1f0 100644 --- a/src/os2/ownerdrw.cpp +++ b/src/os2/ownerdrw.cpp @@ -36,49 +36,61 @@ // implementation of wxOwnerDrawn class // ============================================================================ +// // ctor // ---- -wxOwnerDrawn::wxOwnerDrawn(const wxString& str, - bool bCheckable, bool bMenuItem) - : m_strName(str) +// +wxOwnerDrawn::wxOwnerDrawn( + const wxString& rsStr +, bool bCheckable +, bool bMenuItem +) +: m_strName(rsStr) { - m_bCheckable = bCheckable; - m_bOwnerDrawn = FALSE; - m_nHeight = 0; - m_nMarginWidth = ms_nLastMarginWidth; -} + m_bCheckable = bCheckable; + m_bOwnerDrawn = FALSE; + m_nHeight = 0; + m_nMarginWidth = ms_nLastMarginWidth; + if (wxNORMAL_FONT) + m_font = *wxNORMAL_FONT; +} // end of wxOwnerDrawn::wxOwnerDrawn - size_t wxOwnerDrawn::ms_nDefaultMarginWidth = 15; +size_t wxOwnerDrawn::ms_nDefaultMarginWidth = 15; size_t wxOwnerDrawn::ms_nLastMarginWidth = ms_nDefaultMarginWidth; -// drawing +// +// Drawing // ------- +// -// get size of the item -bool wxOwnerDrawn::OnMeasureItem(size_t *pwidth, size_t *pheight) +bool wxOwnerDrawn::OnMeasureItem( + size_t* pWidth +, size_t* pHeight +) { - wxMemoryDC dc; - dc.SetFont(GetFont()); + wxMemoryDC vDC; - // ## ugly... - wxChar *szStripped = new wxChar[m_strName.Len()]; - wxStripMenuCodes((wxChar *)m_strName.c_str(), szStripped); - wxString str = szStripped; - delete [] szStripped; + vDC.SetFont(GetFont()); - // # without this menu items look too tightly packed (at least under Windows) - str += wxT('W'); // 'W' is typically the widest letter + wxString sStr = wxStripMenuCodes(m_strName); - dc.GetTextExtent(str, (long *)pwidth, (long *)pheight); + // + // # without this menu items look too tightly packed (at least under Windows) + // + sStr += wxT('W'); // 'W' is typically the widest letter + vDC.GetTextExtent( sStr + ,(long *)pWidth + ,(long *)pHeight + ); - // JACS: items still look too tightly packed, so adding 2 pixels. - (*pheight) = (*pheight) + 2; - - m_nHeight = *pheight; // remember height for use in OnDrawItem - - return TRUE; -} + // + // JACS: items still look too tightly packed, so adding 2 pixels. + // + (*pHeight) = (*pHeight) + 2; + m_nHeight = *pHeight; // remember height for use in OnDrawItem + return TRUE; +} // end of wxOwnerDrawn::OnMeasureItem // searching for this macro you'll find all the code where I'm using the native // Win32 GDI functions and not wxWindows ones. Might help to whoever decides to @@ -89,108 +101,209 @@ bool wxOwnerDrawn::OnMeasureItem(size_t *pwidth, size_t *pheight) // embossing? // draw the item -bool wxOwnerDrawn::OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction act, wxODStatus st) +bool wxOwnerDrawn::OnDrawItem( + wxDC& rDC +, const wxRect& rRect +, wxODAction eAction +, wxODStatus eStatus +) { -/////////////////////////////////////////////////////////////////////////////////////////////////// -// Might want to check the native drawing apis for here and doo something like MSW does for WIN95 -/////////////////////////////////////////////////////////////////////////////////////////////////// + // + // For now we let PM deal with highlighting and framing and such in a + // default manner. So we leave fsAttribute and fsOldAttribute ( or + // fsState and fsOldState ) the same and pass it on. We may want to add + // code later to draw theseattributes in a more custom manner. + // - // we do nothing on focus change - if ( act == wxODFocusChanged ) - return TRUE; + // + // WxWinGdi_CColour <-> RGB + // + #define ToRGB(col) OS2RGB(col.Red(), col.Green(), col.Blue()) + #define UnRGB(col) GetRValue(col), GetGValue(col), GetBValue(col) - // wxColor <-> RGB - #define ToRGB(col) RGB(col.Red(), col.Green(), col.Blue()) - #define UnRGB(col) GetRValue(col), GetGValue(col), GetBValue(col) + CHARBUNDLE vCbndText; + CHARBUNDLE vCbndBack; + HPS hPS= rDC.GetHPS(); + ULONG lColBack; + ULONG lColText; - // set the colors - // -------------- - DWORD colBack, colText; -// TODO: -/* - if ( st & wxODSelected ) { - colBack = GetSysColor(COLOR_HIGHLIGHT); - colText = GetSysColor(COLOR_HIGHLIGHTTEXT); - } - else { - // fall back to default colors if none explicitly specified - colBack = m_colBack.Ok() ? ToRGB(m_colBack) : GetSysColor(COLOR_WINDOW); - colText = m_colText.Ok() ? ToRGB(m_colText) : GetSysColor(COLOR_WINDOWTEXT); - } -*/ -// dc.SetTextForeground(wxColor(UnRGB(colText))); -// dc.SetTextBackground(wxColor(UnRGB(colBack))); - - // select the font and draw the text - // --------------------------------- - - // determine where to draw and leave space for a check-mark. - int x = rc.x + GetMarginWidth(); - - dc.SetFont(GetFont()); - dc.DrawText(m_strName, x, rc.y); - - // draw the bitmap - // --------------- - if ( IsCheckable() && !m_bmpChecked.Ok() ) { - if ( st & wxODChecked ) { - // using native APIs for performance and simplicity -// TODO: -/* - HDC hdcMem = CreateCompatibleDC(hdc); - HBITMAP hbmpCheck = CreateBitmap(GetMarginWidth(), m_nHeight, 1, 1, 0); - SelectObject(hdcMem, hbmpCheck); - // then draw a check mark into it - RECT rect = { 0, 0, GetMarginWidth(), m_nHeight }; - - // finally copy it to screen DC and clean up - BitBlt(hdc, rc.x, rc.y, GetMarginWidth(), m_nHeight, - hdcMem, 0, 0, SRCCOPY); - DeleteDC(hdcMem); -*/ + if (eStatus & wxODSelected) + { + lColBack = (DWORD)::WinQuerySysColor( HWND_DESKTOP + ,SYSCLR_MENUHILITEBGND // Light gray + ,0L + ); + lColText = (DWORD)::WinQuerySysColor( HWND_DESKTOP + ,SYSCLR_MENUTEXT // Black + ,0L + ); } - } - else { - // for uncheckable item we use only the 'checked' bitmap - wxBitmap bmp(GetBitmap(IsCheckable() ? ((st & wxODChecked) != 0) : TRUE)); - if ( bmp.Ok() ) { - wxMemoryDC dcMem(&dc); - dcMem.SelectObject(bmp); - - // center bitmap - int nBmpWidth = bmp.GetWidth(), - nBmpHeight = bmp.GetHeight(); - - // there should be enough place! - wxASSERT((nBmpWidth <= rc.GetWidth()) && (nBmpHeight <= rc.GetHeight())); - - //MT: blit with mask enabled. -// TODO: -/* - dc.Blit(rc.x + (GetMarginWidth() - nBmpWidth) / 2, - rc.y + (m_nHeight - nBmpHeight) /2, - nBmpWidth, nBmpHeight, - &dcMem, 0, 0, wxCOPY,true); - - if ( st & wxODSelected ) { - #ifdef O_DRAW_NATIVE_API - RECT rectBmp = { rc.GetLeft(), rc.GetTop(), - rc.GetLeft() + GetMarginWidth(), - rc.GetTop() + m_nHeight }; - SetBkColor(hdc, colBack); - DrawEdge(hdc, &rectBmp, EDGE_RAISED, BF_SOFT | BF_RECT); - } -*/ + else if (eStatus & wxODDisabled) + { + lColBack = (DWORD)::WinQuerySysColor( HWND_DESKTOP + ,SYSCLR_MENU // Light gray + ,0L + ); + lColText = (DWORD)::WinQuerySysColor( HWND_DESKTOP + ,SYSCLR_MENUDISABLEDTEXT // dark gray + ,0L + ); + } + else + { + // + // Fall back to default colors if none explicitly specified + // + lColBack = m_colBack.Ok() ? ToRGB(m_colBack) : ::WinQuerySysColor( HWND_DESKTOP + ,SYSCLR_MENU // we are using gray for all our window backgrounds in wxWindows + ,0L + ); + lColText = m_colText.Ok() ? ToRGB(m_colText) : ::WinQuerySysColor( HWND_DESKTOP + ,SYSCLR_WINDOWTEXT // Black + ,0L + ); + } + vCbndText.lColor = (LONG)lColText; + vCbndBack.lColor = (LONG)lColBack; + + ::GpiSetAttrs( hPS + ,PRIM_CHAR + ,CBB_BACK_COLOR + ,0 + ,&vCbndBack + ); + ::GpiSetAttrs( hPS + ,PRIM_CHAR + ,CBB_COLOR + ,0 + ,&vCbndText + ); + + + // + // Determine where to draw and leave space for a check-mark. + // + int nX = rRect.x + GetMarginWidth(); + + // + // Select the font and draw the text + // --------------------------------- + // + + // + // Use default font if no font set + // + if (m_font.Ok()) + { + m_font.RealizeResource(); + } + else + { + ::GpiSetCharSet(hPS, LCID_DEFAULT); + } + + // + // Unfortunately, unlike Win32, PM has no owner drawn specific text + // 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. + + rDC.DrawText( m_strName + ,nX + ,rRect.y + ); + + // + // Draw the bitmap + // --------------- + // + if (IsCheckable() && !m_bmpChecked.Ok()) + { + if (eStatus & wxODChecked) + { + RECTL vRect; + HBITMAP hBmpCheck = ::WinGetSysBitmap(HWND_DESKTOP, SBMP_MENUCHECK); + + vRect.xLeft = rRect.x; + vRect.xRight = rRect.x + GetMarginWidth(); + vRect.yBottom = rRect.y; + vRect.yTop = rRect.y + m_nHeight; + + ::WinDrawBitmap( hPS // PS for this menuitem + ,hBmpCheck // system checkmark + ,NULL // draw the whole bitmap + ,(PPOINTL)&vRect // destination -- bottom left corner of the menuitem area + ,0L // ignored + ,0L // draw a bitmap + ,DBM_NORMAL // draw normal size + ); + } + } + else + { + // + // For uncheckable item we use only the 'checked' bitmap + // + wxBitmap vBmp(GetBitmap(IsCheckable() ? ((eStatus & wxODChecked) != 0) : TRUE)); + + if (vBmp.Ok()) + { + wxMemoryDC vDCMem(&rDC); + + vDCMem.SelectObject(vBmp); + + // + // Center bitmap + // + int nBmpWidth = vBmp.GetWidth(); + int nBmpHeight = vBmp.GetHeight(); + + // + // There should be enough space! + // + wxASSERT((nBmpWidth <= rRect.width) && (nBmpHeight <= rRect.height)); + + // + //MT: blit with mask enabled. + // + rDC.Blit( rRect.x + (GetMarginWidth() - nBmpWidth) / 2 + ,rRect.y + (m_nHeight - nBmpHeight) /2 + ,nBmpWidth + ,nBmpHeight + ,&vDCMem + ,0 + ,0 + ,wxCOPY + ,TRUE + ); + + if (eStatus & wxODSelected) + { + RECT vRectBmp = { rRect.x + ,rRect.y + ,rRect.x + GetMarginWidth() + ,rRect.y + m_nHeight + }; + LINEBUNDLE vLine; + + vLine.lColor = lColBack; + ::GpiSetAttrs( hPS + ,PRIM_LINE + ,LBB_COLOR + ,0 + ,&vLine + ); + ::GpiBox( hPS + ,DRO_OUTLINE + ,(PPOINTL)&vRectBmp + ,0L + ,0L + ); + } + } } - } -/* - #ifdef O_DRAW_NATIVE_API - ::SetTextColor(hdc, colOldText); - ::SetBkColor(hdc, colOldBack); - #undef hdc - #endif //O_DRAW_NATIVE_API -*/ return TRUE; } diff --git a/src/os2/window.cpp b/src/os2/window.cpp index eda3bf9747..ce16cbc0c7 100644 --- a/src/os2/window.cpp +++ b/src/os2/window.cpp @@ -2654,78 +2654,113 @@ bool wxWindow::OS2OnDrawItem( , WXDRAWITEMSTRUCT* pItemStruct ) { - // - // I'll get to owner drawn stuff later - // + wxDC vDc; // - // is it a menu item or control? + // Is it a menu item? // - wxWindow* pItem = FindItem(vId); + if (vId == 0) + { #if wxUSE_OWNER_DRAWN + POWNERITEM pMeasureStruct = (POWNERITEM)pItemStruct; + wxMenuItem vMenuItem; + HDC hDC = ::GpiQueryDevice(pMeasureStruct->hps); + + vDc.SetHDC( hDC + ,FALSE + ); + vDc.SetHPS(pMeasureStruct->hps); + + // + // We stored the CMenuItem itself into the menuitem text field so now + // we need to extract it. + // + ::WinSendMsg( pMeasureStruct->hItem + ,MM_QUERYITEMTEXT + ,MPFROM2SHORT( (USHORT)pMeasureStruct->idItem + ,(SHORT)(sizeof(wxMenuItem)) + ) + ,(PSZ)&vMenuItem + ); + + wxRect vRect( pMeasureStruct->rclItem.xLeft + ,pMeasureStruct->rclItem.yTop + ,pMeasureStruct->rclItem.xRight + ,pMeasureStruct->rclItem.yBottom + ); + + wxOwnerDrawn::wxODAction eAction; + + // + // Attribute applies to menuitems, fsState to listbox and other controls + // + if (pMeasureStruct->fsAttribute == pMeasureStruct->fsAttributeOld) + eAction = wxOwnerDrawn::wxODDrawAll; + else + eAction = wxOwnerDrawn::wxODSelectChanged; + + return(vMenuItem.OnDrawItem( vDc + ,vRect + ,eAction + ,(wxOwnerDrawn::wxODStatus)pMeasureStruct->fsAttribute + )); + // + // leave the fsAttribute and fsOldAttribute unchanged. If different, + // the system will do the highlight or fraeming or disabling for us, + // otherwise, we'd have to do it ourselves. + // + } + + wxWindow* pItem = FindItem(vId); + if (pItem && pItem->IsKindOf(CLASSINFO(wxControl))) { return ((wxControl *)pItem)->OS2OnDraw(pItemStruct); } - else if (pItem && pItem->IsKindOf(CLASSINFO(wxMenu))) - { - /* - // TODO: draw a menu item - // - POWNERITEM pDrawStruct = (OWNERITEM *)pItemStruct; - wxMenuItem* pMenuItem = (wxMenuItem *)(pDrawStruct->pItemData); - - wxCHECK(pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE); - - // - // Prepare to call OnDrawItem() - // - HPSdc; - dc.SetHDC((WXHDC)pDrawStruct->hDC, FALSE); - wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top, - pDrawStruct->rcItem.right - pDrawStruct->rcItem.left, - pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top); - - return pMenuItem->OnDrawItem - ( - dc, rect, - (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction, - (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState - ); - */ - } - - else - return FALSE; #endif - return TRUE; + return FALSE; } // end of wxWindow::OS2OnDrawItem -bool wxWindow::OS2OnMeasureItem(int id, WXMEASUREITEMSTRUCT *itemStruct) +bool wxWindow::OS2OnMeasureItem( + int lId +, WXMEASUREITEMSTRUCT* pItemStruct +) { - // TODO: more owner drawn menu related stuff, get to it later -/* -#if wxUSE_OWNER_DRAWN - // is it a menu item? - if ( id == 0 ) + // + // Is it a menu item? + // + if (lId == 0) { - MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct; - wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData); + POWNERITEM pMeasureStruct = (POWNERITEM)pItemStruct; + wxMenuItem vMenuItem; - wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE ); + // + // We stored the CMenuItem itself into the menuitem text field so now + // we need to extract it. + // + ::WinSendMsg( pMeasureStruct->hItem + ,MM_QUERYITEMTEXT + ,MPFROM2SHORT( (USHORT)pMeasureStruct->idItem + ,(SHORT)(sizeof(wxMenuItem)) + ) + ,(PSZ)&vMenuItem + ); + wxCHECK(vMenuItem.IsKindOf(CLASSINFO(wxMenuItem)), FALSE); - return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth, - &pMeasureStruct->itemHeight); + size_t lWidth = (size_t)(pMeasureStruct->rclItem.xRight - pMeasureStruct->rclItem.xLeft); + size_t lHeight = (size_t)(pMeasureStruct->rclItem.yTop - pMeasureStruct->rclItem.yBottom); + + return(vMenuItem.OnMeasureItem( &lWidth + ,&lHeight + )); } + wxWindow* pItem = FindItem(id); - wxWindow *item = FindItem(id); - if ( item && item->IsKindOf(CLASSINFO(wxControl)) ) + if (pItem && pItem->IsKindOf(CLASSINFO(wxControl))) { - return ((wxControl *)item)->MSWOnMeasure(itemStruct); + return ((wxControl *)pItem)->OS2OnMeasure(pItemStruct); } -#endif // owner-drawn menus -*/ return FALSE; }