MFC. How to display a bitmap or a .png file
-
Thank You. I copied the sample code over, and I have noticed the following: 1) If I draw the bitmap first, and then draw the board afterwards, I can see the board and the test bitmap. 2) If I draw the board first and then the test bitmap, I only see the board. The loadBitmap call is successfull)
-
Thank You. Appreciate it.
Okay, you have an error in your code: // Copy the bits from the memory DC into the current dc pDC->BitBlt(20, 10, 436, 364, &MemDCLady, 0, 0, SRCCOPY); is the culprit. Recall that you've set your coordinate system to low English which fixes the bassackwardness of drawing. If you trace your board generation, you will see that your Y values go from 0 to negative values. Looking at the above line, you are drawing off the top of your view window. Change the 364 to -364 and you'll see your image. Of course, *I've* never done that :)
Charlie Gilley “They who can give up essential liberty to obtain a little temporary safety deserve neither liberty nor safety.” BF, 1759 Has never been more appropriate.
-
Thank You. Appreciate it.
-
That's rather strange. Do you use the same DC for the board and bitmap?
"In testa che avete, Signor di Ceprano?" -- Rigoletto
Yes, I do.
-
Yes, I do.
Post the complete contents of both your [WM_PAINT](https://learn.microsoft.com/en-us/windows/win32/gdi/wm-paint) and [WM_ERASEBKGND](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-erasebkgnd). I can help but I need to see both.
-
Post the complete contents of both your [WM_PAINT](https://learn.microsoft.com/en-us/windows/win32/gdi/wm-paint) and [WM_ERASEBKGND](https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-erasebkgnd). I can help but I need to see both.
Here is my onDraw()
void CMyChessTestView::OnDraw(CDC* pDC)
{
CMyChessTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;// TODO: add draw code for native data here // Draw the empty board.... drawImage(pDC, 100, 100); drawEmptyBoard(pDC);
}
Here is the drawImage(...)
void CMyChessTestView::drawImage(CDC* pDC, int x, int y)
{// load IDB\_BITMAP1 from our resources CBitmap bmp; if (bmp.LoadBitmap(IDB\_LADYPIC)) { // Get the size of the bitmap BITMAP bmpInfo; bmp.GetBitmap(&bmpInfo); // Create an in-memory DC compatible with the // display DC we're using to paint CDC dcMemory; dcMemory.CreateCompatibleDC(pDC); // Select the bitmap into the in-memory DC CBitmap \*pOldBitmap = dcMemory.SelectObject(&bmp); // Find a centerpoint for the bitmap in the client area CRect rect; GetClientRect(&rect); int nX = rect.left + (rect.Width() - bmpInfo.bmWidth) / 2; int nY = rect.top + (rect.Height() - bmpInfo.bmHeight) / 2; // Copy the bits from the in-memory DC into the on- // screen DC to actually do the painting. Use the centerpoint // we computed for the target offset. pDC->BitBlt(nX, nY, bmpInfo.bmWidth, bmpInfo.bmHeight, &dcMemory, 0, 0, SRCCOPY); dcMemory.SelectObject(pOldBitmap); } else { TRACE0("ERROR: Where's IDB\_LADYPIC?\\n"); }
}
Here is the drawEmptyBoard()
void CMyChessTestView::drawEmptyBoard(CDC* pDC)
{
CMyChessTestDoc* pBC = GetDocument();
ASSERT_VALID(pBC);
if (!pBC)
return;
//drawImage(pDC, 80, 80);
pDC->SetMapMode(MM_LOENGLISH);
pDC->SetWindowExt(800, 800);
//pDC->SetViewportOrg(testrec.Width(), testrec.Height());for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { COLORREF color = pBC->getSquare(i, j); CBrush brush(color); int x1 = (j \* 70) + 35; int y1 = (i \* -70) - 35; int x2 = x1 + 70; int y2 = y1 - 70; CRect rect(x1, y1, x2, y2); pDC->FillRect(rect, &brush); //pDC->Rectangle(rect); } } // Now draw the borders for (int x = 35; x <= 595; x += 70) { pDC->MoveTo(x, -35); pDC->LineTo(x, -595); } for (int y = -35; y >= -595; y -= 70) { pDC->MoveTo(35, y); pDC->LineTo(595, y); }
-
Here is my onDraw()
void CMyChessTestView::OnDraw(CDC* pDC)
{
CMyChessTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;// TODO: add draw code for native data here // Draw the empty board.... drawImage(pDC, 100, 100); drawEmptyBoard(pDC);
}
Here is the drawImage(...)
void CMyChessTestView::drawImage(CDC* pDC, int x, int y)
{// load IDB\_BITMAP1 from our resources CBitmap bmp; if (bmp.LoadBitmap(IDB\_LADYPIC)) { // Get the size of the bitmap BITMAP bmpInfo; bmp.GetBitmap(&bmpInfo); // Create an in-memory DC compatible with the // display DC we're using to paint CDC dcMemory; dcMemory.CreateCompatibleDC(pDC); // Select the bitmap into the in-memory DC CBitmap \*pOldBitmap = dcMemory.SelectObject(&bmp); // Find a centerpoint for the bitmap in the client area CRect rect; GetClientRect(&rect); int nX = rect.left + (rect.Width() - bmpInfo.bmWidth) / 2; int nY = rect.top + (rect.Height() - bmpInfo.bmHeight) / 2; // Copy the bits from the in-memory DC into the on- // screen DC to actually do the painting. Use the centerpoint // we computed for the target offset. pDC->BitBlt(nX, nY, bmpInfo.bmWidth, bmpInfo.bmHeight, &dcMemory, 0, 0, SRCCOPY); dcMemory.SelectObject(pOldBitmap); } else { TRACE0("ERROR: Where's IDB\_LADYPIC?\\n"); }
}
Here is the drawEmptyBoard()
void CMyChessTestView::drawEmptyBoard(CDC* pDC)
{
CMyChessTestDoc* pBC = GetDocument();
ASSERT_VALID(pBC);
if (!pBC)
return;
//drawImage(pDC, 80, 80);
pDC->SetMapMode(MM_LOENGLISH);
pDC->SetWindowExt(800, 800);
//pDC->SetViewportOrg(testrec.Width(), testrec.Height());for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { COLORREF color = pBC->getSquare(i, j); CBrush brush(color); int x1 = (j \* 70) + 35; int y1 = (i \* -70) - 35; int x2 = x1 + 70; int y2 = y1 - 70; CRect rect(x1, y1, x2, y2); pDC->FillRect(rect, &brush); //pDC->Rectangle(rect); } } // Now draw the borders for (int x = 35; x <= 595; x += 70) { pDC->MoveTo(x, -35); pDC->LineTo(x, -595); } for (int y = -35; y >= -595; y -= 70) { pDC->MoveTo(35, y); pDC->LineTo(595, y); }
-
No, It serves to demonstrate that if I draw the board first, the pieces will not show up, and that by drawing the piece first and then the board, all shows up.
-
No, It serves to demonstrate that if I draw the board first, the pieces will not show up, and that by drawing the piece first and then the board, all shows up.
BigSteve-O wrote:
if I draw the board first, the pieces will not show up, and that by drawing the piece first and then the board, all shows up.
Then why do you try to draw first the board? :confused:
-
No, It serves to demonstrate that if I draw the board first, the pieces will not show up, and that by drawing the piece first and then the board, all shows up.
OK, I was able to reproduce your issue, and with a bit of luck, to fix it. The problem arises when you change the DC mapping mode. Now while I am not an expert of mapping modes, this code displays the bitmap over the empty board: Inside
OnDraw
(is actuallyOnPaint
in my test app)//..
drawEmptyBoard(&dc);
drawImage(&dc, 105, -105); // note the negative y
//..While
drawImage
becomes/*..*/::drawImage(CDC* pDC, int x, int y)
{
CBitmap bmp;
if (bmp.LoadBitmap(IDB_LADYPIC))
{
BITMAP bmpInfo;
bmp.GetBitmap(&bmpInfo);CDC dcMemory; dcMemory.CreateCompatibleDC(pDC); dcMemory.SetMapMode(pDC->GetMapMode()); // as weird as it looks, the map mode is not the same, after CreateCompatibleDC // Select the bitmap into the in-memory DC CBitmap\* pOldBitmap = dcMemory.SelectObject(&bmp); pDC->StretchBlt(x, y, bmpInfo.bmWidth, bmpInfo.bmHeight, &dcMemory,0, 0, bmpInfo.bmWidth, -bmpInfo.bmHeight, SRCCOPY); // note the negative height of the bitmap dcMemory.SelectObject(pOldBitmap); }
}
To make things more explicit, I would move the
SetMapMode
call out ofdrawEmptyBoard
."In testa che avete, Signor di Ceprano?" -- Rigoletto
-
OK, I was able to reproduce your issue, and with a bit of luck, to fix it. The problem arises when you change the DC mapping mode. Now while I am not an expert of mapping modes, this code displays the bitmap over the empty board: Inside
OnDraw
(is actuallyOnPaint
in my test app)//..
drawEmptyBoard(&dc);
drawImage(&dc, 105, -105); // note the negative y
//..While
drawImage
becomes/*..*/::drawImage(CDC* pDC, int x, int y)
{
CBitmap bmp;
if (bmp.LoadBitmap(IDB_LADYPIC))
{
BITMAP bmpInfo;
bmp.GetBitmap(&bmpInfo);CDC dcMemory; dcMemory.CreateCompatibleDC(pDC); dcMemory.SetMapMode(pDC->GetMapMode()); // as weird as it looks, the map mode is not the same, after CreateCompatibleDC // Select the bitmap into the in-memory DC CBitmap\* pOldBitmap = dcMemory.SelectObject(&bmp); pDC->StretchBlt(x, y, bmpInfo.bmWidth, bmpInfo.bmHeight, &dcMemory,0, 0, bmpInfo.bmWidth, -bmpInfo.bmHeight, SRCCOPY); // note the negative height of the bitmap dcMemory.SelectObject(pOldBitmap); }
}
To make things more explicit, I would move the
SetMapMode
call out ofdrawEmptyBoard
."In testa che avete, Signor di Ceprano?" -- Rigoletto
Thank you so much for your suggestions. It is much appreciated! I am going to try it soon.
-
Thank you so much for your suggestions. It is much appreciated! I am going to try it soon.
-
Good Morning. In my view class in the onDraw() function, I am drawing the board and filling in the squares as follows:
pDC->SetMapMode(MM\_LOENGLISH); pDC->SetWindowExt(800, 800); //pDC->SetViewportOrg(testrec.Width(), testrec.Height()); for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { COLORREF color = pBC->getSquare(i, j); CBrush brush(color); int x1 = (j \* 70) + 35; int y1 = (i \* -70) - 35; int x2 = x1 + 70; int y2 = y1 - 70; CRect rect(x1, y1, x2, y2); pDC->FillRect(rect, &brush); } } // Now draw the borders for (int x = 35; x <= 595; x += 70) { pDC->MoveTo(x, -35); pDC->LineTo(x, -595); } for (int y = -35; y >= -595; y -= 70) { pDC->MoveTo(35, y); pDC->LineTo(595, y); }
This all works well, and I have my board coming up.
Now I want to draw the chess pieces on the board, and have written some code, just to load 1 bitgmap and display it on the screen. However, nothing gets drawn to the screen. (All I see is just the chessboard)
This is the test code to display my bitmap on the screen:
void CMyChessTestView::drawImage(CDC* pDC, int x, int y)
{CPaintDC dc(this); // device context for painting // TODO: Add your message handler code here CBitmap BmpLady; CDC MemDCLady; // Load the bitmap from the resource BmpLady.LoadBitmap(IDB\_BISHOP\_WHITE); // Create a memory device compatible with the above CPaintDC variable MemDCLady.CreateCompatibleDC(/\*&dc\*/pDC); // Select the new bitmap CBitmap \*BmpPrevious = MemDCLady.SelectObject(&BmpLady); // Copy the bits from the memory DC into the current dc pDC->BitBlt(20, 10, 436, 364, &MemDCLady, 0, 0, SRCCOPY); // Restore the old bitmap pDC->SelectObject(BmpPrevious); // Do not call CView::OnPaint() for painting messages
The bitmap is not drwan to the screen. I have tried using both the CPaintDC dc or the pDC* but to no avail. I cannot get the bitmap to display. Any suggestions will be greatly appreciated.