void PrintRichEdit(HWND hwnd, Gdiplus::Graphics* graphics, Gdiplus::Bitmap* background, Gdiplus::Rect layoutArea) { using namespace Gdiplus; //Calculate the area to render. HDC hdc1 = ::GetDC(hwnd); double anInchX = 1440 / GetDeviceCaps(hdc1, LOGPIXELSX); double anInchY = 1440 / GetDeviceCaps(hdc1, LOGPIXELSY); ReleaseDC(hwnd,hdc1); //double anInch = 1440.0 / GetDeviceCaps(hdc1, LOGPIXELSX); RECT rectLayoutArea; rectLayoutArea.top = (int)(layoutArea.GetTop() * anInchY); rectLayoutArea.bottom = (int)(layoutArea.GetBottom() * anInchY); rectLayoutArea.left = (int)(layoutArea.GetLeft() *anInchX ); rectLayoutArea.right = (int)(layoutArea.GetRight() * anInchX); HDC hdc = graphics->GetHDC(); Gdiplus::Graphics gr2(hdc); SolidBrush br(Color(255,255,255)); // We need to draw background on new HDC, otherwise the text will look ugly Status st = gr2.DrawImage(background,layoutArea.GetLeft(),layoutArea.GetTop(),layoutArea.GetLeft(), layoutArea.GetTop(), layoutArea.Width, layoutArea.Height,Gdiplus::UnitPixel/*gr2.GetPageUnit()*/); FORMATRANGE fmtRange; fmtRange.chrg.cpMax = -1; //Indicate character from to character to fmtRange.chrg.cpMin = 0; fmtRange.hdc = hdc; //Use the same DC for measuring and rendering fmtRange.hdcTarget = hdc; //Point at printer hDC fmtRange.rc = rectLayoutArea; //Indicate the area on page to print fmtRange.rcPage = rectLayoutArea; //Indicate size of page int characterCount = ::SendMessage(hwnd, EM_FORMATRANGE, 1, (LPARAM)&fmtRange); //Release the device context handle obtained by a previous call graphics->ReleaseHDC(hdc); }
HRESULT Action( const P* pts, size_t count, const Gdiplus::Rect& clip, ScanConvertCallback callback, INT_PTR hint) { if(count <= 0) return E_INVALIDARG; if(pts == NULL) return E_INVALIDARG; if(callback == NULL) return E_INVALIDARG; n = (INT) count; pt = pts; /// initialize index array as natrual order std::vector<INT> idx(n); active.resize(n); for(INT i = 0; i < n; i ++) { idx[i] = i; } /// Sort idx by the order of pt[idx[k]].Y std::sort(&idx[0], &idx[0] + n, CompareIndex(pt)); nact = 0; /// number of active edges, init as empty INT k = 0; /// idx[k] is the next vertex to precess INT y0 = max(clip.GetTop(), xtl::FloorCast<INT>(pt[idx[0]].Y)); /// the topmost scanline INT y1 = min(clip.GetBottom(), xtl::CeilCast<INT>(pt[idx[n-1]].Y)); /// the bottom scanline /// step through scanlines /// scanline y is at y+.5 in continuous coordinates for(INT y = y0; y < y1; y ++) { /// check vertices between previous scanline and current one, if any for (; (k < n) && (pt[idx[k]].Y <= y); k++) { /// to simplify, if pt.y = y+.5, pretend it's above /// invariant: y-.5 < pt[i].y <= y+.5 INT i = idx[k]; /// insert or delete edges before and after vertex i /// (i-1 to i, and i to i+1) from active list if they cross scanline y INT j = i > 0 ? i-1 : n-1; /// vertex previous to i if (pt[j].Y <= y) /// old edge, remove from active list { DeleteActiveEdge(j); } else if (pt[j].Y > y) /// new edge, add to active list { InsertActiveEdge(j, y); } j = i < (n - 1) ? i+1 : 0; /// vertex next after i if (pt[j].Y <= y) /// old edge, remove from active list { DeleteActiveEdge(i); } else if (pt[j].Y > y) /// new edge, add to active list { InsertActiveEdge(i, y); } } /// sort active edge list by active[j].x std::sort(&active[0], &active[0] + nact, CompareEdge()); /// draw horizontal segments for scanline y for (INT j=0; j < nact; j += 2) /// draw horizontal segments { /// span 'tween j & j+1 is inside, span tween j+1 & j+2 is outside INT xl = xtl::CeilCast<INT>(active[j].x); /// left end of span if (xl < clip.GetLeft()) xl = clip.GetLeft(); if (xl > clip.GetRight()) xl = clip.GetRight(); INT xr = xtl::CeilCast<INT>(active[j+1].x); /// right end of span if (xr < clip.GetLeft()) xr = clip.GetLeft(); if (xr > clip.GetRight()) xr = clip.GetRight(); if (xl < xr) { /// Invoke call back in span if(!callback(y, xl, xr, hint)) { /// if call back returns false /// return prematurely return S_OK; } } active[j].x += active[j].dx; /// increment edge coords active[j+1].x += active[j+1].dx; } } return S_OK; }
void TrackListCtrl::DrawItem(Gdiplus::Graphics& g, INT nItem, Gdiplus::Rect& itemRC) { HDC hdc = g.GetHDC(); if (hdc == 0) { TRACE(_T("@1 TrackListCtrl::DrawItem. Cant get HDC\r\n")); return; } CDC* pDC = CDC::FromHandle(hdc); PrgAPI* pAPI = PRGAPI(); //Calculate Colors BOOL bSelected = IsItemSelected(nItem); COLORREF clrText = m_colors[COL_Text]; COLORREF clrBk = m_colors[COL_Bk]; if (bSelected) { clrText = m_colors[COL_TextSel]; clrBk = m_colors[COL_TextSelBk]; } CRect rcSubItem(itemRC.X, itemRC.Y, itemRC.GetRight(), itemRC.GetBottom()); pDC->SetTextColor(clrText); pDC->FillSolidRect(rcSubItem, clrBk); const INT cMargin = 2; FullTrackRecordSP& rec = (*m_pCollection)[nItem]; pDC->SetBkMode(TRANSPARENT); INT curx = cMargin; CRect rcFirstLine(rcSubItem); rcFirstLine.bottom = rcFirstLine.top + 20; rcFirstLine.left = cMargin; rcFirstLine.right -= cMargin; CRect rcSecondLine(rcSubItem); rcSecondLine.top = rcFirstLine.bottom; rcSecondLine.left = cMargin; rcSecondLine.right -= cMargin; if (m_bDrawPictures) { INT imgHeight = 32;//rcSubItem.Height() - 2 * cMargin; INT cury = rcSubItem.top + cMargin; LocalPictureManager* pLM = PRGAPI()->GetLocalPictureManager(); Gdiplus::Rect rcImage(curx, cury, imgHeight, imgHeight); Graphics g2(hdc); BOOL bRet = pLM->DrawAlbumThumbnail(rec->artist.name.c_str(), rec->album.name.c_str(), g2, rcImage); if (!bRet) bRet = pLM->DrawArtistThumbnail(rec->artist.name.c_str(), g2, rcImage); if (!bRet) bRet = pLM->DrawDefaultThumbnail(IIT_AlbumPicture, g2, rcImage); curx += 32 + cMargin ; } rcSecondLine.left = curx; //=== Draw the icon INT cury = rcFirstLine.top + (rcFirstLine.Height() - 16) / 2; pDC->SetTextColor(clrText); DrawIconEx(pDC->m_hDC, curx, cury, pAPI->GetIconForTrackType(rec->track.trackType), 16, 16, 0, 0, DI_NORMAL); curx += 16 + cMargin; //=== Draw the title CRect rcTitle(rcFirstLine); rcTitle.left = curx; CFont* pOldFont = pDC->SelectObject(m_pBoldFont); pDC->DrawText(rec->track.name.c_str(), rec->track.name.size(), &rcTitle, DT_END_ELLIPSIS | DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); pDC->DrawText(rec->track.name.c_str(), rec->track.name.size(), &rcTitle, DT_END_ELLIPSIS | DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX | DT_CALCRECT); //=== Draw the artist CRect rcArtist(rcFirstLine); rcArtist.left = rcTitle.right + cMargin; pDC->DrawText(rec->artist.name.c_str(), rec->artist.name.size(), &rcArtist, DT_END_ELLIPSIS | DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); pDC->SelectObject(m_pNormalFont); //=== Next line //=== Draw the rating (if exists) if (rec->track.rating > 0 && rec->track.rating < 256) { FLOAT fStars = Rating2Stars(rec->track.rating); if (fStars > 0.0f && fStars <=1.0f) { DrawIconEx(hdc, rcSecondLine.left, rcSecondLine.top, pAPI->GetIcon(ICO_StarBad16), 16, 16, 0, 0, DI_NORMAL); rcSecondLine.left += 17; } while (fStars > 1.0f) { DrawIconEx(hdc, rcSecondLine.left, rcSecondLine.top, pAPI->GetIcon(ICO_StarGold16), 16, 16, 0, 0, DI_NORMAL); fStars -= 1.0f; rcSecondLine.left += 17; } } TCHAR time[500]; UINT len = _sntprintf(time, 500, _T("%d:%02d | %s: %s | %s: %s"), INT (rec->track.duration / 60), INT(rec->track.duration) % 60, pAPI->GetString(IDS_ALBUM), rec->album.name.c_str(), pAPI->GetString(IDS_LOCATION), rec->track.location.c_str() ); pDC->DrawText(time, len, &rcSecondLine, DT_END_ELLIPSIS | DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); pDC->SelectObject(pOldFont); g.ReleaseHDC(pDC->m_hDC); }