Why don't the calls to LineTo & SetPixel draw anything? - c++

I've written a simple MFC application to draw a polygon in a dialog, the complete code being here.
The code opens a dialog, with default standard grey background, defines
std::vector<CPoint> m_LeftPolygon;
then does as following:
void DrawPitons(std::vector<CPoint> points, COLORREF rgbColor, HDC hDC)
{
static unsigned short XDiff[7] = { 5,4,4,3,2,1,0 },
YDiff[7] = { 0,1,2,3,4,4,5 };
for (unsigned pnt = 0; pnt < points.size(); pnt++)
{
SetPixel(hDC, points[pnt].x, points[pnt].y, rgbColor);
for (unsigned short i = 0; i < 7; i++)
{
SetPixel(hDC, points[pnt].x + XDiff[i], points[pnt].y + YDiff[i], rgbColor);
SetPixel(hDC, points[pnt].x + XDiff[i], points[pnt].y - YDiff[i], rgbColor);
SetPixel(hDC, points[pnt].x - XDiff[i], points[pnt].y + YDiff[i], rgbColor);
SetPixel(hDC, points[pnt].x - XDiff[i], points[pnt].y - YDiff[i], rgbColor);
}
}
}
void CROIDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CPaintDC dc(this); // device context for painting
HDC hDC = dc.GetSafeHdc();
HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)),
oldPen = (HPEN)SelectObject(hDC, hPen);
SetROP2(hDC, R2_COPYPEN);
// Draw the polygon
if (m_LeftPolygon.size() > 1)
{
BOOL stat = MoveToEx(hDC, (int)m_LeftPolygon[0].x, (int)m_LeftPolygon[0].y, NULL);
for (size_t index = 1; index < m_LeftPolygon.size(); index++)
stat = LineTo(hDC, (int)m_LeftPolygon[index].x, (int)m_LeftPolygon[index].y);
stat = LineTo(hDC, (int)m_LeftPolygon[0].x, (int)m_LeftPolygon[0].y);
}
// Draw the control points
DrawPitons(m_LeftPolygon, RGB(255, 0, 0), hDC);
SelectObject(hDC, oldPen);
DeleteObject(hPen);
}
}
void CROIDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
m_LeftPolygon.push_back(point);
SendMessage(WM_PAINT);
}
For some reason, nothing is drawn, though I would expect the pitons and connecting lines to be drawn in red over the grey background.
What am I missing?

Related

Get coordinates of specified color of pixel on screen

im making a game bot, and in some moments it must find (on the whole screen) a specified color of some pixel(without specified coordinates), and if it has founded it, bot has to print coordinates(x, y) of founded color.
I have a this example
int click_color = color;
HDC dc = GetDC(hWnd);
COLORREF click_col = GetPixel(dc, x, y);
ReleaseDC(NULL, dc);
it works fine, but it search for a color on a specified coordinates. But i need it the other way around, to search it on the whole screen and print coordinates of that color.
Can anyone help me?
Sorry for my broken English)
I'm not aware of any function that does that for you, so I believe your best shot would be to look through every pixel coordinate to check if the color corresponds. Obviously the GetPixel() funtion is too slow for that, so it would be best to capture the entirity of the screen and then analyze sequentially the pixels salved. When I need to do something like this I use this class after including Windows.h:
class screenshot
{
public:
BYTE* lpbitmap;
int horizontal;
int vertical;
COLORREF* pxMap;
private:
HDC hScreenDC;
HDC hMemoryDC;
HBITMAP hBitmap;
HBITMAP hOldBitmap;
RECT desktop;
const HWND hDesktop = GetDesktopWindow();
BITMAPINFOHEADER bi;
DWORD dwBmpSize;
HANDLE hDIB;
int x;
int y;
union color
{
int col;
unsigned char abgr[4];
};
public:
screenshot()
{
hScreenDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
hMemoryDC = CreateCompatibleDC(hScreenDC);
x = GetDeviceCaps(hScreenDC, HORZRES);
y = GetDeviceCaps(hScreenDC, VERTRES);
GetWindowRect(hDesktop, &desktop);
horizontal = desktop.right;
vertical = desktop.bottom;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = horizontal;
bi.biHeight = vertical;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmpSize = ((horizontal * bi.biBitCount + 31) / 32) * 4 * vertical;
pxMap = new COLORREF[dwBmpSize];
lpbitmap = new BYTE[dwBmpSize];
hDIB = GlobalAlloc(GHND, dwBmpSize);
hBitmap = CreateCompatibleBitmap(hScreenDC, x, y);
}
void capture()
{
hOldBitmap = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
BitBlt(hMemoryDC, 0, 0, horizontal, vertical, hScreenDC, 0, 0, SRCCOPY);
hBitmap = (HBITMAP)SelectObject(hMemoryDC, hOldBitmap);
GetDIBits(hMemoryDC, hBitmap, 0, (UINT)vertical, lpbitmap, (BITMAPINFO*)&bi, DIB_RGB_COLORS);
GetObject(hBitmap, sizeof(lpbitmap), &lpbitmap);
BYTE* img;
for (int Y = 0; Y < vertical; Y++)
{
for (int X = 0; X < horizontal; X++)
{
img = lpbitmap + ((vertical - 1 - Y) * horizontal + X) * 4;
pxMap[Y * horizontal + X] = RGB(img[2], img[1], img[0]);
}
}
}
~screenshot()
{
GlobalFree(hDIB);
DeleteDC(hMemoryDC);
DeleteDC(hScreenDC);
}
COLORREF getPixel(int X, int Y)
{
//300 414
return pxMap[Y * horizontal + X];
}
int getPixelRed(int X, int Y)
{
color col;
col.col = pxMap[Y * horizontal + X];
return col.abgr[0];
}
int getPixelGreen(int X, int Y)
{
color col;
col.col = pxMap[Y * horizontal + X];
return col.abgr[1];
}
int getPixelBlue(int X, int Y)
{
color col;
col.col = pxMap[Y * horizontal + X];
return col.abgr[2];
}
};
Simply create an instance of it, capture a screenshot when you need to and go nuts analyzing the returned pixels.

winAPI Rotating an Image on Screen while Keeping It Centered and the Background Updated

