I want draw arc have big Radius using gdi.
Drawing is Success.
but arc is wrong.
so, I draw ellipse.
ellipse is Correct.
why that Two Drawing is Different??
Thanks For your Reading.
CClientDC dc(this);
CPen pen(PS_SOLID, 1, 0xff0000);
dc.SetArcDirection(AD_COUNTERCLOCKWISE);
CPoint ptTopLeft(-1290, 203);
CPoint ptBottomRight(4009, 5502);
CPoint ptStart(550, 329);
CPoint ptEnd(356, 400);
dc.Arc(ptTopLeft.x, ptTopLeft.y, ptBottomRight.x, ptBottomRight.y, ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
dc.SelectStockObject(NULL_BRUSH);
dc.Ellipse(ptTopLeft.x, ptTopLeft.y, ptBottomRight.x, ptBottomRight.y);
Related
I have to draw left (not inside) from a CButton, two little red and green rectangle. I am not sure how to achieve this in the right way. Can I use in DrawItem() the device context from the parent DC to draw it?
void CSpecialButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{ ..
CDC* parentDC = GetParent()->GetDC();
CRect rcClrRed;
.. calculate rcClrRed;
parentDC->FillSolidRect(rcRed, RGB(255,0,0);
}
At the beginning, sorry about my English.
I'm now learning how to build a MFC application in visual studio 2015. I'm using Direct2D to draw lines in a window.
When left button is down, my OnLbuttonDown() function is called:
void CMyProjectNameView::OnLButtonDown(UINT nFlags, CPoint point)
{
startPoint = point; // start point of the line, a gloable variable.
pRenderTarget->BeginDraw();
CView::OnLButtonDown(nFlags, point);
}
When left button is up, my OnLButtonUp() function is called:
void CMyProjectNameView::OnLButtonUp(UINT nFlags, CPoint point)
{
pRenderTarget->DrawLine(startPoint, point, m_pbrush, 1.0f); // draw the line
pRenderTarget->EndDraw();
CView::OnLButtonUp(nFlags, point);
}
So it will draw a line in the window when I drag my mouse, and it works fine yesterday.
The problem is when I run it today, it suddenly become abnormal. The start point coordinates and end point coordinates is two times bigger than before. So When I draw the line, the line shows on the bottom right position compared to the position it supposed to be.
For instance, if I draw a line from (100,100) to (500,500), a line start from (100,100) to (500,500) will appear on screen, but when I click left button of my mouse at (100,100), move it to (500,500) and release left button, a line from (200,200) to (1000,1000) will be drawn.
OnLButtonDown(UINT nFlags, CPoint point)
OnLButtonUp(UINT nFlags, CPoint point)
So basically, these two point above is scaled before they are passed in. Do I accidentally change any configurations? Is there any way to fix this? I am sure I didn't change my code.
Coordinates for DrawLine are in device-Independent pixels. See also DPI and Device-Independent Pixels
You have probably changed the size of client rectangle, it needs to be adjusted. Try also to resize the window and see if it gets the right coordinates.
CRect rc;
GetClientRect(&rc);
D2D1_SIZE_F size = pRenderTarget->GetSize();
const float x = size.width / rc.right;
const float y = size.height / rc.bottom;
D2D1_POINT_2F p1;
D2D1_POINT_2F p2;
p1.x = 100 * x;
p1.y = 100 * y;
p2.x = 500 * x;
p2.y = 500 * y;
pRenderTarget->DrawLine(p1, p2, brush);
I create a sample dialog application which has a circle drawn. Also on mouse move the circle will be re-drawn. I am providing my code below. Its also compilable.
I tried using double buffering and erasebackground, i was not getting the flickering issue, but i observed that the drawining is not erased properly. So to erase, in OnPaint i wrote the erasing code. Again i am facing the flickering issue.
void CPOCDlg::OnPaint()
{
CPaintDC dc(this);
GetClientRect(&clientRect);
circle = clientRect;
circle.DeflateRect(100,100);
dc.SelectStockObject(NULL_BRUSH);
dc.SelectStockObject(NULL_PEN);
dc.FillSolidRect(circle, ::GetSysColor(COLOR_BTNFACE));
Bitmap buffer(circle.right, circle.bottom);
Graphics graphicsbuf(&buffer);
Graphics graphics(dc.m_hDC);
graphicsbuf.SetSmoothingMode(SmoothingModeHighQuality);
SolidBrush brush(Color(255,71,71,71));
Pen bluePen(Color(255, 0, 0, 255),1);
graphicsbuf.DrawEllipse(&bluePen,Rect(circle.left,circle.top,circle.Width(),circle.Height()));
graphicsbuf.SetSmoothingMode(SmoothingModeHighQuality);
graphics.DrawImage(&buffer, 0, 0);
}
void CPOCDlg::OnMouseMove(UINT nFlags, CPoint point)
{
m_point = point;
InvalidateRect(circle,FALSE);
CDialogEx::OnMouseMove(nFlags, point);
}
BOOL CPOCDlg::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
Please let me know if i am doing any mistake.
You need to use so called double buffer technique to prevent flickering:
// create Mem DC
dcMemory = new CDC;
dcMemory->CreateCompatibleDC(pDC);
pDC->SetMapMode(MM_TEXT);
dcMemory->SetMapMode(MM_TEXT);
// TODO: draw to memDC here
//switch back to paint dc
pDC->BitBlt(rectDirty.left, rectDirty.top,
rectDirty.Width(), rectDirty.Height(),
dcMemory,
rectDirty.left,rectDirty.top,SRCCOPY);
dcMemory->DeleteDC();
delete dcMemory;
dcMemory = NULL;
I want a dialog to be borderless and yet have a dialog shadow. I came across this solution Borderless Window Using Areo Snap, Shadow, Minimize Animation, and Shake which uses a workaround by making the Dialog having a Margin of 1 px and extending the Client Area to it.
MARGINS borderless = { 1, 1, 1, 1 };
DwmExtendFrameInfoClientArea(this->GetSafeHwnd(), &borderless);
The post mentioned that the Client Area is literally being extended and Transparent drawing makes the Dialog edges of 1px each visible again.
Now this is exactly what happened, when I tried to paint a Solid Rectangle onto the whole dialog:
// getting the client area
CRect clientRect;
GetClientRect(&clientRect);
// expanding it to the new margins
clientRect.left -= 1;
clientRect.top -= 1;
clientRect.right += 2;
clientRect.bottom += 2;
// set the Device Context to draw non transparent and with a black background
pDC->SetBkMode(OPAQUE);
pDC->SetBkColor(RGB(0, 0, 0));
// finally draw a rectangle to it
CBrush brush_back_ground(RGB(0, 0, 0));
pDC->FillRect(clientRect, &brush_back_ground);
But the dialog is still drawn with its margins:
How would it be possible to draw something stretched on the margins? Later I'm going to use pictures as dialog Background which should be drawn on the margins aswell.
Thanks to Hans Passant for his comment. The solution is to use GDI+ drawing instead of GDI drawing
// making a Gdi+ graphics object from my CDC*
Graphics g(*pDC);
// getting the client area
CRect clientRect;
GetClientRect(&clientRect);
// making a Gdi+ rect
Rect bkRect(0,0,clientRect.Width(), clientRect.Height());
// making a pen for the Rect Drawing
Pen bkPen(Color(255,0,0,0));
// draw the rectangle over the full dialog
g.DrawRectangle(&bkPen, bkRect);
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