BitBlt does not work in print preview
-
I am trying to draw something into memory DC and then copy it to screen or printer DC. I get the correct output drawing on screen or when directly taking the print out on printer. BUt while viewing print preview, it does not show any output.
CMyView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;CRect rcClient; if (pDC->IsPrinting()) { rcClient = m\_rcPrintRect; //obtained from CPrintInfo } else { GetClientRect(&rcClient); } CBitmap bmp; CDC memDC; memDC.CreateCompatibleDC(pDC); bmp.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()); memDC.SelectObject(&bmp); memDC.DrawText(L"Hello", &rcClient, DT\_CENTER | DT\_VCENTER); pDC->BitBlt(0,0,rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY); bmp.DeleteObject(); memDC.DeleteDC(); return;
}
I suspect something is wrong with creating compatible DC. pDC represents printer dc but the display is on screen. How to remove this problem? :sigh:
-
I am trying to draw something into memory DC and then copy it to screen or printer DC. I get the correct output drawing on screen or when directly taking the print out on printer. BUt while viewing print preview, it does not show any output.
CMyView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;CRect rcClient; if (pDC->IsPrinting()) { rcClient = m\_rcPrintRect; //obtained from CPrintInfo } else { GetClientRect(&rcClient); } CBitmap bmp; CDC memDC; memDC.CreateCompatibleDC(pDC); bmp.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()); memDC.SelectObject(&bmp); memDC.DrawText(L"Hello", &rcClient, DT\_CENTER | DT\_VCENTER); pDC->BitBlt(0,0,rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY); bmp.DeleteObject(); memDC.DeleteDC(); return;
}
I suspect something is wrong with creating compatible DC. pDC represents printer dc but the display is on screen. How to remove this problem? :sigh:
What is the value of rcClient when it fails? I'm not seeing anything wrong with your DC creation... Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
What is the value of rcClient when it fails? I'm not seeing anything wrong with your DC creation... Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I checked it in debug mode. the program does not fail in print preview. BitBlt also completes successfully. only I do not get any output. I can initialize rcClient to (0,0,0,0) but that does not make a difference. Thanks.
ok....and the answer to my question is? :) From the debugger, what is the left/top/right/bottom values of the rect?????
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
ok....and the answer to my question is? :) From the debugger, what is the left/top/right/bottom values of the rect?????
Mark Salsbery Microsoft MVP - Visual C++ :java:
oh sorry... in print preview, top=0, bottom=6400, left = 0, right=4900 (size of A4 sheet in pixels @600 dpi) in print, height= 6300, widht=4800...(because of different margin settings?)
the fruits of your success will be in direct ratio to the honesty and sincerity of your own efforts in keeping your own records, doing your own thinking and, reaching your own conclusions. ..surviving in autumn..in love with spring..
-
oh sorry... in print preview, top=0, bottom=6400, left = 0, right=4900 (size of A4 sheet in pixels @600 dpi) in print, height= 6300, widht=4800...(because of different margin settings?)
the fruits of your success will be in direct ratio to the honesty and sincerity of your own efforts in keeping your own records, doing your own thinking and, reaching your own conclusions. ..surviving in autumn..in love with spring..
Arghh I'm drawing a blank here LOL What happens if you do pDC->MoveTo(rcClient.left, rcClient.top); pDC->LineTo(rcClient.right, rcClient.bottom); Do you get a diagonal line? Also is the bitmap creation succeeding?
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Arghh I'm drawing a blank here LOL What happens if you do pDC->MoveTo(rcClient.left, rcClient.top); pDC->LineTo(rcClient.right, rcClient.bottom); Do you get a diagonal line? Also is the bitmap creation succeeding?
Mark Salsbery Microsoft MVP - Visual C++ :java:
Yes, I get a diagonal line. In fact. there's no problem with drawing directly on print preview dc. I am using memory dc in my code only to avoid flickering (perhaps it was obvious) The following code draws properly in print preview... by using DIB. But it's heavily slowing down my system. perhaps, I need to create DIB section in more elegant way. DDB provided by create compatible bitmap perhaps does not work. :doh:
void CMyView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;CRect rcClient; if (pDC->IsPrinting()) { rcClient = m\_rcPrintRect; } else { GetClientRect(&rcClient); } HBITMAP bmp; BYTE\* drawingSurfaceBits; BITMAPINFOHEADER BMIH; BMIH.biSize = sizeof(BITMAPINFOHEADER); BMIH.biBitCount = 24; BMIH.biPlanes = 1; BMIH.biCompression = BI\_RGB; BMIH.biWidth = rcClient.Width(); BMIH.biHeight = rcClient.Height(); BMIH.biSizeImage = ((((BMIH.biWidth \* BMIH.biBitCount) + 31) & ~31) >> 3) \* BMIH.biHeight; bmp = CreateDIBSection(pDC->GetSafeHdc(), (CONST BITMAPINFO\*)&BMIH, DIB\_RGB\_COLORS, (void\*\*)&drawingSurfaceBits, NULL, 0); if((bmp == NULL) || (drawingSurfaceBits == NULL)) { AfxMessageBox(L"Bitmap not created", MB\_OK | MB\_ICONSTOP); return; } memDC.CreateCompatibleDC(pDC); memDC.SelectObject(bmp); memDC.DrawText(L"Hello", &rcClient, DT\_CENTER | DT\_VCENTER); pDC->BitBlt(0,0,rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY); return;
}
Also, in print preview mode, the quality of picture shown on screen is extremely poor. I am perhaps using only rgb etc. I need to study bitmapinfoheader further. Thanks for the precious help. :)
modified on Thursday, September 18, 2008 1:07 PM
-
Yes, I get a diagonal line. In fact. there's no problem with drawing directly on print preview dc. I am using memory dc in my code only to avoid flickering (perhaps it was obvious) The following code draws properly in print preview... by using DIB. But it's heavily slowing down my system. perhaps, I need to create DIB section in more elegant way. DDB provided by create compatible bitmap perhaps does not work. :doh:
void CMyView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;CRect rcClient; if (pDC->IsPrinting()) { rcClient = m\_rcPrintRect; } else { GetClientRect(&rcClient); } HBITMAP bmp; BYTE\* drawingSurfaceBits; BITMAPINFOHEADER BMIH; BMIH.biSize = sizeof(BITMAPINFOHEADER); BMIH.biBitCount = 24; BMIH.biPlanes = 1; BMIH.biCompression = BI\_RGB; BMIH.biWidth = rcClient.Width(); BMIH.biHeight = rcClient.Height(); BMIH.biSizeImage = ((((BMIH.biWidth \* BMIH.biBitCount) + 31) & ~31) >> 3) \* BMIH.biHeight; bmp = CreateDIBSection(pDC->GetSafeHdc(), (CONST BITMAPINFO\*)&BMIH, DIB\_RGB\_COLORS, (void\*\*)&drawingSurfaceBits, NULL, 0); if((bmp == NULL) || (drawingSurfaceBits == NULL)) { AfxMessageBox(L"Bitmap not created", MB\_OK | MB\_ICONSTOP); return; } memDC.CreateCompatibleDC(pDC); memDC.SelectObject(bmp); memDC.DrawText(L"Hello", &rcClient, DT\_CENTER | DT\_VCENTER); pDC->BitBlt(0,0,rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY); return;
}
Also, in print preview mode, the quality of picture shown on screen is extremely poor. I am perhaps using only rgb etc. I need to study bitmapinfoheader further. Thanks for the precious help. :)
modified on Thursday, September 18, 2008 1:07 PM
Creating that big bitmap on every draw is going to be a little slow. I would only (re)create it when the size changes.
theCPkid wrote:
(CONST BITMAPINFO*)&BMIH
Bad cast!!!!! No bueno! You need to pass a pointer to a BITMAPINFO, not a pointer to a BITMAPINFOHEADER. The cast just hides the error from the compiler :) Try
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = rcClient.Width();
bmi.bmiHeader.biHeight = rcClient.Height();
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = ((((bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) + 31) & ~31) >> 3) * bmi.bmiHeader.biHeight;
//bmi.bmiHeader.biXPelsPerMeter = 0;
//bmi.bmiHeader.biYPelsPerMeter = 0;
//bmi.bmiHeader.biClrUsed = 0;
//bmi.bmiHeader.biClrImportant = 0;bmp = ::CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&drawingSurfaceBits, NULL, 0);
I'm not sure what's going on with the rendering quality....I'll ponder that and let you know if I think of something...(maybe the code fix above will do better?) Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I am trying to draw something into memory DC and then copy it to screen or printer DC. I get the correct output drawing on screen or when directly taking the print out on printer. BUt while viewing print preview, it does not show any output.
CMyView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;CRect rcClient; if (pDC->IsPrinting()) { rcClient = m\_rcPrintRect; //obtained from CPrintInfo } else { GetClientRect(&rcClient); } CBitmap bmp; CDC memDC; memDC.CreateCompatibleDC(pDC); bmp.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()); memDC.SelectObject(&bmp); memDC.DrawText(L"Hello", &rcClient, DT\_CENTER | DT\_VCENTER); pDC->BitBlt(0,0,rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY); bmp.DeleteObject(); memDC.DeleteDC(); return;
}
I suspect something is wrong with creating compatible DC. pDC represents printer dc but the display is on screen. How to remove this problem? :sigh:
The issues you may be seeing could be down to what raster operations are supported by the DC types in question. If you had been saying it shows in preview and not on the printer I would definately have said this, but you have it reversed which makes me intrigued (and I have even come out of CP semi-retirment to answer :omg:) The first thing I would say is drop BitBlt altogether. its not guaranteed to be compatible with both display DCs and printer DCs. Your best option would be to switch to StretchDIBits, from memory this is compatible with all DC types. Another thing that could be causing you problems is that your creating a DC compatible with a preview DC, this means you will have all the world transforms which map from print to preview display probably active on your memory DC. Try creating your comapatible DC directtly from the screen by passing NULL instead of pDC. If that fixes the issues then I would say its down to the preview DC supporting all the world transforms and your in effect drawing of the edge of the comaptible bitmap.
If you vote me down, my score will only get lower
-
The issues you may be seeing could be down to what raster operations are supported by the DC types in question. If you had been saying it shows in preview and not on the printer I would definately have said this, but you have it reversed which makes me intrigued (and I have even come out of CP semi-retirment to answer :omg:) The first thing I would say is drop BitBlt altogether. its not guaranteed to be compatible with both display DCs and printer DCs. Your best option would be to switch to StretchDIBits, from memory this is compatible with all DC types. Another thing that could be causing you problems is that your creating a DC compatible with a preview DC, this means you will have all the world transforms which map from print to preview display probably active on your memory DC. Try creating your comapatible DC directtly from the screen by passing NULL instead of pDC. If that fixes the issues then I would say its down to the preview DC supporting all the world transforms and your in effect drawing of the edge of the comaptible bitmap.
If you vote me down, my score will only get lower
Roger Allen wrote:
but you have it reversed which makes me intrigued (and I have even come out of CP semi-retirment to answer )
Special thx for that.
Roger Allen wrote:
The first thing I would say is drop BitBlt altogether. its not guaranteed to be compatible with both display DCs and printer DCs. Your best option would be to switch to StretchDIBits, from memory this is compatible with all DC types.
yeah...as noted earlier, creating a DIB bitmap removes the problem with print preview but the application becomes very slow. Also, the image quality becomes very poor. You can see red, blue, green lines over the whole image.
Roger Allen wrote:
Try creating your comapatible DC directtly from the screen by passing NULL instead of pDC. If that fixes the issues then I would say its down to the preview DC supporting all the world transforms and your in effect drawing of the edge of the comaptible bitmap.
No, I tried that earlier...creating a dc for monitor in print preview mode does not work. Anyway, what I did last night is to check whether the DC is of type CPreviewDC. If it is, then I directly draw on that dc instead of creating a memory dc for it. otherwise I create a memory DC in case of print and normal view mode. It works correctly. Also, I am thinking of creating a smaller fixed size bitmap on which to draw and then StretchBlt it on whatever the size of actual DC. This will save me from creating a bitmap every time inside OnDraw as well as painting on larger DC. As of now, the applicaion is taking large CPU power and I am trying to find out various tools for profiling that can help me find bad code. X| Thanks for your suggestion.
-
Creating that big bitmap on every draw is going to be a little slow. I would only (re)create it when the size changes.
theCPkid wrote:
(CONST BITMAPINFO*)&BMIH
Bad cast!!!!! No bueno! You need to pass a pointer to a BITMAPINFO, not a pointer to a BITMAPINFOHEADER. The cast just hides the error from the compiler :) Try
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = rcClient.Width();
bmi.bmiHeader.biHeight = rcClient.Height();
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = ((((bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) + 31) & ~31) >> 3) * bmi.bmiHeader.biHeight;
//bmi.bmiHeader.biXPelsPerMeter = 0;
//bmi.bmiHeader.biYPelsPerMeter = 0;
//bmi.bmiHeader.biClrUsed = 0;
//bmi.bmiHeader.biClrImportant = 0;bmp = ::CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void**)&drawingSurfaceBits, NULL, 0);
I'm not sure what's going on with the rendering quality....I'll ponder that and let you know if I think of something...(maybe the code fix above will do better?) Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Does not make any difference on rendering quality and the quality is very poor. So, I am not using it in my code as of now. Thanks.
It's not your code or my code causing poor quality...either way should work. Rendering some text in a 6400x4900 offscreen buffer then squishing it down to fit a window is going to look bad. The only way to make it look 100% correct is to make your bitmap the exact size it will be rendered on the screen.
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
It's not your code or my code causing poor quality...either way should work. Rendering some text in a 6400x4900 offscreen buffer then squishing it down to fit a window is going to look bad. The only way to make it look 100% correct is to make your bitmap the exact size it will be rendered on the screen.
Mark Salsbery Microsoft MVP - Visual C++ :java: