15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Printing problem

Adrian_Glanvill@stockley-park.sterling.com
Monday, April 24, 1995

Not sure if this problem is strictly MFC related, but here goes anyway...

When printing out each page of my document, I blit a bitmap into the top-left 
corner of the page. I'm testing this on an HP Laserjet 4, which defaults to 
600dpi mode, and it works fine. If, however, I change the resolution to 300dpi, 
the bitmap gets drawn just over halfway across the page instead of at the left 
hand edge.

The code I am using in my OnPrint() function is as follows :

   // m_pLogoDC is a memory DC already set up earlier
   // Print logo:  
   if (m_pLogoDC && pDC->GetDeviceCaps(RASTERCAPS) & RC_STRETCHBLT )
   {
      m_pOldBitmap = m_pLogoDC->SelectObject(m_pLogo);

      // change map mode to guarantee physical dimensions of logo on page
      int nOldMode = pDC->SetMapMode(MM_HIMETRIC);    

      // transfer from the memory dc to the printer dc
      pDC->StretchBlt(0, 0, 1000, -1000, m_pLogoDC, 0, 0, 112, 112,  SRCCOPY);

      // restore original map mode and clear bitmap
      pDC->SetMapMode(nOldMode);      
      m_pLogoDC->SelectObject(m_pOldBitmap);        
   }

Apart from using magic numbers, what's wrong with this code ?        

============================================================================
Adrian Glanvill         Phone  : +44-181-867-8275
Sterling Software       E-Mail : Adrian_Glanvill@stockley-park.sterling.com
============================================================================




RND - Gan Chai Beng -- locbg@venus.likom.com.my
Tuesday, July 18, 1995

I use VC++ 1.5.
I load a bitmap and stretch it to a device context of the view. It seems 
everything correct. But if I print it to printer, some of the image on the top 
of bitmap is truncated.	

	StretchBlt( DestHDC,
		0, 0,               
	              SrcWidth, SrcHeight,
		SrcHDC,
		0, 0,
		SrcWidth, SrcHeight,
		SRCCOPY);

If I change the code to :

	StretchBlt( DestHDC,
**eg.		30, 30,               
	              SrcWidth, SrcHeight,
		SrcHDC,
		0, 0,
		SrcWidth, SrcHeight,
		SRCCOPY);

all the image will print out. What the printer driver I used is PostScript  
Printer.
I think this may be the top margin of page setup problem. Any idea of this ?
How I can get the top margin value as printing ? 



Jack
Friday, February 16, 1996


I'm calling code similar to the following from my OnDraw() function in a   
CView derived class:
Interestingly enough, it prints on a monochrome Postscript printer but   
not on my HP 855C Color printer. Additionally, depending on the size of   
the rect, it may or may not print.

For example:

void CPrintView::OnDraw(CDC* pDC)
{
  CPrintDoc* pDoc = GetDocument();
  ASSERT_VALID(pDoc);

  CPoint ptOrigin(225,255);
  CSize sz(93,273); 
  Draw(pDC,CRect(ptOrigin,ptOrigin+sz));
}

void CPrintView::Draw(CDC* pDC, const CRect& rc)
{
    

  CSize sz(rc.Size());
  CPoint pos(rc.TopLeft());

  CDC dc;
  dc.CreateDC("DISPLAY",0,0,0);
    

  CDC memDC;
  memDC.CreateCompatibleDC(pDC);
  CBitmap bmp;
  bmp.CreateCompatibleBitmap(pDC,sz.cx,sz.cy);
  BITMAP bitmap;
  bmp.GetObject(sizeof(BITMAP),&bitmap);
  memDC.SelectObject(&bmp);
  CBrush br(RGB(0,0,0));
  memDC.FillRect(&CRect(CPoint(0,0),sz),&br);
      

  pDC->SetMapMode(MM_TEXT);

  pDC->BitBlt(pos.x, pos.y, sz.cx, sz.cy, &memDC, 0, 0, SRCCOPY);
}




Andreas Will -- a.will@T-Online.de
Sunday, February 18, 1996

>
>I'm calling code similar to the following from my OnDraw() function in a   
>CView derived class:
>Interestingly enough, it prints on a monochrome Postscript printer but   
>not on my HP 855C Color printer. Additionally, depending on the size of   
>the rect, it may or may not print.
>
>For example:
..snip..
>
>  CDC dc;
>  dc.CreateDC("DISPLAY",0,0,0);

You create a dc that is compatible to your display not necessarily your printer.
I don't know about the capabilities of your PS-printer but it's driver
probably makes it compatible to the screen display.

You should call dc.CreateCompatibleDC(pDC) to get a printer-compatible dc

You can ask for the bits per pixel (bpp) of your printer dc by calling 
  pDC->GetDeviceCaps(BITSPIXEL) (also: not all devices support BitBlt)

If your bitmap uses more bpp you have a problem:
 MSVC 1.5 help quote:
 An application can select a bitmap into memory device contexts only and 
 into only one memory device context at a time. 
 The format of the bitmap must either be monochrome or compatible 
 with the device context; if it is not, SelectObject returns an error.