I'm writing code where a user can pick an image from their computer and rotate it on screen. However, there are two problems that I'm having currently. First, I realized that if the image is rectangular, you can see the old picture before it was rotated behind the new rotated image. Second, when I rotated the image, it seemed to rotate around a certain point on the picture, making the picture go off-screen sometimes. So I wanted to know how I would both keep the old image from showing after I rotated the iamge and also how I would keep the image centered to the screen.
This is my rotate code:
int flip = 1;
void rotateImage(HWND hWnd)
{
HDC hdc = GetDC(hWnd);
Graphics graphic(hdc);
Image* image = Image::FromFile(filePath);
int x = (GetSystemMetrics(SM_CXSCREEN) - image->GetWidth()) / 2;
int y = (GetSystemMetrics(SM_CYSCREEN) - image->GetHeight()) / 2 - 50;
int xx = image->GetWidth();
int yy = image->GetHeight();
if (flip == 1)
image->RotateFlip(Rotate90FlipNone);
else if (flip == 2)
image->RotateFlip(Rotate180FlipNone);
else if (flip == 3)
image->RotateFlip(Rotate270FlipNone);
RECT rc;
HBRUSH hBr;
SetRect(&rc, x, y, x + xx, y + yy);
hBr = CreateSolidBrush(RGB(255, 255, 255));
FillRect(hdc, &rc, hBr);
Status status = graphic.DrawImage(image, x, y);
RECT updateRect = { 0 };
updateRect.left = x;
updateRect.top = y;
updateRect.right = updateRect.left + image->GetWidth();
updateRect.bottom = updateRect.top + image->GetHeight();
flip++;
if (flip > 4) flip = 1;
ReleaseDC(hWnd, hdc);
}
This part of the code
RECT rc;
HBRUSH hBr;
SetRect(&rc, x, y, x + xx, y + yy);
hBr = CreateSolidBrush(RGB(255, 255, 255));
FillRect(hdc, &rc, hBr);
was me trying to solve the issue of the old image appearing after a rotation, but it seems that it cuts out too much of the window and deletes the controls on the window as well.
Some tips:
Each call to GdiplusStartup should be paired with a call to GdiplusShutdown.
Compare window width and height with image's.
Do drawing work in WM_PAINT message
Use window client RECT instead of screen RECT to draw image.
Get image width and heigth after rotate the image.
winAPI Rotating an Image on Screen while Keeping It Centered and the
Background Updated
The following code piece shows mentioned modifications and can achieve this purpose for me. You can refer to.
BOOL fRotate = FALSE;
BOOL fFileOpened = FALSE;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HRESULT hr;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
AddMenus(hWnd);
AddControls(hWnd);
hr = BufferedPaintInit();
break;
case WM_COMMAND:
switch (wParam)
{
case FILE_MENU_EXIT:
// File Menu Exit
DestroyWindow(hWnd);
break;
case FILE_OPEN:
fFileOpened = FALSE;
OpenFileWindow(hWnd);
InvalidateRect(hWnd, NULL, FALSE);
break;
case PIC_EDIT:
if (fFileOpened)
{
displayDialogW(hWnd);
}
else
MessageBoxA(NULL, "Pick an Image File to Edit!", "Error!", MB_ICONINFORMATION | MB_OKCANCEL);
break;
case PIC_ROTATE:
if (fFileOpened)
{
fRotate = TRUE;
InvalidateRect(hWnd, NULL, TRUE);
}
else
MessageBoxA(NULL, "Pick an Image File to Rotate!", "Error!", MB_ICONINFORMATION | MB_OKCANCEL);
break;
}
break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC screen = BeginPaint(hWnd, &ps);
// 3. Do draw work in WM_PAINT message
if (fRotate)
{
rotateImage(hWnd);
fRotate = FALSE;
}
else if (fFileOpened)
{
HPAINTBUFFER hbuff = BeginBufferedPaint(ps.hdc, &ps.rcPaint, BPBF_COMPATIBLEBITMAP, NULL, &screen);
if (hbuff)
{
RECT rc;
GetClientRect(hWnd, &rc);
FillRect(screen, &rc, GetSysColorBrush(COLOR_WINDOW));
putImage(screen, hWnd);
hr = EndBufferedPaint(hbuff, TRUE);
}
}
EndPaint(hWnd, &ps); } break;
case WM_DESTROY:
BufferedPaintUnInit();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
void OpenFileWindow(HWND hWnd)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
IFileOpenDialog* pFileOpen;
// Create the FileOpenDialog object.
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
if (SUCCEEDED(hr))
{
// Show the Open dialog box.
hr = pFileOpen->Show(NULL);
// Get the file name from the dialog box.
if (SUCCEEDED(hr))
{
IShellItem* pItem;
hr = pFileOpen->GetResult(&pItem);
if (SUCCEEDED(hr))
{
PWSTR pszFilePath;
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
// Display the file name to the user.
if (SUCCEEDED(hr))
{
char szBuffer[255];
WideCharToMultiByte(CP_ACP, 0, pszFilePath, -1, szBuffer, sizeof(szBuffer), NULL, NULL);
// JPG/JPEG/PNG
filePath = pszFilePath;
fFileOpened = TRUE;
CoTaskMemFree(pszFilePath);
}
pItem->Release();
}
}
pFileOpen->Release();
}
CoUninitialize();
}
}
void putImage(HDC hdc, HWND hWnd)
{
Graphics graphic(hdc);
Image* image = Image::FromFile(filePath);
// 4. Use window client RECT instead of screen RECT to draw image.
RECT clientRect;
GetClientRect(hWnd, &clientRect);
LONG cx = clientRect.right - clientRect.left;
LONG cy = clientRect.bottom - clientRect.top;
// TODO: 2. compare window width and height with image's before subtract.
int x = (cx - image->GetWidth()) / 2;
int y = (cy - image->GetHeight()) / 2;
Status status = graphic.DrawImage(image, x, y);
#if 1 //For testing purpose and feel free to remove.
// Draw a line at window middle for checking is the image is centered
LONG xMid = cx / 2;
LONG yMid = cy / 2;
Pen pen(Color(255, 0, 0, 255));
graphic.DrawLine(&pen, xMid, 0, xMid, clientRect.bottom);
graphic.DrawLine(&pen, 0, yMid, clientRect.right, yMid);
#endif //
}
int flip = 1;
void rotateImage(HWND hWnd)
{
HDC hdc = GetDC(hWnd);
Graphics graphic(hdc);
Image* image = Image::FromFile(filePath);
// 4. Use window client RECT instead of screen RECT to draw image.
RECT clientRect;
GetClientRect(hWnd, &clientRect);
LONG cx = clientRect.right - clientRect.left;
LONG cy = clientRect.bottom - clientRect.top;
if (flip == 1)
image->RotateFlip(Rotate90FlipNone);
else if (flip == 2)
image->RotateFlip(Rotate180FlipNone);
else if (flip == 3)
image->RotateFlip(Rotate270FlipNone);
// 5. Get image width and heigth after rotate
int xx = image->GetWidth();
int yy = image->GetHeight();
// TODO: 2. compare window width and height with image's before subtract.
int x = (cx - xx) / 2;
int y = (cy - yy) / 2;
RECT rc;
HBRUSH hBr;
SetRect(&rc, x, y, x + xx, y + yy);
hBr = CreateSolidBrush(RGB(255, 255, 255));
FillRect(hdc, &rc, hBr);
Status status = graphic.DrawImage(image, x, y);
// Draw a line at window middle
LONG xMid = cx / 2;
LONG yMid = cy / 2;
Pen pen(Color(255, 0, 0, 255));
graphic.DrawLine(&pen, xMid, 0, xMid, clientRect.bottom);
graphic.DrawLine(&pen, 0, yMid, clientRect.right, yMid);
flip++;
if (flip > 4) flip = 1;
ReleaseDC(hWnd, hdc);
}
Update: Add result of an image not working for OP.

