I have the following code:
POINT p;
int main(void) {
HDC hdc = GetDC(NULL);
while(!GetAsyncKeyState(VK_F1)) {
GetCursorPos(&p);
SetPixel(hdc, p.x, p.y, RGB(73, 214, 0));
}
DeleteObject(hdc);
}
What I want to achive is when I move mouse the pixel at curent cursor position changes its color until the program is stopped. However I see a few issues here:
The pixel is drawn below cursor position (resolution?) and after some time all pixels changes to default color. How Can I resolve the problem? Thanks for any help.
Related
I'm trying to make smooth animations in the console window in c++. I'm using windows.h for functions like Ellipse, and LineTo. The issue is that the frames are very slow and blink a lot. Sometimes the frames get progressively slower and slower as the program moves along. I tried animating a circle that moves down to the right, and a line that goes from the upper left corner to wherever the circle is. When I used the LineTo function, the line was black. I don't know how to color it. Any help would be appreciated, I just want to be able to draw and animate in the console.
#include <windows.h>
void drawSprt(int x, int y) {
HWND handle = GetConsoleWindow();
HDC dc = GetDC(handle);
int r = 10;
int a;
COLORREF color = 0x00FFFFFF;
Ellipse( dc, x-r,y-r,x+r,y+r);
MoveToEx( dc, 0, 0, NULL);
LineTo( dc, x+r, y+r);
ReleaseDC(handle, dc);
}
int main() {
int x = 100;
int y = 100;
start:
drawSprt(x,y);
Sleep(500);
x+=5;
y+=5;
system("cls");
goto start;
}
I'm currently using 5MP Camera, so I convert BYTE* to GDI+ Bitmap object and uses Graphics object to draw on picture control (all GDI+ objects)
and I want to draw a string on it and when I do so, resolution (quality or whatsoever) gets strange. here're the images.
this is the original image
this is the image with the text on it
And here's my code. it uses MFC's WM_MOUSEMOVE. and when mouse pointer gets on CRect(dispRC[array]), it renders string "aa" on the Bitmap object.
and when I do so, quality of image gets lower or I don't exactly know it changes the IMAGE. (You might not notice because those are captured images, but latter image's quality gets lower.)
void CSmall_StudioDlg::OnMouseMove(UINT nFlags, CPoint point)
{
CPoint insidePoint;
// MAXCAM is the number of bitmap objects.
for (int i = 0; i < MAXCAM; i++)
{
// m_pBitmap[MAXCAM] is array of Bitmap* which contains address of Gdiplus::Bitmap objects.
if (m_pBitmap[i] != NULL)
{
// m_rcDisp[MAXCAM] are CRect objects which has information of picture control.
// i.e. GetDlgItem(IDC_BIN_DISP)->GetWindowRect(m_rcDisp[BINARY_VID]);
if (point.x > m_rcDisp[i].TopLeft().x && point.y > m_rcDisp[i].TopLeft().y)
{
if (point.x < m_rcDisp[i].BottomRight().x && point.y < m_rcDisp[i].BottomRight().y)
{
StringFormat SF;
insidePoint.x = point.x - m_rcDisp[i].TopLeft().x;
insidePoint.y = point.y - m_rcDisp[i].TopLeft().y;
Graphics textG(m_pBitmap[i]);
textG.SetTextRenderingHint(TextRenderingHintSingleBitPerPixel);
Gdiplus::Font F(L"Palatino Linotype Bold", 10, FontStyleBold, UnitPixel);
RectF R(insidePoint.x, insidePoint.y, 20, 100);
SF.SetAlignment(StringAlignmentCenter);
SF.SetLineAlignment(StringAlignmentCenter);
SolidBrush B(Color(0, 0, 0));
textG.DrawString(_T("aa"), -1, &F, R, &SF, &B);
// m_pGraphics[MAXCAM] is made like this
// i.e.
// static CClientDC roiDc(GetDlgItem(IDC_ROI_DISP));
// m_hDC[ROI_VID] = roiDc.GetSafeHdc();
// m_pGraphics[ROI_VID] = Graphics::FromHDC(m_hDC[ROI_VID]);
m_pGraphics[i]->DrawImage(m_pBitmap[i], 0, 0, m_vidwidth[i], m_vidheight[i]);
}
}
}
}
CDialogEx::OnMouseMove(nFlags, point);
}
Hope I get a helpful answer.
Thanks!
I had a similar problem and solved it by creating the GDI+ font from a Windows font like this:
Gdiplus::Font font(hDc, hFont);
where hDc is a DC handle and hFont is a font handle.
Can you try if this helps?
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 have a program which draw a Rectangle under mouse cursor and show the pixel color, but I can't manage it to clear the shape inside the while loop, if I use 'InvalidateRect()' it clear rectangle too fast and flickering, if not use 'InvalidateRect()' then Rectangle keep duplicating like THIS, how to fix that?
HWND hwnd;
POINT p;
unsigned short R=0, G=0, B=0;
void drawRect()
{
GetCursorPos(&p);
HDC hdc = GetDC(NULL);
HPEN border = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
HBRUSH background = CreateSolidBrush(RGB(R, G, B));
SelectObject(hdc, border);
SelectObject(hdc, background);
Rectangle(hdc, p.x+10, p.y+10, p.x+40, p.y+40);
DeleteObject(border);
DeleteObject(background);
}
void init()
{
while (GetAsyncKeyState(VK_RBUTTON) & 0x8000)
{
grabPixel(); //get RGB color from cursor coordination
drawRect(); //draw preview rectangle under cursor
InvalidateRect(hwnd, NULL, true);
}
}
Note: it doesn't have WinMain() or WndProc()
There are all sorts of things wrong with this. What are you actually trying to do?
From the fact that you're using GetDC(NULL), it looks like this is supposed to be drawing a rectangle on the entire screen.
Where is the hwnd value coming from? If that window does have a message loop (and it probably does), then that's the window being invalidated and redrawing itself.
A note: InvalidateRect merely marks the rectangle as needing-to-be-painted the next time that that application's (actually thread's, more-or-less) message queue is empty. UpdateWindow will cause a WM_PAINT message to be sent immediately.
drawRect isn't cleaning up properly, either. It should call ReleaseDC when it's finished, and it ought to restore the previous drawing objects after it's finished (and most definitely before it deletes them) as well:
HBRUSH oldBackground = SelectObject(hDC, background);
// ...
SelectObject(hDC, oldBackground);
What you probably want to do is, when selection starts, create a window the size of the screen and copy the existing screen into it. Then you can draw all over that intelligently.
The DrawDragRect function (see my blog) is designed for this sort of thing.