Best regards 
 Andy
/////////////////
Andreas Will
Jever, Germany
inet:   a.will@t-online.de
cserve: 101537,3347
/////////////////



David Shak -- Dshak@TORONTO.DELRINA.com
Thursday, February 22, 1996


>>I'm calling code similar to the following from my OnDraw() function in   
a
>>CView derived class:
>>Interestingly enough, it prints on a monochrome Postscript printer but   
    

>>not on my HP 855C Color printer. Additionally, depending on the size of   
    

>>the rect, it may or may not print.
>>
>>For example:
>..snip..
>>
>>  CDC dc;
>>  dc.CreateDC("DISPLAY",0,0,0);

>You create a dc that is compatible to your display not necessarily your
>printer.
>I don't know about the capabilities of your PS-printer but it's driver
>probably makes it compatible to the screen display.

>You should call dc.CreateCompatibleDC(pDC) to get a printer-compatible   
dc

>You can ask for the bits per pixel (bpp) of your printer dc by calling
>  pDC->GetDeviceCaps(BITSPIXEL) (also: not all devices support BitBlt)

>If your bitmap uses more bpp you have a problem:
> MSVC 1.5 help quote:
> An application can select a bitmap into memory device contexts only and   

> into only one memory device context at a time.
> The format of the bitmap must either be monochrome or compatible
> with the device context; if it is not, SelectObject returns an error.

If you notice in the original code, the CDC object 'dc' is
used to in
dc.CreateDC("DISPLAY",0,0,0);
but no where else this must have been test code that was not taken
out...
also notice that the original code does call CreateCompatibleDC correctly
(I think).

Strangely enough I am having a similar (possibly the exact) problem,
I am also having difficulty printing bitmaps but ( and this is really   
weird)
only on some machines... It works on my NT 3.51 machine but not on
another NT 3.51 machine printing to the same printer.  I've tried my test   

app on allot of machines and there seems to be no configuration that
works all the time.
The app is failing in the SelectObject but I have no idea why. ( remember
it does work on some machines)
I'm doing the simplest of examples... here is the code
void CPrintView::OnDraw(CDC* pDC)
{
 CDC memDC;
 CBitmap bitmap, *pOldBitmap;
 BITMAP bitmapInfo;

 bitmap.LoadBitmap( IDB_THING);
 bitmap.GetObject( sizeof( bitmapInfo), &bitmapInfo);

 memDC.CreateCompaibleDC( pDC);
 pOldBitmap = (CBitmap*)memDC.SelectObject( &bitmap); // fails here
        // on some machines
 ASSERT( pOldBitmap);

 pDC->BitBlt( 0, 0, bitmapInfo.bmWidth, bitmapInfo.bmHeight, &memDC, 0,   
0, SRCCOPY);

 memDC.SelectObject( pOldBitmap);
}
I think solving this problem will also solve the first problem.
( by the way the sample app was made with the VC4 app wizard)

Dave.



dhylands@creo.bc.ca
Friday, February 23, 1996

[Mini-digest: 2 responses]

Hi Dave,

> Strangely enough I am having a similar (possibly the exact) problem,
> I am also having difficulty printing bitmaps but ( and this is really
> weird) only on some machines... It works on my NT 3.51 machine but not on
> another NT 3.51 machine printing to the same printer.  I've tried my test
> app on allot of machines and there seems to be no configuration that
> works all the time.
> The app is failing in the SelectObject but I have no idea why. ( remember
> it does work on some machines)

The answer doesn't have anything to do with MFC but it probably explains 
whats happening.

Make sure that both printer drivers are actually using the same PSCRIPT.DLL 
file. It seems like there are minor changes to each one with each service pack 
and version of NT (It probably it isn't it just seems that way).

Check C:\WINNT35\SYSTEM32\SPOOL\DRIVERS\W32ALPHA (or w32x86) and ALL of the 
numbered directories found here.

All of the PSCRIPT.DLL's  should have the same date/timestamp and size.
All of the PSCRPTUI.DLL's should have the same date/timestamp and size.

The ones on the machine that doesn't work are probably different from the ones 
on the machine that does work.

After you install a printer, make sure that run the appropriate service pack 
again (installing a printer may copy in old files off your diskettes or CD which
were updated on a service pack).

Even after installing the service pack, I would double check the date and file 
sizes and see if they've been updated.

NT 3.51 for Intel ships with 

May 26  10:57:00  1995     220944  pscript.dll
May 26  10:57:00  1995     184592  pscrptui.dll

NT 3.51 Service Pack 2 for Intel has DLL's with the following date & size:

Oct  7  10:57:02  1995     221456  PSCRIPT.DLL
Oct  7  10:57:02  1995     184592  PSCRPTUI.DLL

Dave Hylands             Email: DHylands@creo.bc.ca   3700 Gilmore Way
Senior Software Developer  Tel: (604) 451-2700 x2329  Burnaby B.C.
Creo Products Inc.         Fax: (604) 437-9891        Canada V5G 4M1 

-----From: Jack.Zucker@software.rockwell.com (Zucker, Jack)



>If your bitmap uses more bpp you have a problem:
> MSVC 1.5 help quote:
> An application can select a bitmap into memory device contexts only and   
    

> into only one memory device context at a time.

> The format of the bitmap must either be monochrome or compatible
> with the device context; if it is not, SelectObject returns an error.

If you notice in the original code, the CDC object 'dc' is
used to in
dc.CreateDC("DISPLAY",0,0,0);
but no where else this must have been test code that was not taken
out...

Yes that is correct. I forgot to take it out but it has nothing to do   
with the problem.
also notice that the original code does call CreateCompatibleDC correctly
(I think).

No that's not correct. I'm getting a CDC* in my function which is the   
printer DC.
I'm doing the following:

CDC memDC;
memDC.CreateCompatibleDC(pDC);

This is correct.

I think your statement regarding having the bitmap selected into only one   
DC at a time or having the bitmap be incompatible with the destination DC   
is probably not the problem either. In my test code, I always selected   
the previous bitmap back into the memory DC and the printer DC had it's   
previous bitmap reselected via calls to SaveDC() and RestoreDC().   
Additionally, the bitmap was created and destroyed each time the function   
was called. The bitmap was a color bitmap so there could possibly be an   
issue there but since I created the bitmap by using the printer DC as in:

CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC /*PrinterDC*/,width,height);