How do I draw an array made bitmap on screen using bitblt?

Instead of drawing using Moveto and LineTo, I want to use a hand made bitmap, that I will fill with an array that I will create myself, and use that to fill the screen.
Right now, the array is just filled with red,
But when I draw to the screen I get all black.
This is the code:
void CCGWorkView::OnDraw(CDC* pDC)
{
CCGWorkDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
pDCToUse->FillSolidRect(&r, world.bg_color);
BITMAPINFO bminfo;
CPaintDC hdc(this);
CRect rect;
GetWindowRect(&rect);
int h = rect.bottom - rect.top,
w = rect.right - rect.left;
int *bits = new int[w * h];
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP bm = CreateCompatibleBitmap(hdc, w, h);
SelectObject(hdcMem, bm);
bminfo.bmiHeader.biSize = sizeof(bminfo.bmiHeader);
bminfo.bmiHeader.biWidth = w;
bminfo.bmiHeader.biHeight = h;
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biCompression = BI_RGB;
bminfo.bmiHeader.biSizeImage = 0;
bminfo.bmiHeader.biXPelsPerMeter = 1;
bminfo.bmiHeader.biYPelsPerMeter = 1;
bminfo.bmiHeader.biClrUsed = 0;
bminfo.bmiHeader.biClrImportant = 0;
for (int i = 0; i < w * h; i++) {
bits[i] = RGB(255, 0, 0);
}
SetDIBits(hdcMem, bm, 0, h, bits, &bminfo, 0);
BitBlt(hdc, rect.left, rect.top, w, h, hdcMem, rect.left, rect.top, SRCCOPY);
DeleteDC(hdcMem);
DeleteObject(bm);
delete bits;
}
There are a couple of issues in your code.
First, you don’t need CPaintDC, as the pDC is passed into your OnDraw() function.
This may have actually caused your black display, as the newly created DC has a one pixel black-and-white bitmap selected into it, and when you call CreateCompatibleBitmap(), that bitmap is also monochrome.
Second, SetDIBits() expect RGBQUAD colors (https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-rgbquad), NOT RGB.
And, as Constantine Georgiou suggested, you should de-select your bitmap out of DC before deleting it to avoid resource leaks, even if MFC handles it for you.
Here is modified code:
void CMFCApplication1View::OnDraw(CDC* pDC)
{
CMFCApplication1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
//pDCToUse->FillSolidRect(&r, world.bg_color);
BITMAPINFO bminfo;
CRect rect;
GetClientRect(&rect);
int h = rect.bottom - rect.top,
w = rect.right - rect.left;
int* bits = new int[w * h];
HDC hdcMem = CreateCompatibleDC(pDC->m_hDC);
HBITMAP bm = CreateCompatibleBitmap(pDC->m_hDC, w, h);
HGDIOBJ hOld = SelectObject(hdcMem, bm);
bminfo.bmiHeader.biSize = sizeof(bminfo.bmiHeader);
bminfo.bmiHeader.biWidth = w;
bminfo.bmiHeader.biHeight = h;
bminfo.bmiHeader.biPlanes = 1;
bminfo.bmiHeader.biBitCount = 32;
bminfo.bmiHeader.biCompression = BI_RGB;
bminfo.bmiHeader.biSizeImage = 0;
bminfo.bmiHeader.biXPelsPerMeter = 1;
bminfo.bmiHeader.biYPelsPerMeter = 1;
bminfo.bmiHeader.biClrUsed = 0;
bminfo.bmiHeader.biClrImportant = 0;
RGBQUAD red = { 0, 0, 255, 0 };
for (int i = 0; i < w * h; i++) {
bits[i] = *((int*)&red);
}
SetDIBits(hdcMem, bm, 0, h, bits, &bminfo, DIB_RGB_COLORS);
BitBlt(pDC->m_hDC, rect.left, rect.top, w, h, hdcMem, rect.left, rect.top, SRCCOPY);
SelectObject(hdcMem, hOld);
DeleteDC(hdcMem);
DeleteObject(bm);
delete[] bits;
}

