void cSettingsDialog::LayoutAndSetWindowSize() { int iX = GetMarginWidth(); int iY = GetMarginHeight(); // Find the widest static text const int widestStaticText = max(max(MeasureStaticTextWidth(historyStaticClearFolders.GetHandle()), MeasureStaticTextWidth(historyStaticClearCache.GetHandle())), MeasureStaticTextWidth(historyStaticCacheSize.GetHandle())); // Find the widest row of controls on the right const int widthRowClearFolders = MeasureButtonWidth(historyStaticClearFolders.GetHandle()); const int widthRowClearCache = MeasureButtonWidth(buttonHistoryClearCache.GetHandle()); const int widthCacheGB = MeasureStaticTextWidth(historyStaticGB.GetHandle()); const int widestRowOnTheRight = max(widthRowClearFolders, widthRowClearCache); const int widthCacheMaximumSize = widestRowOnTheRight - (GetSpacerWidth() + widthCacheGB); const int widthControls = widestStaticText + GetSpacerWidth() + widestRowOnTheRight; const int widthHistoryText = MeasureStaticTextWidth(lineHistory.GetStaticTextHandle()); const int widthHistoryLine = widthControls - (widthHistoryText + GetSpacerWidth()); const int heightHistoryLine = MeasureStaticTextHeight(lineHistory.GetStaticTextHandle(), widthHistoryLine); MoveControl(lineHistory.GetStaticTextHandle(), iX, iY, widthHistoryText, heightHistoryLine); MoveControl(lineHistory.GetLineHandle(), iX + widthHistoryText + GetSpacerWidth(), iY + (heightHistoryLine / 2), widthHistoryLine, 1); iY += heightHistoryLine + GetSpacerHeight(); MoveControlStaticNextToOtherControls(historyStaticClearFolders.GetHandle(), iX, iY, widestStaticText); MoveControl(buttonHistoryClearFolders.GetHandle(), iX + widestStaticText + GetSpacerWidth(), iY, widestRowOnTheRight, GetButtonHeight()); iY += GetButtonHeight() + GetSpacerHeight(); MoveControlStaticNextToOtherControls(historyStaticClearCache.GetHandle(), iX, iY, widestStaticText); MoveControl(buttonHistoryClearCache.GetHandle(), iX + widestStaticText + GetSpacerWidth(), iY, widestRowOnTheRight, GetButtonHeight()); iY += GetButtonHeight() + GetSpacerHeight(); MoveControlStaticNextToOtherControls(historyStaticCacheSize.GetHandle(), iX, iY, widestStaticText); MoveControlInputUpDown(historyCacheMaximumSizeGB, iX + widestStaticText + GetSpacerWidth(), iY, widthCacheMaximumSize); MoveControlStaticNextToOtherControls(historyStaticGB.GetHandle(), iX + widestStaticText + GetSpacerWidth() + widthCacheMaximumSize + GetSpacerWidth(), iY, widthCacheGB); iY += GetInputHeight() + GetSpacerHeight(); const int iWidth = widestStaticText + GetSpacerWidth() + widestRowOnTheRight; MoveControl(horizontalLine.GetLineHandle(), iX, iY, iWidth, 1); iY += 1 + GetSpacerHeight(); const int iDialogWidth = GetMarginWidth() + iWidth + GetMarginWidth(); const int iDialogHeight = iY + GetButtonHeight() + GetMarginHeight(); MoveOkCancelHelp(iDialogWidth, iDialogHeight); // Set our window size now that we know how big it should be SetClientSize(iDialogWidth, iDialogHeight); }
void DisplayCaret( LPCLASSDATA lpcd, BOOL bShow ) { /* * Only when we have the focus. */ if ( lpcd->bHasFocus == FALSE ) return; /* * Anything changed? */ if ( bShow != lpcd->bCaretVisible ) { /* * Change it. */ if (( lpcd->bCaretVisible = bShow ) == TRUE ) { int cy = ( Parser->nCaretType == CARET_HORIZONTAL && ! lpcd->bOverwrite ) ? Parser->szCharSize.cy - ( 2 * GetSystemMetrics( SM_CYBORDER )) : 0; SetCaretPos( GetMarginWidth( lpcd ) + GetLineMarginWidth( lpcd ) + (( GetCaretOffset( lpcd, lpcd->ptCaretPos.x ) - lpcd->ptViewPos.x ) * Parser->szCharSize.cx ), ( lpcd->ptCaretPos.y - lpcd->ptViewPos.y ) * Parser->szCharSize.cy + cy ); ShowCaret( lpcd->hWnd ); } else HideCaret( lpcd->hWnd ); } /* * Send caret position message. */ SendCaretMessage( lpcd ); }
void ctlSQLBox::UpdateLineNumber() { bool showlinenumber; settings->Read(wxT("frmQuery/ShowLineNumber"), &showlinenumber, false); if (showlinenumber) { long int width = TextWidth(wxSTC_STYLE_LINENUMBER, wxT(" ")+NumToStr((long int)GetLineCount())+wxT(" ")); if (width != GetMarginWidth(0)) SetMarginWidth(0, width); } else { SetMarginWidth(0, 0); } }
void wxMenuItem::Init() { #if wxUSE_OWNER_DRAWN // when the color is not valid, wxOwnerDraw takes the default ones. // If we set the colors here and they are changed by the user during // the execution, then the colors are not updated until the application // is restarted and our menus look bad SetTextColour(wxNullColour); SetBackgroundColour(wxNullColour); // setting default colors switched ownerdraw on: switch it off again SetOwnerDrawn(false); // switch ownerdraw back on if using a non default margin if ( !IsSeparator() ) SetMarginWidth(GetMarginWidth()); #endif // wxUSE_OWNER_DRAWN }
void UpdateCaret( LPCLASSDATA lpcd ) { /* * Do we have the focus? */ if ( lpcd->bHasFocus == TRUE || lpcd->bDragOver == TRUE ) { /* * Caret inside the view? */ if ( CaretInView( lpcd )) { /* * Already visible? */ if ( lpcd->bCaretVisible == FALSE ) /* * No make it visible. */ DisplayCaret( lpcd, TRUE ); else { /* * Re-position. */ int cy = ( Parser->nCaretType == CARET_HORIZONTAL && ! lpcd->bOverwrite ) ? Parser->szCharSize.cy - ( 2 * GetSystemMetrics( SM_CYBORDER )) : 0; SetCaretPos( GetMarginWidth( lpcd ) + GetLineMarginWidth( lpcd ) + (( GetCaretOffset( lpcd, lpcd->ptCaretPos.x ) - lpcd->ptViewPos.x ) * Parser->szCharSize.cx ), ( lpcd->ptCaretPos.y - lpcd->ptViewPos.y ) * Parser->szCharSize.cy + cy ); } } else if ( lpcd->bCaretVisible == TRUE ) /* * Hide the caret. */ DisplayCaret( lpcd, FALSE ); } /* * Send caret position message. */ SendCaretMessage( lpcd ); }
void SvnBlameEditor::OnContextMenu(wxContextMenuEvent& event) { wxPoint pt = event.GetPosition(); wxPoint clientPt = ScreenToClient(pt); int margin = GetMarginWidth(0); // get the margin width if ( clientPt.x < margin ) { GotoPos( PositionFromPoint(clientPt) ); // Margin context menu wxMenu menu; menu.Append( XRCID("svn_highlight_revision"), _("Highlight this revision"), _("Highlight this revision"), false); menu.Connect(XRCID("svn_highlight_revision"), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(SvnBlameEditor::OnHighlightRevision), NULL, this); PopupMenu(&menu); } else { wxStyledTextCtrl::OnContextMenu(event); } }
void CCrystalEditView::DoDragScroll(const CPoint &point) { CRect rcClientRect; GetClientRect(rcClientRect); if (point.y < rcClientRect.top + DRAG_BORDER_Y) { HideDropIndicator(); ScrollUp(); UpdateWindow(); ShowDropIndicator(point); return; } if (point.y >= rcClientRect.bottom - DRAG_BORDER_Y) { HideDropIndicator(); ScrollDown(); UpdateWindow(); ShowDropIndicator(point); return; } if (point.x < rcClientRect.left + GetMarginWidth() + DRAG_BORDER_X) { HideDropIndicator(); ScrollLeft(); UpdateWindow(); ShowDropIndicator(point); return; } if (point.x >= rcClientRect.right - DRAG_BORDER_X) { HideDropIndicator(); ScrollRight(); UpdateWindow(); ShowDropIndicator(point); return; } }
/* * Check is the mouse position is located * on a hyperlink. */ BOOL MouseOnHyperLink( LPCLASSDATA lpcd ) { POINT ptMousePos; /* * Are we parsing hyperlinks? */ if ( Parser->bParseHyperLinks ) { /* * Get mouse position and convert * to client coordinates. */ GetCursorPos( &ptMousePos ); ScreenToClient( lpcd->hWnd, &ptMousePos ); /* * Skip selection margin. */ ptMousePos.x -= ( GetMarginWidth( lpcd ) + GetLineMarginWidth( lpcd )); return PointOnHyperlink( lpcd, ptMousePos.x, ptMousePos.y ); } return FALSE; }
void CodeEditor::OnLineNumber(wxCommandEvent &WXUNUSED(event)) { SetMarginWidth(mLineNumID, GetMarginWidth(mLineNumID) == 0 ? mLineNumMargin : 0); }
void Edit::OnLineNumber (wxCommandEvent &WXUNUSED(event)) { SetMarginWidth (m_LineNrID, GetMarginWidth (m_LineNrID) == 0? m_LineNrMargin: 0); }
// draw the item bool wxOwnerDrawn::OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction, wxODStatus stat) { // we do nothing if item isn't ownerdrawn if ( !IsOwnerDrawn() ) return true; wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); HDC hdc = GetHdcOf(*impl); RECT rect; wxCopyRectToRECT(rc, rect); { // set the font and colors wxFont font; GetFontToUse(font); wxColour colText, colBack; GetColourToUse(stat, colText, colBack); SelectInHDC selFont(hdc, GetHfontOf(font)); wxMSWImpl::wxTextColoursChanger textCol(hdc, colText, colBack); wxMSWImpl::wxBkModeChanger bkMode(hdc, wxBRUSHSTYLE_TRANSPARENT); AutoHBRUSH hbr(wxColourToPalRGB(colBack)); SelectInHDC selBrush(hdc, hbr); ::FillRect(hdc, &rect, hbr); // using native API because it recognizes '&' wxString text = GetName(); SIZE sizeRect; ::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &sizeRect); int flags = DST_PREFIXTEXT; if ( (stat & wxODDisabled) && !(stat & wxODSelected) ) flags |= DSS_DISABLED; if ( (stat & wxODHidePrefix) ) flags |= DSS_HIDEPREFIX; int x = rc.x + GetMarginWidth(); int y = rc.y + (rc.GetHeight() - sizeRect.cy) / 2; int cx = rc.GetWidth() - GetMarginWidth(); int cy = sizeRect.cy; ::DrawState(hdc, NULL, NULL, wxMSW_CONV_LPARAM(text), text.length(), x, y, cx, cy, flags); } // reset to default the font, colors and brush if (stat & wxODHasFocus) ::DrawFocusRect(hdc, &rect); return true; }
bool wxMenuItem::OnDrawItem( wxDC& rDC, const wxRect& rRect, wxODAction eAction, wxODStatus eStatus ) { // // Select the font and draw the text // --------------------------------- // CHARBUNDLE vCbnd; wxPMDCImpl *impl = (wxPMDCImpl*) rDC.GetImpl(); HPS hPS= impl->GetHPS(); wxFont vFont; wxColour vColBack; wxColour vColText; COLORREF vRef; RECTL vRect = {rRect.x + 4, rRect.y + 1, rRect.x + (rRect.width - 2), rRect.y + rRect.height}; memset(&vCbnd, 0, sizeof(CHARBUNDLE)); GetFontToUse(vFont); GetColourToUse(eStatus, vColText, vColBack); rDC.SetFont(vFont); rDC.SetTextBackground(vColBack); rDC.SetTextForeground(vColText); rDC.SetBackgroundMode(wxTRANSPARENT); vCbnd.lColor = vColText.GetPixel(); vCbnd.lBackColor = vColBack.GetPixel(); ::GpiSetAttrs( hPS ,PRIM_CHAR ,CBB_BACK_COLOR | CBB_COLOR ,0 ,&vCbnd ); ::GpiSetBackMix( hPS ,BM_LEAVEALONE ); // // Paint the background // ::WinFillRect(hPS, &vRect, vColBack.GetPixel()); // // Determine where to draw and leave space for a check-mark. // int nX = rRect.x + GetMarginWidth(); // // Unfortunately, unlike Win32, PM has no owner drawn specific text // drawing methods like ::DrawState that can cleanly handle accel // mnemonics and deal, automatically, with various states, so we have // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn // strings either. We cannot handle mnemonics either. We display // them, though, in the hope we can figure them out some day. // // // Display main text and accel text separately to align better // wxString sTgt = wxT("\t"); wxString sFullString = GetItemLabel(); // need to save the original text wxString sAccel; int nIndex; size_t nWidth; size_t nCharWidth; size_t nHeight; bool bFoundMnemonic = false; bool bFoundAccel = false; // // Deal with the tab, extracting the Accel text // nIndex = sFullString.Find(sTgt); if (nIndex != -1) { bFoundAccel = true; sAccel = sFullString.Mid(nIndex + 1); sFullString.Remove(nIndex); } // // Deal with the mnemonic character // sTgt = wxT("~"); nIndex = sFullString.Find(sTgt); if (nIndex != -1) { wxString sTmp = sFullString; bFoundMnemonic = true; sTmp.Remove(nIndex); rDC.GetTextExtent( sTmp ,(wxCoord *)&nWidth ,(wxCoord *)&nHeight ); sTmp = sFullString[(size_t)(nIndex + 1)]; rDC.GetTextExtent( sTmp ,(wxCoord *)&nCharWidth ,(wxCoord *)&nHeight ); sFullString.Replace(sTgt.c_str(), wxEmptyString, true); } // // Draw the main item text sans the accel text // POINTL vPntStart = {nX, rRect.y + 4}; ::GpiCharStringAt( impl->GetHPS() ,&vPntStart ,sFullString.length() ,sFullString.char_str() ); if (bFoundMnemonic) { // // Underline the mnemonic -- still won't work, but at least it "looks" right // wxPen vPen; POINTL vPntEnd = {nX + nWidth + nCharWidth - 3, rRect.y + 2}; //CharWidth is bit wide vPntStart.x = nX + nWidth - 1; vPntStart.y = rRect.y + 2; // Make it look pretty! vPen = wxPen(vColText, 1, wxSOLID); // Assuming we are always black rDC.SetPen(vPen); ::GpiMove(hPS, &vPntStart); ::GpiLine(hPS, &vPntEnd); } // // Now draw the accel text // if (bFoundAccel) { size_t nWidth; size_t nHeight; rDC.GetTextExtent( sAccel ,(wxCoord *)&nWidth ,(wxCoord *)&nHeight ); // // Back off the starting position from the right edge // vPntStart.x = rRect.width - (nWidth + 7); vPntStart.y = rRect.y + 4; ::GpiCharStringAt( impl->GetHPS() ,&vPntStart ,sAccel.length() ,sAccel.char_str() ); } // // Draw the bitmap // --------------- // if (IsCheckable() && !m_bmpChecked.IsOk()) { 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 - 3; ::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.IsOk()) { wxMemoryDC vDCMem(&rDC); wxMemoryDC* pOldDC = (wxMemoryDC*)vBmp.GetSelectedInto(); if(pOldDC != NULL) { vBmp.SetSelectedInto(NULL); } 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)); int nHeightDiff = m_nHeight - nBmpHeight; rDC.Blit( rRect.x + (GetMarginWidth() - nBmpWidth) / 2 ,rRect.y + nHeightDiff / 2 ,nBmpWidth ,nBmpHeight ,&vDCMem ,0 ,0 ,wxCOPY ,true ); if (eStatus & wxODSelected) { POINTL vPnt1 = {rRect.x + 1, rRect.y + 3}; // Leave a little background border POINTL vPnt2 = {rRect.x + GetMarginWidth(), rRect.y + m_nHeight - 3}; LINEBUNDLE vLine; vLine.lColor = vColBack.GetPixel(); ::GpiSetAttrs( hPS ,PRIM_LINE ,LBB_COLOR ,0 ,&vLine ); ::GpiMove(hPS, &vPnt1); ::GpiBox( hPS ,DRO_OUTLINE ,&vPnt2 ,0L ,0L ); } vBmp.SetSelectedInto(NULL); } } return true; } // end of wxOwnerDrawn::OnDrawItem
bool wxMenuItem::OnMeasureItem( size_t* pWidth, size_t* pHeight ) { wxMemoryDC vDC; wxString sStr = GetName(); // // If we have a valid accel string, then pad out // the menu string so that the menu and accel string are not // placed on top of each other. wxString accel = GetItemLabel().AfterFirst(wxT('\t')); if (!accel.empty() ) { sStr.Pad(sStr.length()%8); sStr += accel; } vDC.SetFont(GetFont()); vDC.GetTextExtent( sStr ,(wxCoord *)pWidth ,(wxCoord *)pHeight ); if (!accel.empty()) { // // Measure the accelerator string, and add its width to // the total item width, plus 16 (Accelerators are right justified, // with the right edge of the text rectangle 16 pixels left of // the right edge of the menu) // int nAccelWidth; int nAccelHeight; vDC.GetTextExtent( m_strAccel ,&nAccelWidth ,&nAccelHeight ); *pWidth += nAccelWidth; } // // Add space at the end of the menu for the submenu expansion arrow. // This will also allow offsetting the accel string from the right edge // *pWidth = (size_t)(*pWidth + GetDefaultMarginWidth() * 1.5); // // JACS: items still look too tightly packed, so adding 5 pixels. // (*pHeight) += 5; // // Ray Gilbert's changes - Corrects the problem of a BMP // being placed next to text in a menu item, and the BMP does // not match the size expected by the system. This will // resize the space so the BMP will fit. Without this, BMPs // must be no larger or smaller than 16x16. // if (m_bmpChecked.IsOk()) { // // Is BMP height larger than text height? // size_t nAdjustedHeight = m_bmpChecked.GetHeight() + wxSystemSettings::GetMetric(wxSYS_EDGE_Y); if (*pHeight < nAdjustedHeight) *pHeight = nAdjustedHeight; // // Does BMP encroach on default check menu position? // size_t nAdjustedWidth = m_bmpChecked.GetWidth() + (wxSystemSettings::GetMetric(wxSYS_EDGE_X) * 2); // // Do we need to widen margin to fit BMP? // if ((size_t)GetMarginWidth() < nAdjustedWidth) SetMarginWidth(nAdjustedWidth); // // Add the size of the bitmap to our total size... // *pWidth += GetMarginWidth(); } // // Add the size of the bitmap to our total size - even if we don't have // a bitmap we leave room for one... // *pWidth += GetMarginWidth(); // // Make sure that this item is at least as // tall as the user's system settings specify // const size_t heightStd = 6; // FIXME: get value from the system if ( *pHeight < heightStd ) *pHeight = heightStd; m_nHeight = *pHeight; // remember height for use in OnDrawItem return true; } // end of wxOwnerDrawn::OnMeasureItem
bool wxMenuItem::OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction WXUNUSED(act), wxODStatus stat) { const MenuDrawData* data = MenuDrawData::Get(); wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); HDC hdc = GetHdcOf(*impl); RECT rect; wxCopyRectToRECT(rc, rect); int imgWidth = wxMax(GetMarginWidth(), data->CheckSize.cx); if ( IsOwnerDrawn() ) { // font and colors to use wxFont font; GetFontToUse(font); wxColour colText, colBack; GetColourToUse(stat, colText, colBack); // calculate metrics of item parts RECT rcSelection = rect; data->ItemMargin.ApplyTo(rcSelection); RECT rcSeparator = rcSelection; data->SeparatorMargin.ApplyTo(rcSeparator); RECT rcGutter = rcSelection; rcGutter.right = data->ItemMargin.cxLeftWidth + data->CheckBgMargin.cxLeftWidth + data->CheckMargin.cxLeftWidth + imgWidth + data->CheckMargin.cxRightWidth + data->CheckBgMargin.cxRightWidth; RECT rcText = rcSelection; rcText.left = rcGutter.right + data->TextBorder; // we draw the text label vertically centered, but this results in it // being 1px too low compared to native menus for some reason, fix it if ( data->MenuLayout() != MenuDrawData::FullTheme ) rcText.top--; #if wxUSE_UXTHEME // If a custom background colour is explicitly specified, we should use // it instead of the default theme background. wxUxThemeEngine* const theme = GetBackgroundColour().IsOk() ? NULL : MenuDrawData::GetUxThemeEngine(); if ( theme ) { POPUPITEMSTATES state; if ( stat & wxODDisabled ) { state = (stat & wxODSelected) ? MPI_DISABLEDHOT : MPI_DISABLED; } else if ( stat & wxODSelected ) { state = MPI_HOT; } else { state = MPI_NORMAL; } wxUxThemeHandle hTheme(GetMenu()->GetWindow(), L"MENU"); if ( theme->IsThemeBackgroundPartiallyTransparent(hTheme, MENU_POPUPITEM, state) ) { theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPBACKGROUND, 0, &rect, NULL); } theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPGUTTER, 0, &rcGutter, NULL); if ( IsSeparator() ) { rcSeparator.left = rcGutter.right; theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPSEPARATOR, 0, &rcSeparator, NULL); return true; } theme->DrawThemeBackground(hTheme, hdc, MENU_POPUPITEM, state, &rcSelection, NULL); } else #endif // wxUSE_UXTHEME { if ( IsSeparator() ) { DrawEdge(hdc, &rcSeparator, EDGE_ETCHED, BF_TOP); return true; } AutoHBRUSH hbr(colBack.GetPixel()); SelectInHDC selBrush(hdc, hbr); ::FillRect(hdc, &rcSelection, hbr); } // draw text label // using native API because it recognizes '&' HDCTextColChanger changeTextCol(hdc, colText.GetPixel()); HDCBgColChanger changeBgCol(hdc, colBack.GetPixel()); HDCBgModeChanger changeBgMode(hdc, TRANSPARENT); SelectInHDC selFont(hdc, GetHfontOf(font)); // item text name without mnemonic for calculating size wxString text = GetName(); SIZE textSize; ::GetTextExtentPoint32(hdc, text.c_str(), text.length(), &textSize); // item text name with mnemonic text = GetItemLabel().BeforeFirst('\t'); int flags = DST_PREFIXTEXT; // themes menu is using specified color for disabled labels if ( data->MenuLayout() == MenuDrawData::Classic && (stat & wxODDisabled) && !(stat & wxODSelected) ) flags |= DSS_DISABLED; if ( (stat & wxODHidePrefix) && !data->AlwaysShowCues ) flags |= DSS_HIDEPREFIX; int x = rcText.left; int y = rcText.top + (rcText.bottom - rcText.top - textSize.cy) / 2; ::DrawState(hdc, NULL, NULL, wxMSW_CONV_LPARAM(text), text.length(), x, y, 0, 0, flags); // ::SetTextAlign(hdc, TA_RIGHT) doesn't work with DSS_DISABLED or DSS_MONO // as the last parameter in DrawState() (at least with Windows98). So we have // to take care of right alignment ourselves. wxString accel = GetItemLabel().AfterFirst(wxT('\t')); if ( !accel.empty() ) { SIZE accelSize; ::GetTextExtentPoint32(hdc, accel.c_str(), accel.length(), &accelSize); flags = DST_TEXT; // themes menu is using specified color for disabled labels if ( data->MenuLayout() == MenuDrawData::Classic && (stat & wxODDisabled) && !(stat & wxODSelected) ) flags |= DSS_DISABLED; x = rcText.right - data->ArrowMargin.GetTotalX() - data->ArrowSize.cx - data->ArrowBorder; // right align accel on FullTheme menu, left otherwise if ( data->MenuLayout() == MenuDrawData::FullTheme) x -= accelSize.cx; else x -= m_parentMenu->GetMaxAccelWidth(); y = rcText.top + (rcText.bottom - rcText.top - accelSize.cy) / 2; ::DrawState(hdc, NULL, NULL, wxMSW_CONV_LPARAM(accel), accel.length(), x, y, 0, 0, flags); } } // draw the bitmap RECT rcImg; SetRect(&rcImg, rect.left + data->ItemMargin.cxLeftWidth + data->CheckBgMargin.cxLeftWidth + data->CheckMargin.cxLeftWidth, rect.top + data->ItemMargin.cyTopHeight + data->CheckBgMargin.cyTopHeight + data->CheckMargin.cyTopHeight, rect.left + data->ItemMargin.cxLeftWidth + data->CheckBgMargin.cxLeftWidth + data->CheckMargin.cxLeftWidth + imgWidth, rect.bottom - data->ItemMargin.cyBottomHeight - data->CheckBgMargin.cyBottomHeight - data->CheckMargin.cyBottomHeight); if ( IsCheckable() && !m_bmpChecked.IsOk() ) { if ( stat & wxODChecked ) { DrawStdCheckMark((WXHDC)hdc, &rcImg, stat); } } else { wxBitmap bmp; if ( stat & wxODDisabled ) { bmp = GetDisabledBitmap(); } if ( !bmp.IsOk() ) { // for not checkable bitmaps we should always use unchecked one // because their checked bitmap is not set bmp = GetBitmap(!IsCheckable() || (stat & wxODChecked)); #if wxUSE_IMAGE if ( bmp.IsOk() && stat & wxODDisabled ) { // we need to grey out the bitmap as we don't have any specific // disabled bitmap wxImage imgGrey = bmp.ConvertToImage().ConvertToGreyscale(); if ( imgGrey.IsOk() ) bmp = wxBitmap(imgGrey); } #endif // wxUSE_IMAGE } if ( bmp.IsOk() ) { wxMemoryDC dcMem(&dc); dcMem.SelectObjectAsSource(bmp); // center bitmap int nBmpWidth = bmp.GetWidth(), nBmpHeight = bmp.GetHeight(); int x = rcImg.left + (imgWidth - nBmpWidth) / 2; int y = rcImg.top + (rcImg.bottom - rcImg.top - nBmpHeight) / 2; dc.Blit(x, y, nBmpWidth, nBmpHeight, &dcMem, 0, 0, wxCOPY, true); } } return true; }
bool wxMenuItem::OnMeasureItem(size_t *width, size_t *height) { const MenuDrawData* data = MenuDrawData::Get(); if ( IsOwnerDrawn() ) { *width = data->ItemMargin.GetTotalX(); *height = data->ItemMargin.GetTotalY(); if ( IsSeparator() ) { *width += data->SeparatorSize.cx + data->SeparatorMargin.GetTotalX(); *height += data->SeparatorSize.cy + data->SeparatorMargin.GetTotalY(); return true; } wxString str = GetName(); wxMemoryDC dc; wxFont font; GetFontToUse(font); dc.SetFont(font); wxCoord w, h; dc.GetTextExtent(str, &w, &h); *width = data->TextBorder + w + data->AccelBorder; *height = h; w = m_parentMenu->GetMaxAccelWidth(); if ( w > 0 ) *width += w + data->ArrowBorder; *width += data->Offset; *width += data->ArrowMargin.GetTotalX() + data->ArrowSize.cx; } else // don't draw the text, just the bitmap (if any) { *width = 0; *height = 0; } // bitmap if ( IsOwnerDrawn() ) { // width of menu icon with margins in ownerdrawn menu // if any bitmap is not set, the width of space reserved for icon // image is equal to the width of std check mark, // if bitmap is set, then the width is set to the width of the widest // bitmap in menu (GetMarginWidth()) unless std check mark is wider, // then it's is set to std mark's width int imgWidth = wxMax(GetMarginWidth(), data->CheckSize.cx) + data->CheckMargin.GetTotalX(); *width += imgWidth + data->CheckBgMargin.GetTotalX(); } if ( m_bmpChecked.IsOk() || m_bmpUnchecked.IsOk() ) { // get size of bitmap always return valid value (0 for invalid bitmap), // so we don't needed check if bitmap is valid ;) size_t heightBmp = wxMax(m_bmpChecked.GetHeight(), m_bmpUnchecked.GetHeight()); size_t widthBmp = wxMax(m_bmpChecked.GetWidth(), m_bmpUnchecked.GetWidth()); if ( IsOwnerDrawn() ) { heightBmp += data->CheckMargin.GetTotalY(); } else { // we must allocate enough space for the bitmap *width += widthBmp; } // Is BMP height larger than text height? if ( *height < heightBmp ) *height = heightBmp; } // make sure that this item is at least as tall as the system menu height const size_t menuHeight = data->CheckMargin.GetTotalY() + data->CheckSize.cy; if (*height < menuHeight) *height = menuHeight; return true; }
/* * Obtain the hyperlink located at the * mouse position. If there is no hyperlink * at the mouse position return NULL. */ TCHAR *GetHyperlink( LPCLASSDATA lpcd ) { POINT ptStart, ptEnd, ptMousePos; /* * Are we parsing hyperlinks? */ if ( Parser->bParseHyperLinks ) { /* * Get mouse position and convert * to client coordinates. */ GetCursorPos( &ptMousePos ); ScreenToClient( lpcd->hWnd, &ptMousePos ); /* * Skip selection margin. */ ptMousePos.x -= ( GetMarginWidth( lpcd ) + GetLineMarginWidth( lpcd )); /* * Convert the coordinates to the character * position. */ if ( MouseToCaret( lpcd, ptMousePos.x, ptMousePos.y, &ptMousePos )) { /* * Check if the character is located inside * a hyperlink. */ if ( CheckForHyperlink( lpcd, &ptMousePos, &ptStart, &ptEnd, FALSE )) { /* * Allocate memory to store the * hyperlink text. */ TCHAR *pszUrl = AllocPooled( lpcd->pMemPool, REAL_SIZE( ptEnd.x - ptStart.x + 2 )); if ( pszUrl ) { /* * Copy the hyperlink text into the * allocated buffer. */ LPLINE lpLine = ( LPLINE )ArrayGetAt( lpcd->lpLines, ptStart.y ); memcpy( pszUrl, &lpLine->pcText[ ptStart.x ], ptEnd.x - ptStart.x + 1 ); /* * 0-terminate to be on the safe side. */ pszUrl[ ptEnd.x - ptStart.x + 1 ] = 0; return pszUrl; } } } } /* * No hyperlink or memory failure... */ return NULL; }
// draw the item bool wxOwnerDrawn::OnDrawItem( wxDC& rDC, const wxRect& rRect, wxODAction eAction, wxODStatus eStatus ) { // // Select the font and draw the text // --------------------------------- // CHARBUNDLE vCbnd; wxPMDCImpl *impl = (wxPMDCImpl*) rDC.GetImpl(); HPS hPS= impl->GetHPS(); wxFont vFont; wxColour vColBack; wxColour vColText; COLORREF vRef; RECTL vRect = {rRect.x + 4, rRect.y + 1, rRect.x + (rRect.width - 2), rRect.y + rRect.height}; memset(&vCbnd, 0, sizeof(CHARBUNDLE)); GetFontToUse(vFont); GetColourToUse(eStatus, vColText, vColBack); rDC.SetFont(vFont); rDC.SetTextBackground(vColBack); rDC.SetTextForeground(vColText); rDC.SetBackgroundMode(wxTRANSPARENT); vCbnd.lColor = vColText.GetPixel(); vCbnd.lBackColor = vColBack.GetPixel(); ::GpiSetAttrs( hPS ,PRIM_CHAR ,CBB_BACK_COLOR | CBB_COLOR ,0 ,&vCbnd ); ::GpiSetBackMix( hPS ,BM_LEAVEALONE ); // // Paint the background // ::WinFillRect(hPS, &vRect, vColBack.GetPixel()); // // Determine where to draw and leave space for a check-mark. // int nX = rRect.x + GetMarginWidth(); // // Unfortunately, unlike Win32, PM has no owner drawn specific text // drawing methods like ::DrawState that can cleanly handle accel // mnemonics and deal, automatically, with various states, so we have // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn // strings either. We cannot handle mnemonics either. We display // them, though, in the hope we can figure them out some day. // // // Display main text // wxString sFullString = GetItemLabel(); // need to save the original text int nIndex; size_t nWidth; size_t nCharWidth; size_t nHeight; bool bFoundMnemonic = false; // // Deal with the mnemonic character // nIndex = sFullString.Find(wxT("~")); if (nIndex != -1) { wxString sTmp = sFullString; bFoundMnemonic = true; sTmp.Remove(nIndex); rDC.GetTextExtent( sTmp ,(wxCoord *)&nWidth ,(wxCoord *)&nHeight ); sTmp = sFullString[(size_t)(nIndex + 1)]; rDC.GetTextExtent( sTmp ,(wxCoord *)&nCharWidth ,(wxCoord *)&nHeight ); sFullString.Replace(sTgt.c_str(), wxEmptyString, true); } // // Draw the main item text sans the accel text // POINTL vPntStart = {nX, rRect.y + 4}; ::GpiCharStringAt( impl->GetHPS() ,&vPntStart ,sFullString.length() ,sFullString.char_str() ); if (bFoundMnemonic) { // // Underline the mnemonic -- still won't work, but at least it "looks" right // wxPen vPen; POINTL vPntEnd = {nX + nWidth + nCharWidth - 3, rRect.y + 2}; //CharWidth is bit wide vPntStart.x = nX + nWidth - 1; vPntStart.y = rRect.y + 2; // Make it look pretty! vPen = wxPen(vColText, 1, wxSOLID); // Assuming we are always black rDC.SetPen(vPen); ::GpiMove(hPS, &vPntStart); ::GpiLine(hPS, &vPntEnd); } return true; } // end of wxOwnerDrawn::OnDrawItem