This should not have been a problem.
In fact, here is the code:

void MyView::PrintThisSucker(CDC* pPrinterDC /* MM_TEXT mode */)
{
  CDC memDC;
  memDC.CreateCompatibleDC(pPrinterDC);
  CBitmap bmp;
  bmp.CreateCompatibleBitmap(pPrinterDC,93,273);
  CBrush brush(RGB(255,0,0));
    

  CBitmap* pOld = memDC.SelectObject(&bmp);
  memDC.FillRect(&CRect(0,0,93,273),&brush);

  pPrinterDC->BitBlt(0,0,93,273,&memDC,0,0,SRCCOPY);
   

  memDC.SelectObject(pOld);
}

Again, this works on the HP855C but not on the postscript printer. (Or is   
it the other way around ?) In any event, if I change the memDC and Bitmap   
to use a "DISPLAY" dc, it then prints on the opposite printer only. It   
still never prints on both. The other thing that changes is if I change   
the width and height. For some reason, 93x273 seems to be a magical   
number because it prints on both printers if I change it to something   
like 100x300. (Both printers support 300x300 DPI)

 -Jaz






David Shak -- Dshak@TORONTO.DELRINA.com
Tuesday, February 27, 1996


>The answer doesn't have anything to do with MFC but it probably explains   

>whats happening.

>Make sure that both printer drivers are actually using the same   
PSCRIPT.DLL
>file. It seems like there are minor changes to each one with each   
service
>pack
>and version of NT (It probably it isn't it just seems that way).

>Check C:\WINNT35\SYSTEM32\SPOOL\DRIVERS\W32ALPHA (or w32x86) and ALL of   
the
>numbered directories found here.
......snip......
I really don't think the problem is with bad drivers... that would mean
the machine should not print bitmaps at all ( and that's not the case)
or that MFC does not work with these printer drivers which seems   
unlikely.

......snip........
>void MyView::PrintThisSucker(CDC* pPrinterDC /* MM_TEXT mode */)
>{
>  CDC memDC;
>  memDC.CreateCompatibleDC(pPrinterDC);
>  CBitmap bmp;
>  bmp.CreateCompatibleBitmap(pPrinterDC,93,273);
>  CBrush brush(RGB(255,0,0));

>  CBitmap* pOld = memDC.SelectObject(&bmp);
>  memDC.FillRect(&CRect(0,0,93,273),&brush);

>  pPrinterDC->BitBlt(0,0,93,273,&memDC,0,0,SRCCOPY);

>  memDC.SelectObject(pOld);
>}

In the above code, creating a bitmap and then BitBliting it is
not necessary, one call to FillRect using the correct DC
should work fine.

Dave.




Jack
Friday, March 01, 1996



You wrote:


>>void MyView::PrintThisSucker(CDC* pPrinterDC /* MM_TEXT mode */)
>>{
>>  CDC memDC;
>>  memDC.CreateCompatibleDC(pPrinterDC);
>>  CBitmap bmp;
>>  bmp.CreateCompatibleBitmap(pPrinterDC,93,273);
>>  CBrush brush(RGB(255,0,0));
>
>>  CBitmap* pOld = memDC.SelectObject(&bmp);
>>  memDC.FillRect(&CRect(0,0,93,273),&brush);
>
>>  pPrinterDC->BitBlt(0,0,93,273,&memDC,0,0,SRCCOPY);
>
>>  memDC.SelectObject(pOld);
>>}
>
>In the above code, creating a bitmap and then BitBliting it is
>not necessary, one call to FillRect using the correct DC
>should work fine.
>
>Dave.
>

You missed the point. The FillRect() is just a placeholder for additional   
code which can't simply be
draw to the destination DC.

 -Jaz  





| Вернуться в корень Архива |