The function d3ddev->Present() doesn't work when I copy the backbuffer to the screen

When I use d3ddev->Present() to copy the back buffer to the screen, nothing happened (the return value is D3D_OK). When I create a window without titlebar such as WS_POPUP, it works. Is there someone who can tell me why? Thanks.
and sorry for poor English.
win10, Direct3D9
window without titlebar
window with titlebar
...
//Game update function
void Game_Run(HWND hwnd)
{
//make sure the Direct3D device is valid
if (!d3ddev) return;
//start rendering
if (SUCCEEDED(d3ddev->BeginScene())) {
//fill the surface with random color
int r = rand() % 255;
int g = rand() % 255;
int b = rand() % 255;
d3ddev->ColorFill(surface, NULL, D3DCOLOR_XRGB(r, g, b));
//copy the surface to the backbuffer
RECT rect;
rect.left = rand() % SCREENW / 2;
rect.right = rect.left + rand() % SCREENW / 2;
rect.top = rand() % SCREENH / 2;
rect.bottom = rect.top + rand() % SCREENH / 2;
d3ddev->StretchRect(surface, NULL, backbuffer, &rect, D3DTEXF_NONE);
//stop rendering
d3ddev->EndScene();
//copy the back buffer to the screen
d3ddev->Present(NULL, NULL, NULL, NULL);
}
//check for escape key
if (KEY_DOWN(VK_ESCAPE))
PostMessage(hwnd, WM_DESTROY, 0, 0);
}
...
//create a new window
HWND hwnd = CreateWindow(
"MainWindowClass",
APPTITLE.c_str(),
WS_POPUP, //it works
//WS_OVERLAPPEDWINDOW, it doesn't work
CW_USEDEFAULT, CW_USEDEFAULT,
SCREENW, SCREENH,
NULL, NULL, hInstance, NULL);

MFC, Drawing text in memory context (printing)

