I have a rounded rectangle that I make like so
dc.RoundRect(textBorder, CPoint(20, 20));
Later on I draw a line through it about 1/3 of the way down.
dc.LineTo(textBorder.right, textBorder.top + 15);
Now I would like to fill just the part above the line with a solid color. In other words I need to fill a partially rounded rectangle, because the top of the rectangle is rounded, but the bottom of it is truncated by the line. Is there an easy way to do this?
Have you tried using a combination of CreateRoundRectRegion and then FillRgn to fill the non-rectangular area?
This the example given in the docs for CreateRoundRectRegion:
CRgn rgnA, rgnB, rgnC;
VERIFY(rgnA.CreateRoundRectRgn( 50, 50, 150, 150, 30, 30 ));
VERIFY(rgnB.CreateRoundRectRgn( 200, 75, 250, 125, 50, 50 ));
VERIFY(rgnC.CreateRectRgn( 0, 0, 50, 50 ));
int nCombineResult = rgnC.CombineRgn( &rgnA, &rgnB, RGN_OR );
ASSERT( nCombineResult != ERROR && nCombineResult != NULLREGION );
CBrush brA, brB, brC;
VERIFY(brA.CreateSolidBrush( RGB(255, 0, 0) ));
VERIFY(pDC->FillRgn( &rgnA, &brA)); // rgnA Red Filled
VERIFY(brB.CreateSolidBrush( RGB(0, 255, 0) ));
VERIFY(pDC->FillRgn( &rgnB, &brB)); // rgnB Green Filled
VERIFY(brC.CreateSolidBrush( RGB(0, 0, 255) )); // rgnC Blue
VERIFY(pDC->FrameRgn( &rgnC, &brC, 2, 2 ));
In general, when you want to do something with non-rectangular areas you have to start looking into regions.
Related
I need to print a grid like the one in the photo on a PDF document
I am using CIMG to create the image in bmp, then save it as jpg and paste it in the PDF using JagPDF
The code for the graph is as follows:
int lineseparation=3;
int lineseparationbold=lineseparation*5;
CImg<unsigned char> graph1;
graph1.assign(50*lineseparationbold+1, 28*lineseparationbold+1, 1, 3, 255);
static const unsigned char black[] = { 0, 0, 0 }, white[] = { 255, 255, 255 };
static const unsigned char gray2[] = { 110, 110, 110 }, ngray[] = { 35, 35, 35 }, gray[] = { 220, 220, 220 };
static const unsigned char red[] = { 255, 200, 200 }, bred[] = { 255, 100, 100 };
graph1.draw_grid(lineseparation, lineseparation, 0, 0, false, true, red, 10.0f, 0xFFFFFFFF, 0xFFFFFFFF);
graph1.draw_grid(lineseparationbold, lineseparationbold, 0, 0, false, true, bred, 10.0f, 0xFFFFFFFF, 0xFFFFFFFF);
graph.save("plot.bmp");
Then after saving it as JPG I put it in the PDF using jagPDF this way:
pdf::Document doc(pdf::create_file("report.pdf"));
doc.page_start(pagewidth, pageheight);
pdf::Image imag2 = doc.image_load_file("plot1.jpg");
doc.page().canvas().image(imag2, 10, 50);
doc.page_end();
doc.finalize();
I need the grid to be 1mm separation between the lines (5mm the bold ones), when I put 3 pixels as separation when I print it is a little more than 1mm and if I put 2 pixels then is less than 1mm.
Putting non integers (e.g int lineseparation=2.9;) as input allow me to get bold lines closer to 5mm but the small lines are uneven. Saving the figure as BMP and resizing it is messing with the grid.
How can I make it print in the correct size?
Note: BMP and JPG have same size in pixels. I do the convertion without any resizing (although I tried that too).
There's a GDI's StrokePath API that can allow to simulate "stroking" of text using this method. I'll copy it here:
void CCanvas::DrawOutlineText( CDC& dc, const CString& Text )
{
const int RestorePoint = dc.SaveDC();
// Create new font
CFont NewFont;
NewFont.CreatePointFont( 700, TEXT( "Verdana" ), &dc );
// Use this font
dc.SelectObject( &NewFont );
// Brush for pen
LOGBRUSH lBrushForPen = { 0 };
lBrushForPen.lbColor = RGB( 200, 150, 100 );
lBrushForPen.lbHatch = HS_CROSS;
lBrushForPen.lbStyle = BS_SOLID;
// New pen for drawing outline text
CPen OutlinePen;
OutlinePen.CreatePen( PS_GEOMETRIC | PS_SOLID, 2, &lBrushForPen, 0, 0 );
// Use this pen
dc.SelectObject( &OutlinePen );
dc.SetBkMode( TRANSPARENT );
dc.BeginPath();
// This text is not drawn on screen, but instead each action is being
// recorded and stored internally as a path, since we called BeginPath
dc.TextOut( 20, 20, Text );
// Stop path
dc.EndPath();
// Now draw outline text
dc.StrokePath();
dc.RestoreDC( RestorePoint );
}
In my case I'm using DrawString function from GDI+ to draw text.
Does anyone know if there's an alternative to BeginPath, EndPath and StrokePath in GDI+ to simulate text stroking?
EDIT: Following the advice by jschroedl below, I tried the following:
CString str = L"Text";
Graphics grpx(dc.GetSafeHdc());
SolidBrush gdiBrush(Color(0xFF, 0xFF, 0, 0));
StringFormat gdiSF;
gdiSF.SetAlignment(StringAlignmentNear);
gdiSF.SetFormatFlags(StringFormatFlagsNoWrap | StringFormatFlagsNoFitBlackBox |
StringFormatFlagsNoFontFallback | StringFormatFlagsNoClip);
gdiSF.SetHotkeyPrefix(HotkeyPrefixNone);
gdiSF.SetTrimming(StringTrimmingNone);
grpx.SetTextRenderingHint(TextRenderingHintAntiAlias);
grpx.SetPixelOffsetMode(PixelOffsetModeNone);
grpx.SetInterpolationMode(InterpolationModeHighQualityBicubic);
GraphicsPath dd;
FontFamily gdiFF(L"Segoe UI");
const PointF pntF(0, 0);
dd.AddString(str, str.GetLength(), &gdiFF, FontStyleRegular, 58.0f, pntF, &gdiSF);
Pen penFF(Color(0xFF, 0xFF, 0, 0), 1.0f);
grpx.DrawPath(&penFF, &dd);
that produced quite a jagged outline (enlarged screenshot):
Any idea how to make it render with anti-aliasing?
I believe our code creates a GraphicsPath object, calls GraphicsPath::AddString() to get the path for the text and later draws the path with Graphics::DrawPath().
Update:
Based on the blocky text, I experimented and think this looks a bit smoother.
grpx.SetTextRenderingHint(TextRenderingHintClearTypeGridFit);
grpx.SetSmoothingMode(SmoothingModeHighQuality);
grpx.SetPixelOffsetMode(PixelOffsetModeHalf);
In this jsfiddle I have a Raphael canvas with two images. The first one is the complete image (not clipped) and the second one is the same image but clipped. For some reason the second image is not showing up. What's wrong with this code?
javascript:
var paper = Raphael(document.getElementById('canvas'));
var img = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png', 0, 0, 480, 259 );
var img2 = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png', 0, 300, 40, 40 );
img2.attr({'clip-rect': "0,0,40,40" });
You made two mistakes.
First: You scaled your image down. Change
var img2 = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png',
0, 300, 40, 40 );
to
var img2 = paper.image('http://designsbynickthegeek.com/wp-content/uploads/2012/01/social-header.png',
0, 300, 480, 259 );
Second: You used the wrong clipping coordinates. Change
img2.attr({'clip-rect': "0,0,40,40" });
to
img2.attr({'clip-rect': "0,300,40,40" });
see your edited fiddle here.
Using WTL and Graphics,I rewrite an list view tool,like:
,but after click the Name or Phone Number header to sort, it appears like:.
Seems that the old one still there, but not so clear,whats wrong?
The Core Draw Code:
void _DrawItem(HDC hDC, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
...
CDCHandle dcx;
Gdiplus::Graphics grap(hDC);
CRect rcTmp;
GetClientRect(&rcTmp);
dcx.Attach(hDC);
BOOL bBackColor = TRUE;
if ((lpDrawItemStruct->itemID % 2) == 0)
{
bBackColor = FALSE;
}
Gdiplus::SolidBrush mySolidBrush(Gdiplus::Color(235, 235, 235,235));
if (pItem->getOver() || pItem->getChecked())
{
mySolidBrush.SetColor(Gdiplus::Color(215, 0, 0, 215));
}else{
if (bBackColor)
{
mySolidBrush.SetColor(Gdiplus::Color(235, 235, 235, 235));
}else{
mySolidBrush.SetColor(Gdiplus::Color(255, 255, 255, 255));
}
}
grap.FillRectangle(&mySolidBrush, lpDrawItemStruct->rcItem.left , lpDrawItemStruct->rcItem.top, nColumWidth,
lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top);
Just a guess but your alpha transparency value is not opaque so filling the rect with 235,235,235,235 will blend with the old content. Probably need a 255 in there for alpha.
I need to fill the closed besier curve with colour...can anybody help me to improve this code because it doesn't work:
COLORREF collor = RGB(100,50,150);
CPen g(PS_INSIDEFRAME, 50, collor);
pDC->SetBkColor(RGB(90, 100, 128));
pDC->SelectObject(&g);
CPoint Pt[10]=
{
CPoint(400, 260),
CPoint(480, 260),
CPoint(500, 260),
CPoint(470, 290),
CPoint(450, 350),
CPoint(470, 370),
CPoint(430, 370),
CPoint(420, 391),
CPoint(405, 410),
CPoint(400, 260),
};
pDC->PolyBezier(Pt, 10);
Thanks!
You need to select a brush which has been created as a solid color with the color you want to fill with.
CBrush brush;
brush.CreateSolidBrush(collor);
CBrush * pOldBrush = (CBrush *) pDC->SelectObject(&brush);
...
pDC->SelectObject(pOldBrush);