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);
Related
I try to make some easy application which scrolling ECG singal which is drawing on bitmap grid. Environment which I use is Visual Studio 2013 with C++ MFC.
My problem is with transfer gdi object like LineTo or Rectangle() function from dcMemory to my main device context (cdc). Before I make similar application using WinAPI and all go well. I spent a lot time with studying msdn and looking answer with google, and I have no idea why only bitmap from Bitmap.LoadBitmapW(IDB_BITMAP2) is printing. Can anybody help me?
Message when button from menu was calling:
void CToradex_MFC_BitmapView::OnBitmapDraw()
{
Bitmap.LoadBitmapW(IDB_BITMAP2);
cdc.CreateDC(L"DISPLAY", NULL, NULL, NULL);
dcMemory.CreateCompatibleDC(&cdc);
LoadData();
GetObject(Bitmap, sizeof(bmpInfo), &bmpInfo);
dcMemory.SelectObject(&Pen);
dcMemory.Rectangle(100, 100, 200, 200);
dcMemory.LineTo(100, 300);
dcMemory.SelectObject(&Bitmap);
druk.DrawECG(&dcMemory, pointer, 3, SIGN_LEN);
}
Message on mouse button down:
void CToradex_MFC_BitmapView::OnLButtonDown(UINT,CPoint)
{
CToradex_MFC_BitmapDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
POINT p;
GetCursorPos(&p);
x_start = p.x;
y_start = p.y;
}
Message on mouse move:
void CToradex_MFC_BitmapView::OnMouseMove(UINT, CPoint)
{
POINT d;
//CDC * pDC = this->GetDC();
//this->GetClientRect(&rect);
//rect = CRect(rect.left, rect.top, rect.right, rect.bottom);
if (GetCursorPos(&d))
{
move_x = d.x - x_start;
move_y = d.y - y_start;
cdc.BitBlt(move_x, move_y, bmpInfo.bmWidth, bmpInfo.bmHeight, &dcMemory, 0, 0, SRCCOPY);
x_start = d.x;
y_start = d.y;
//Invalidate();
Sleep(10);
}
Below link for all .cpp file:
https://pastebin.com/h7hcLJbz
You need to select a bitmap into your DC first, then draw on top of it:
dcMemory.SelectObject(&Bitmap);
dcMemory.SelectObject(&Pen);
dcMemory.Rectangle(100, 100, 200, 200);
dcMemory.LineTo(100, 300);
druk.DrawECG(&dcMemory, pointer, 3, SIGN_LEN);
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);
I modified my dialog to a polygon region dialog. Then i am trying to frame/draw the border.Using device context the CRgn::FrameRgn, i am bale to draw the border around the dialog. But i want to achieve this using Gdi+. I did as below, but the border is appearing only on left and top of the dialog.
Can someone please help on this.
CPoint vertex[4];
BOOL CPolygonDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
ModifyStyle(WS_CAPTION,0);
ModifyStyle(WS_BORDER,0);
CRect rect(400,200,900,700);
CRect wr = rect;
AdjustWindowRect( wr, 0, FALSE );
MoveWindow(wr);
GetClientRect( rect );
CRect csr = rect;
ClientToScreen( csr );
vertex[0] = CPoint(rect.left,rect.top);
vertex[1] = CPoint(rect.right,rect.top);
vertex[2] = CPoint(rect.right,rect.bottom);
vertex[3] = CPoint(rect.left,rect.bottom);
m_rgnShape.CreatePolygonRgn( vertex, 4, ALTERNATE );
m_rgnShape.OffsetRgn( CPoint( csr.TopLeft() - wr.TopLeft() ) );
SetWindowRgn( (HRGN)m_rgnShape.Detach(), TRUE );
m_rgnShape.CreatePolygonRgn( vertex, 4, ALTERNATE );
return TRUE; // return TRUE unless you set the focus to a control
}
void CPolygonDlg::OnPaint()
{
Graphics graphics(dc.m_hDC);
CRect rect;
GetClientRect(rect);
GraphicsPath gp;
Point point[4];
point[0] = Point(rect.left,rect.top);
point[1] = Point(rect.right,rect.top);
point[2] = Point(rect.right,rect.bottom);
point[3] = Point(rect.left,rect.bottom);
gp.AddPolygon(point,4);
Pen pen(Color(255, 255, 0, 0));
graphics.DrawPath(&pen, &gp);
}
Thanks
When you call GetClientRect(), it returns the size of the client area of the window - the part you can easily draw on, and the part that is controlled by the device context when you do CPaintDC dc(this); in your OnPaint() method.
The problem you are facing is that your dialog window has a border and you need to handle WM_NCPAINT in order to draw on border area.
in a C++ MFC application. using the dc of ( CPaintDC dc(this); )
How do i draw a rectangle ( LPRECT ) with an alpha transparency that i can adjust.?
Following is an example c# code which i need to convert into C++
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Color color = Color.FromArgb(75,Color.Red); //sets color Red with 75% alpha transparency
Rectangle rectangle = new Rectangle(100,100,400,400);
g.FillRectangle(new SolidBrush(color), rectangle); //draws the rectangle with the color set.
}
You need to look into GDI+. Its a bit of a faff but you can create a "Graphics" object as follows:
Gdiplus::Graphics g( dc.GetSafeHdc() );
Gdiplus::Color color( 192, 255, 0, 0 );
Gdiplus::Rect rectangle( 100, 100, 400, 400 );
Gdiplus::SolidBrush solidBrush( color );
g.FillRectangle( &solidBrush, rectangle );
Don't forget to do
#include <gdiplus.h>
and to call
GdiplusStartup(...);
somewhere :)
You'll notice it's pretty damned similar to your C# code ;)
Its worth noting that the 75 you put in your FromArgb code doesn't set 75% alpha it actually sets 75/255 alpha or ~29% alpha.
GDI (and thus MFC) has no decent support for drawing with an alpha. But GDI+ is available in C++ code as well. Use #include <gdiplus.h> and initialize it with GdiplusStartup(). You can use the Graphics class, create one with its Graphics(HDC) constructor from your CPaintDC. And use its FillRectangle() method. The SDK docs are here.
int StartHoriz,StartVert,BarWidth,BarHeight; // rect start, width and height
StartHoriz=0;
StartVert=100;
width = 100;
height=120;
CDC* pCDC = GetDC(); // Get CDC pointer
CRect Rect(StartHoriz,StartVert,BarWidth,BarHeight); //create rectangle dimensions
pCDC->Rectangle(Rect); //draw rectangle
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.