I got stuck with a problem - I need to create a bitmap in memory, draw some text i it and save it as a BMP file and then print out the bitmap with physical printer. I can do this drawing in the dialog window context - it works fine. But when I try to do the same drawing in printer context the text doesn't appear. I really can't figure out why it is so. Please, help me guys. Thanks in advance. Here is the code:
void CMy2Dlg::OnButton1()
{
// TODO: Add your control notification handler code here
CPrintDialog pd(false);
if (pd.DoModal()==IDOK)
{
CDC PrintDC;
HDC hdc = pd.CreatePrinterDC();
PrintDC.Attach(hdc);
DOCINFO infStru;
::ZeroMemory (&infStru, sizeof (DOCINFO));
CString title="Print test";
infStru.cbSize = sizeof (DOCINFO);
infStru.lpszDocName=title;
infStru.lpszOutput=NULL;
PrintDC.StartDoc(&infStru);
PrintDC.StartPage();
{
CRect r, r2;
CBitmap memBMP, * pOldBitmap;
CPaintDC dc(this);
CDC memDC, *pDC = &memDC;
CFont font, * pOldFont;
int width = 2000;
int height = 1500;
int textwidth = 300;
int textheight = 150;
int oldMapMode = 0;
int oldbkmode = 0;
int i, j;
LOGFONT logFont, lf;
COLORREF oldTextColor;
memset(&logFont, 0, sizeof(logFont));
logFont.lfHeight = 16;
logFont.lfWidth = 0;
logFont.lfEscapement = 0;
logFont.lfOrientation = 0;
logFont.lfWeight = FW_NORMAL;
logFont.lfItalic = FALSE;
logFont.lfUnderline = FALSE;
logFont.lfStrikeOut = 0;
logFont.lfCharSet = ANSI_CHARSET;
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logFont.lfQuality = DEFAULT_QUALITY;
logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
strcpy(logFont.lfFaceName, "Arial");
if(memDC.CreateCompatibleDC(&PrintDC)) {
if (memBMP.CreateCompatibleBitmap(&PrintDC, width, height)) {
pOldBitmap = pDC->SelectObject(&memBMP);
pDC->FillSolidRect(0, 0, width, height, RGB(200, 200, 200));
oldTextColor = pDC->SetTextColor(RGB(255,0,0));
oldMapMode = pDC->SetMapMode(MM_LOMETRIC);
oldbkmode = pDC->SetBkMode(TRANSPARENT);
lf = logFont;
lf.lfHeight = -MulDiv(lf.lfHeight, GetDeviceCaps(pDC->GetSafeHdc(), LOGPIXELSY), 72);
//lf.lfHeight = 100;
font.CreateFontIndirect(&lf);
pOldFont = pDC->SelectObject(&font);
r.left = 10;
r.top = 10;
r.right = r.left + textwidth;
r.bottom = r.top + textheight;
r.top *= -1;
r.bottom *= -1;
pDC->MoveTo(r.left, r.top);
pDC->LineTo(r.right, r.top);
pDC->LineTo(r.right, r.bottom);
pDC->LineTo(r.left, r.bottom);
pDC->LineTo(r.left, r.top);
pDC->DrawText("qwerty", &r, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
pDC->SetMapMode(oldMapMode);
pDC->SetTextColor(oldTextColor);
pDC->SetBkMode(oldbkmode);
PrintDC.BitBlt(10, 10, width, height, pDC, 0, 0, SRCCOPY);
pDC->SelectObject(pOldBitmap);
pDC->SelectObject(pOldFont);
font.DeleteObject();
memBMP.DeleteObject();
pDC->DeleteDC();
}
}
}
PrintDC.EndPage();
PrintDC.EndDoc();
PrintDC.Detach();
DeleteDC(hdc);
}
}
If SetMapMode(MM_LOMETRIC) is used on memory DC, then memory DC has to be drawn upside down when using BitBlt to copy to printer/display DC. The width/height will have to be adjusted as well. Just use the default map mode (MM_TEXT). Use SetMapMode(MM_LOMETRIC) when you are drawing on printer DC and you want that specific measurement units.
void CMy2Dlg::OnButton1()
{
//create the bitmap
int w = 600, h = 400;
CClientDC dc(this);
CBitmap bmp;
CDC memdc;
memdc.CreateCompatibleDC(&dc);
bmp.CreateCompatibleBitmap(&dc, w, h);
auto oldbmp = memdc.SelectObject(bmp);
//draw on bitmap
memdc.FillSolidRect(0, 0, w, h, RGB(200, 200, 200));
memdc.SetTextColor(RGB(255, 0, 0));
CRect rc(0, 0, w, h);
memdc.DrawText(L"qwerty", &rc, 0);
dc.BitBlt(0, 0, w, h, &memdc, 0, 0, SRCCOPY);//optional: draw the bitmap on dialog
CPrintDialog pd(false);
if(pd.DoModal() == IDOK)
{
CDC PrintDC;
HDC hdc = pd.GetPrinterDC();
PrintDC.Attach(hdc);
DOCINFO docinfo = { sizeof(docinfo) };
docinfo.lpszDocName = L"Print test";
PrintDC.StartDoc(&docinfo);
PrintDC.StartPage();
PrintDC.BitBlt(0, 0, w, h, &memdc, 0, 0, SRCCOPY);
PrintDC.EndPage();
PrintDC.EndDoc();
}
dc.SelectObject(oldbmp);
}