GME
13
|
00001 #include "stdafx.h" 00002 00003 #include "GMEstd.h" 00004 #include "GraphicsUtil.h" 00005 #define _USE_MATH_DEFINES 00006 #include <math.h> 00007 00008 00009 static bool fontBoldness[GME_FONT_KIND_NUM] = { false, false, false }; 00010 static bool fontSemiboldness[GME_FONT_KIND_NUM] = { true, true, false }; 00011 static int fontSizes[GME_FONT_KIND_NUM] = { 16, 15, 12 }; 00012 00013 00015 00016 CArrowHead::CArrowHead(int dir, const std::vector<CPoint>& coords) 00017 { 00018 this->dir = dir; 00019 ASSERT(coords.size() > 0); 00020 std::vector<CPoint>::const_iterator ii = coords.begin(); 00021 while(ii != coords.end()) { 00022 CPoint coord; 00023 switch(dir) { 00024 case GME_RIGHT_DIRECTION: 00025 coord.x = (*ii).x; 00026 coord.y = (*ii).y; 00027 break; 00028 case GME_LEFT_DIRECTION: 00029 coord.x = -(*ii).x; 00030 coord.y = -(*ii).y; 00031 break; 00032 case GME_UP_DIRECTION: 00033 coord.x = (*ii).y; 00034 coord.y = -(*ii).x; 00035 break; 00036 case GME_DOWN_DIRECTION: 00037 coord.x = -(*ii).y; 00038 coord.y = (*ii).x; 00039 break; 00040 default: 00041 ASSERT(false); 00042 break; 00043 } 00044 path.push_back(coord); 00045 ++ii; 00046 } 00047 } 00048 00049 CArrowHead::~CArrowHead() 00050 { 00051 } 00052 00053 CRect CArrowHead::GetLineCoords(long index1, long index2, double angle, bool skew) 00054 { 00055 CRect line; 00056 if (!skew) { 00057 line.left = path[index1].x; 00058 line.top = path[index1].y; 00059 line.right = path[index2].x; 00060 line.bottom = path[index2].y; 00061 } else { 00062 line.left = (int)(cos(angle) * path[index1].x - sin(angle) * path[index1].y + 0.5); 00063 line.top = (int)(sin(angle) * path[index1].x + cos(angle) * path[index1].y + 0.5); 00064 line.right = (int)(cos(angle) * path[index2].x - sin(angle) * path[index2].y + 0.5); 00065 line.bottom = (int)(sin(angle) * path[index2].x + cos(angle) * path[index2].y + 0.5); 00066 } 00067 return line; 00068 } 00069 00070 void CArrowHead::Draw(Gdiplus::Graphics* gdip, Gdiplus::Pen* pen, Gdiplus::Brush* brush, const CPoint& tip, bool bPen, 00071 double angle, bool bold) 00072 { 00073 bool skew = (abs(angle) > 1.0e-6); 00074 Gdiplus::GraphicsPath arrowHeadPath; 00075 int segments = path.size(); 00076 long lastx; 00077 long lasty; 00078 for (int i = 1; i < segments; i++) { 00079 CRect line = GetLineCoords(i - 1, i, angle, skew); 00080 arrowHeadPath.AddLine(line.left + tip.x, line.top + tip.y, line.right + tip.x, line.bottom + tip.y); 00081 lastx = line.left + tip.x; 00082 lasty = line.top + tip.y; 00083 } 00084 00085 if (bold && !bPen) 00086 { 00087 if (dir == GME_LEFT_DIRECTION || dir == GME_RIGHT_DIRECTION) 00088 { 00089 Gdiplus::Matrix matrix(1.0f, 0.0f, 0.0f, 1.7f, 0, (Gdiplus::REAL)-lasty * (1.7 - 1)); 00090 arrowHeadPath.Transform(&matrix); 00091 } 00092 else 00093 { 00094 Gdiplus::Matrix matrix(1.7f, 0.0f, 0.0f, 1.0f, (Gdiplus::REAL)-lastx * (1.7 - 1), 0); 00095 arrowHeadPath.Transform(&matrix); 00096 } 00097 } 00098 gdip->FillPath(brush, &arrowHeadPath); 00099 00100 if (bPen) { 00101 std::vector<Gdiplus::Point> points; 00102 points.reserve(path.size() + 2); 00103 for (int i = 0; i < path.size(); i++) { 00104 points.push_back(Gdiplus::Point((int)path[i].x + tip.x, (int)path[i].y + tip.y)); 00105 } 00106 CRect line = GetLineCoords(segments - 1, 0, angle, skew); 00107 points.push_back(Gdiplus::Point((int)path[0].x + tip.x, (int)path[0].y + tip.y)); 00108 points.push_back(Gdiplus::Point((int)path[1].x + tip.x, (int)path[1].y + tip.y)); // <- extra point gives nice sharp corner, instead of butt-end 00109 if (bold) 00110 { 00111 pen = pen->Clone(); 00112 Gdiplus::Matrix mat(3.0, 0.0, 0.0, 3.0, 0, 0); 00113 pen->MultiplyTransform(&mat); // FIXME only shows up at higher zoom for some reason 00114 } 00115 gdip->DrawLines(pen, &points[0], points.size()); 00116 if (bold) 00117 { 00118 delete pen; 00119 } 00120 } 00121 00122 } 00123 00124 00126 00127 CBulletArrowHead::CBulletArrowHead(int dir, const std::vector<CPoint>& coords): 00128 CArrowHead(dir, coords) 00129 { 00130 } 00131 00132 CBulletArrowHead::~CBulletArrowHead() 00133 { 00134 } 00135 00136 void CBulletArrowHead::Draw(Gdiplus::Graphics* gdip, Gdiplus::Pen* pen, Gdiplus::Brush* brush, const CPoint& tip, bool bPen, 00137 double angle, bool bold) 00138 { 00139 ASSERT(path.size() == 2); 00140 int ox = 0; 00141 int oy = 0; 00142 if (abs(angle) < 1.0e-6) 00143 { 00144 ox = path[0].x; 00145 oy = path[0].y; 00146 } 00147 else // skew 00148 { 00149 ox = (int)(cos(angle) * path[0].x - sin(angle) * path[0].y + 0.5); 00150 oy = (int)(sin(angle) * path[0].x + cos(angle) * path[0].y + 0.5); 00151 } 00152 int a = abs(path[1].x); 00153 int b = abs(path[1].y); 00154 Gdiplus::GraphicsPath* bulletPath = new Gdiplus::GraphicsPath(); 00155 bulletPath->AddEllipse(ox - a + tip.x, oy - b + tip.y, 2 * a, 2 * b); 00156 gdip->FillPath(brush, bulletPath); 00157 gdip->DrawPath(pen, bulletPath); 00158 delete bulletPath; 00159 } 00160 00161 00163 00164 CGraphics::CGraphics() 00165 { 00166 } 00167 00168 CGraphics::~CGraphics() 00169 { 00170 } 00171 00172 void CGraphics::Initialize(void) 00173 { 00174 CreateFonts(normalFonts, normalGdipFonts, FW_LIGHT); 00175 CreateFonts(semiboldFonts, semiboldGdipFonts, FW_NORMAL); 00176 CreateFonts(boldFonts, boldGdipFonts, FW_SEMIBOLD); 00177 00178 std::vector<CPoint> arrowCoords; 00179 arrowCoords.push_back(CPoint(-5, 0)); 00180 arrowCoords.push_back(CPoint(-7, -3)); 00181 arrowCoords.push_back(CPoint(-1, 0)); 00182 arrowCoords.push_back(CPoint(-7, 3)); 00183 std::vector<CPoint> leftHalfCoords; 00184 leftHalfCoords.push_back(CPoint(-1, 0)); 00185 leftHalfCoords.push_back(CPoint(-10, -5)); 00186 std::vector<CPoint> rightHalfCoords; 00187 rightHalfCoords.push_back(CPoint(-1, 0)); 00188 rightHalfCoords.push_back(CPoint(-10, 5)); 00189 std::vector<CPoint> diamondCoords; 00190 diamondCoords.push_back(CPoint(-10, 0)); 00191 diamondCoords.push_back(CPoint(-5, -3)); 00192 diamondCoords.push_back(CPoint(-0, 0)); 00193 diamondCoords.push_back(CPoint(-5, 3)); 00194 std::vector<CPoint> apexCoords; 00195 apexCoords.push_back(CPoint(-9, -5)); 00196 apexCoords.push_back(CPoint(-9, 5)); 00197 apexCoords.push_back(CPoint(-1, 0)); 00198 std::vector<CPoint> bulletCoords; // Special: 00199 bulletCoords.push_back(CPoint(-4, 0)); // ellipse origo 00200 bulletCoords.push_back(CPoint(3, 3)); // a and b radius of ellipse 00201 00202 for(int i = 0; i < GME_DIRECTION_NUM; i++) { 00203 arrows[i] = new CArrowHead( i, arrowCoords ); 00204 diamonds[i] = new CArrowHead( i, diamondCoords ); 00205 apexes[i] = new CArrowHead( i, apexCoords ); 00206 bullets[i] = new CBulletArrowHead( i, bulletCoords ); 00207 leftHalfArrows[i] = new CArrowHead( i, leftHalfCoords ); 00208 rightHalfArrows[i] = new CArrowHead( i, rightHalfCoords ); 00209 } 00210 } 00211 00212 void CGraphics::Uninitialize(void) 00213 { 00214 for (std::map<CString,Gdiplus::Pen*>::iterator it = m_mapGdipPens.begin() ; it != m_mapGdipPens.end() ; ++it) 00215 delete it->second; 00216 DeleteBrushes(gdipBrushes); 00217 00218 for (int i = 0; i < GME_FONT_KIND_NUM; i++) { 00219 delete normalFonts[i]; 00220 delete semiboldFonts[i]; 00221 delete boldFonts[i]; 00222 delete normalGdipFonts[i]; 00223 delete semiboldGdipFonts[i]; 00224 delete boldGdipFonts[i]; 00225 } 00226 00227 for (int i = 0; i < GME_DIRECTION_NUM; i++) { 00228 delete arrows[i]; 00229 delete diamonds[i]; 00230 delete apexes[i]; 00231 delete bullets[i]; 00232 delete leftHalfArrows[i]; 00233 delete rightHalfArrows[i]; 00234 } 00235 } 00236 00237 void CGraphics::DeleteBrushes(GdipBrushTable& gdipBrushTable) 00238 { 00239 POSITION pos = gdipBrushTable.GetStartPosition(); 00240 void* pt; 00241 Gdiplus::SolidBrush* gdipBrush; 00242 while(pos) { 00243 gdipBrushTable.GetNextAssoc(pos, pt, gdipBrush); 00244 delete gdipBrush; 00245 } 00246 } 00247 00248 void CGraphics::CreateFonts(CFont** font, Gdiplus::Font** gdipFont, int boldness) 00249 { 00250 for (int i = 0; i < GME_FONT_KIND_NUM; i++) { 00251 font[i] = new CFont(); 00252 font[i]->CreateFont(fontSizes[i],0,0,0,boldness,0,0,0,ANSI_CHARSET, 00253 OUT_DEVICE_PRECIS,CLIP_DEFAULT_PRECIS, 00254 PROOF_QUALITY,FF_SWISS,_T("Arial")); 00255 00256 CDC dc; 00257 dc.CreateCompatibleDC(NULL); 00258 LOGFONT logFont; 00259 font[i]->GetLogFont(&logFont); 00260 gdipFont[i] = new Gdiplus::Font( dc.m_hDC, &logFont ); 00261 } 00262 } 00263 00264 Gdiplus::Font* CGraphics::GetGdipFont(GMEFontKind kind) 00265 { 00266 return GetGdipFont(kind, fontBoldness[kind], fontSemiboldness[kind]); 00267 } 00268 00269 Gdiplus::Font* CGraphics::GetGdipFont(int kindsize, bool bold, bool semibold) 00270 { 00271 return bold ? boldGdipFonts[kindsize] : (semibold ? semiboldGdipFonts[kindsize] : normalGdipFonts[kindsize]); 00272 } 00273 00274 Gdiplus::Pen* CGraphics::GetGdipPen2(Gdiplus::Graphics* gdip, COLORREF color, GMEConnLineType lineType, 00275 bool isViewMagnified, int width) 00276 { 00277 // TODO 00278 // HDC hDC = gdip->GetHDC(); 00279 // bool isPrinting = GetDeviceCaps(hDC, TECHNOLOGY) == DT_RASPRINTER; 00280 // gdip->ReleaseHDC(hDC); 00281 return GetGdipPen(gdip, color, /*isPrinting*/ false, lineType, isViewMagnified, width); 00282 } 00283 00284 Gdiplus::Pen* CGraphics::GetGdipPen(Gdiplus::Graphics* gdip, COLORREF color, bool isPrinting, GMEConnLineType lineType, 00285 bool isViewMagnified, int width) 00286 { 00287 CString chBuffer; 00288 chBuffer.Format(_T("%x-%d-%d-%d-%ld"), color, isPrinting, lineType, isViewMagnified, width); 00289 std::map<CString,Gdiplus::Pen*>::iterator it = m_mapGdipPens.find(chBuffer); 00290 if (it != m_mapGdipPens.end()) 00291 return it->second; 00292 00293 Gdiplus::Color gdipColor(GetRValue(color), GetGValue(color), GetBValue(color)); 00294 float fWidth = static_cast<float> (isPrinting ? 1 : width); 00295 Gdiplus::Pen* pen = new Gdiplus::Pen(gdipColor, fWidth); 00296 if (lineType == GME_LINE_DASH) { 00297 Gdiplus::REAL dashPatternVals[2] = { 00298 5.0f, // dash length 5 00299 2.0f // space length 2 00300 }; 00301 pen->SetDashPattern(dashPatternVals, 2); 00302 pen->SetDashStyle(Gdiplus::DashStyleCustom); 00303 pen->SetDashCap(Gdiplus::DashCapRound); 00304 } else if (lineType == GME_LINE_CUSTOMIZED) { 00305 pen->SetDashStyle(Gdiplus::DashStyleDashDotDot); 00306 pen->SetDashCap(Gdiplus::DashCapRound); 00307 // } else { 00308 // pen->SetDashStyle(Gdiplus::DashStyleSolid); 00309 } 00310 00311 m_mapGdipPens.insert(std::map<CString,Gdiplus::Pen*>::value_type(chBuffer, pen)); 00312 return pen; 00313 } 00314 00315 Gdiplus::SolidBrush* CGraphics::GetGdipBrush(COLORREF color) 00316 { 00317 Gdiplus::SolidBrush* brush = NULL; 00318 if(!(gdipBrushes.Lookup((void*)color, brush))) { 00319 brush = new Gdiplus::SolidBrush(Gdiplus::Color(GetRValue(color), GetGValue(color), GetBValue(color))); 00320 gdipBrushes.SetAt((void*)color, brush); 00321 } 00322 ASSERT(brush); 00323 return brush; 00324 } 00325 00326 void CGraphics::DrawGrid(Gdiplus::Graphics* gdip, int xSpace, int ySpace, int maxx, int maxy, COLORREF color) 00327 { 00328 Gdiplus::Pen* pen = GetGdipPen2(gdip, color); 00329 for(int x = 0 ; x < maxx; x += xSpace) 00330 gdip->DrawLine(pen, x, 0, x, maxy); 00331 for(int y = 0; y < maxy; y += ySpace) 00332 gdip->DrawLine(pen, 0, y, maxx, y); 00333 } 00334 00335 typedef std::pair<long,long> Long_Pair; 00336 00337 void CGraphics::DrawConnection(Gdiplus::Graphics* gdip, const CPointList& points, const std::vector<long>& customizedEdgeIndexes, 00338 COLORREF color, GMEConnLineType lineType, int srcEnd, int dstEnd, bool isViewMagnified, 00339 bool drawBullets, int width) 00340 { 00341 if (points.GetCount() == 0) 00342 return; 00343 00344 long numEdges = points.GetCount() - 1; 00345 if (numEdges < 1) { 00346 ASSERT(false); 00347 return; 00348 } 00349 00350 // TODO? 00351 // HDC hDC = gdip->GetHDC(); 00352 bool isPrinting = false; //GetDeviceCaps(hDC, TECHNOLOGY) == DT_RASPRINTER; 00353 // gdip->ReleaseHDC(hDC); 00354 // if (isPrinting) 00355 // color = GME_BLACK_COLOR; 00356 00357 Gdiplus::Brush* brush = GetGdipBrush(color); 00358 Gdiplus::Brush* bulletBrush = brush; 00359 long bulletOffset = (width + 4) / 2; 00360 long bulletRadius = width + 4; 00361 00362 if (customizedEdgeIndexes.size() > 0) { 00363 std::map<long,long> customizedIndexes; // FIXME if customizedEdgeIndexes is sorted, use binary search to avoid allocations 00364 // convert array to a map for easier lookup 00365 std::vector<long>::const_iterator ii = customizedEdgeIndexes.begin(); 00366 while (ii != customizedEdgeIndexes.end()) 00367 { 00368 customizedIndexes.insert(Long_Pair(*ii, 0)); 00369 ++ii; 00370 } 00371 std::map<long,long>::const_iterator indIter; 00372 00373 CPoint last; 00374 POSITION pos = points.GetHeadPosition(); 00375 if (pos) { 00376 CPoint pt = points.GetNext(pos); 00377 last = pt; 00378 long currEdgeIndex = 0; 00379 while (pos) { 00380 pt = points.GetNext(pos); 00381 Gdiplus::Pen* pen; 00382 indIter = customizedIndexes.find(currEdgeIndex); 00383 if (indIter != customizedIndexes.end()) { 00384 pen = GetGdipPen(gdip, color, isPrinting, GME_LINE_CUSTOMIZED, isViewMagnified, width); 00385 } else { 00386 pen = GetGdipPen(gdip, color, isPrinting, lineType, isViewMagnified, width); 00387 } 00388 gdip->DrawLine(pen, last.x, last.y, pt.x, pt.y); 00389 if (drawBullets && currEdgeIndex < numEdges - 1) { 00390 gdip->FillEllipse(bulletBrush, pt.x - bulletOffset, pt.y - bulletOffset, bulletRadius, bulletRadius); 00391 } 00392 last = pt; 00393 currEdgeIndex++; 00394 } 00395 } 00396 } 00397 else { 00398 // Same pen for all edges. Use DrawLines. 00399 using namespace Gdiplus; 00400 std::vector<Point> gpoints; 00401 gpoints.reserve(points.GetSize()); 00402 POSITION pos = points.GetHeadPosition(); 00403 while (pos) { 00404 CPoint pt = points.GetNext(pos); 00405 gpoints.push_back(Point(pt.x, pt.y)); 00406 } 00407 Pen* pen = GetGdipPen(gdip, color, isPrinting, lineType, isViewMagnified, width); 00408 gdip->DrawLines(pen, &gpoints[0], gpoints.size()); // n.b. this is different than a sequence of DrawLine()s (GME-419) 00409 } 00410 00411 Gdiplus::Pen* headpen = GetGdipPen(gdip, color, isPrinting); 00412 00413 { 00414 POSITION pos2 = points.GetHeadPosition(); 00415 CPoint first = points.GetNext(pos2); 00416 CPoint second = points.GetNext(pos2); 00417 00418 Gdiplus::Brush* headBrush = NULL; 00419 headBrush = GetGdipBrush((srcEnd == GME_EMPTYDIAMOND_END || 00420 srcEnd == GME_EMPTYAPEX_END || 00421 srcEnd == GME_EMPTYBULLET_END) ? GME_WHITE_COLOR : color); 00422 00423 DrawArrow(gdip, headpen, headBrush, second, first, srcEnd, width > 2); 00424 } 00425 00426 { 00427 POSITION pos = points.GetTailPosition(); 00428 CPoint last = points.GetPrev(pos); 00429 CPoint beforeLast = points.GetPrev(pos); 00430 00431 Gdiplus::Brush* headBrush = NULL; 00432 headBrush = GetGdipBrush((dstEnd == GME_EMPTYDIAMOND_END || 00433 dstEnd == GME_EMPTYAPEX_END || 00434 dstEnd == GME_EMPTYBULLET_END) ? GME_WHITE_COLOR : color); 00435 00436 DrawArrow(gdip, headpen, headBrush, beforeLast, last, dstEnd, width > 2); 00437 } 00438 } 00439 00440 void CGraphics::DrawArrow(Gdiplus::Graphics* gdip, Gdiplus::Pen* pen, Gdiplus::Brush* brush, 00441 const CPoint& beforeLast, const CPoint& last, int iEnd, bool bold) 00442 { 00443 if (iEnd == GME_BUTT_END) { 00444 return; 00445 } 00446 int dir = 0; 00447 double alpha = 0.0; 00448 bool skew = false; 00449 if (beforeLast.x == last.x) 00450 { 00451 if (beforeLast.y > last.y) 00452 { 00453 dir = GME_UP_DIRECTION; 00454 } 00455 else 00456 { 00457 dir = GME_DOWN_DIRECTION; 00458 } 00459 } 00460 else if (beforeLast.y == last.y) 00461 { 00462 if (beforeLast.x > last.x) 00463 { 00464 dir = GME_LEFT_DIRECTION; 00465 } 00466 else 00467 { 00468 dir = GME_RIGHT_DIRECTION; 00469 } 00470 } 00471 else // skew 00472 { 00473 skew = true; 00474 dir = GME_RIGHT_DIRECTION; 00475 alpha = atan2((double)last.y - beforeLast.y, (double)last.x - beforeLast.x); 00476 } 00477 00478 switch (iEnd) { 00479 case GME_ARROW_END : 00480 arrows[dir]->Draw(gdip, pen, brush, last, false, alpha, bold); 00481 break; 00482 case GME_DIAMOND_END : 00483 case GME_EMPTYDIAMOND_END : 00484 diamonds[dir]->Draw(gdip, pen, brush, last, iEnd == GME_EMPTYDIAMOND_END, alpha, bold); 00485 break; 00486 case GME_APEX_END : 00487 case GME_EMPTYAPEX_END : 00488 apexes[dir]->Draw(gdip, pen, brush, last, iEnd == GME_EMPTYAPEX_END, alpha, bold); 00489 break; 00490 case GME_BULLET_END : 00491 case GME_EMPTYBULLET_END : 00492 bullets[dir]->Draw(gdip, pen, brush, last, iEnd == GME_EMPTYBULLET_END, alpha, bold); 00493 break; 00494 case GME_HALFARROWLEFT_END : 00495 leftHalfArrows[dir]->Draw(gdip, pen, brush, last, true, alpha, bold); 00496 break; 00497 case GME_HALFARROWRIGHT_END : 00498 rightHalfArrows[dir]->Draw(gdip, pen, brush, last, true, alpha, bold); 00499 break; 00500 } 00501 } 00502 00503 void CGraphics::DrawGdipText(Gdiplus::Graphics* gdip, const CString& txt, const CPoint& pt, Gdiplus::Font* font, COLORREF color, int align) 00504 { 00505 if (font == NULL) 00506 return; 00507 00508 Gdiplus::StringFormat format; 00509 Gdiplus::StringAlignment horizontalAlignment; 00510 if ((align & TA_CENTER) == TA_CENTER) { 00511 horizontalAlignment = Gdiplus::StringAlignmentCenter; 00512 } else if ((align & TA_RIGHT) == TA_RIGHT) { 00513 horizontalAlignment = Gdiplus::StringAlignmentFar; 00514 } else { // TA_LEFT 00515 horizontalAlignment = Gdiplus::StringAlignmentNear; 00516 } 00517 format.SetAlignment(horizontalAlignment); 00518 Gdiplus::StringAlignment verticalAlignment; 00519 if ((align & TA_BASELINE) == TA_BASELINE) { 00520 verticalAlignment = Gdiplus::StringAlignmentCenter; 00521 } else if ((align & TA_BOTTOM) == TA_BOTTOM) { 00522 verticalAlignment = Gdiplus::StringAlignmentFar; 00523 } else { // TA_TOP 00524 verticalAlignment = Gdiplus::StringAlignmentNear; 00525 } 00526 format.SetLineAlignment(verticalAlignment); 00527 format.SetFormatFlags(format.GetFormatFlags() | Gdiplus::StringFormatFlagsNoWrap); 00528 format.SetTrimming(Gdiplus::StringTrimmingEllipsisPath); 00529 00530 // TODO 00531 // HDC hDC = gdip->GetHDC(); 00532 // COLORREF textColor = GetDeviceCaps(hDC, TECHNOLOGY) == DT_RASPRINTER ? GME_BLACK_COLOR : color; 00533 // gdip->ReleaseHDC(hDC); 00534 COLORREF textColor = color; 00535 00536 Gdiplus::SolidBrush textBrush(Gdiplus::Color(GetRValue(textColor), 00537 GetGValue(textColor), 00538 GetBValue(textColor))); 00539 00540 Gdiplus::PointF pointF(static_cast<float> (pt.x), 00541 static_cast<float> (pt.y)); 00542 00543 gdip->DrawString(txt, txt.GetLength(), font, pointF, &format, &textBrush); 00544 } 00545 00546 Gdiplus::RectF CGraphics::MeasureText2(Gdiplus::Graphics* gdip, const CString& txt, const CPoint& pt, Gdiplus::Font* font) 00547 { 00548 Gdiplus::PointF pointF(static_cast<float> (pt.x), 00549 static_cast<float> (pt.y)); 00550 00551 Gdiplus::RectF rectF; 00552 gdip->MeasureString(txt, txt.GetLength(), font, pointF, &rectF); 00553 return rectF; 00554 } 00555 00556 CSize CGraphics::MeasureText(Gdiplus::Graphics* gdip, const CString& txt, const CPoint& pt, Gdiplus::Font* font) 00557 { 00558 Gdiplus::RectF rectF = MeasureText2(gdip, txt, pt, font); 00559 Gdiplus::SizeF sizeF; 00560 rectF.GetSize(&sizeF); 00561 CSize size(static_cast<long> (sizeF.Width), static_cast<long> (sizeF.Height)); 00562 return size; 00563 }