win32-printer.h

00001 
00002 class CGlPrinter
00003 {
00004 public:
00005         typedef enum { RENDER_TO_PRINTER, RENDER_TO_BITMAP, READ_BITMAP, PRINT_BITMAP } PRINTMODE;
00006 public:
00007         inline CGlPrinter( PRINTMODE mode = READ_BITMAP );
00008         inline ~CGlPrinter();
00009         inline bool Begin( char *title, int w=0, int h=0 );
00010         inline void End( GLubyte *bm=NULL );
00011         inline double GetAspect();
00012         inline int GetHorzRes();
00013         inline int GetVertRes();
00014 
00015 private:
00016         PRINTMODE m_printMode;
00017         PRINTDLG m_printDLG;
00018         BITMAPINFO m_bitmapInfo;
00019         void *m_bitmap;
00020         HBITMAP bitmapHandle;
00021         HDC m_bitmapDC;
00022         HGLRC m_printerHGLRC;
00023         HGLRC m_bitmapHGLRC;
00024         int m_pageWidth;                                // Dimension of printer page (x)
00025         int m_pageHeight;                               // Dimension of printer page (y)
00026 };
00027 
00028 inline double CGlPrinter::GetAspect()
00029 {
00030         return (double)m_pageWidth/(double)m_pageHeight;
00031 }
00032 
00033 inline int CGlPrinter::GetHorzRes()
00034 {
00035         return m_pageWidth;
00036 }
00037 
00038 inline int CGlPrinter::GetVertRes()
00039 {
00040         return m_pageHeight;
00041 }
00042 
00043 inline CGlPrinter::CGlPrinter( PRINTMODE mode ) :
00044         m_printerHGLRC( 0 ), m_bitmapHGLRC( 0 ), m_printMode( mode ), m_bitmap( NULL )
00045 {
00046 }
00047 
00048 inline CGlPrinter::~CGlPrinter()
00049 {
00050 }
00051 
00052 inline bool CGlPrinter::Begin( char *title, int w, int h  )
00053 {
00054         // Pixel format for Printer Device context
00055         static PIXELFORMATDESCRIPTOR pPrintfd = {
00056                 sizeof(PIXELFORMATDESCRIPTOR),                  // Size of this structure
00057                 1,                                      // Version of this structure    
00058                 PFD_DRAW_TO_WINDOW |                    // Draw to Window (not to m_bitmap)
00059                 PFD_SUPPORT_OPENGL |                    // Support OpenGL calls 
00060                 PFD_SUPPORT_GDI |                       // Allow GDI drawing in window too
00061                 PFD_DEPTH_DONTCARE,                                             // Don't care about depth buffering
00062                 PFD_TYPE_RGBA,                          // RGBA Color mode
00063                 24,                                     // Want 24bit color 
00064                 0,0,0,0,0,0,                            // Not used to select mode
00065                 0,0,                                    // Not used to select mode
00066                 0,0,0,0,0,                              // Not used to select mode
00067                 0,                                      // Size of depth buffer
00068                 0,                                      // Not used to select mode
00069                 0,                                      // Not used to select mode
00070                 0,                                                      // Not used to select mode
00071                 0,                                      // Not used to select mode
00072                 0,0,0 };                                // Not used to select mode
00073 
00074         DOCINFO docInfo;        // Document Info
00075         int nPixelFormat;               // Pixel format requested
00076 
00077         // Get printer information
00078         memset(&m_printDLG,0,sizeof(PRINTDLG));
00079         m_printDLG.lStructSize = sizeof(PRINTDLG);
00080         m_printDLG.hwndOwner = GetForegroundWindow();
00081         m_printDLG.hDevMode = NULL;
00082         m_printDLG.hDevNames = NULL;
00083         m_printDLG.Flags = PD_RETURNDC | PD_ALLPAGES;
00084 
00085         // Display printer dialog
00086         if(!PrintDlg(&m_printDLG))
00087         {
00088                 printf( "PrintDlg() failed %lx\n", GetLastError() );
00089                 return false;
00090         }
00091 
00092         // Get the dimensions of the page
00093         m_pageWidth = GetDeviceCaps(m_printDLG.hDC, HORZRES);
00094         m_pageHeight = GetDeviceCaps(m_printDLG.hDC, VERTRES);
00095 
00096         // Initialize DocInfo structure
00097         docInfo.cbSize = sizeof(DOCINFO);
00098         docInfo.lpszDocName = title;
00099         docInfo.lpszOutput = NULL;
00100 
00101 
00102         // Choose a pixel format that best matches that described in pfd
00103         nPixelFormat = ChoosePixelFormat(m_printDLG.hDC, &pPrintfd);
00104         // Watch for no pixel format available for this printer
00105         if(nPixelFormat == 0)
00106                 {
00107                 // Delete the printer context
00108                 DeleteDC(m_printDLG.hDC);
00109 
00110                 printf( "ChoosePixelFormat() failed %lx\n", GetLastError() );
00111                 return false;
00112                 }
00113 
00114         // Start the document and page
00115         StartDoc(m_printDLG.hDC, &docInfo);
00116         StartPage(m_printDLG.hDC);
00117         
00118         // Set the pixel format for the device context, but watch for failure
00119         if(!SetPixelFormat(m_printDLG.hDC, nPixelFormat, &pPrintfd))
00120                 {
00121                 // Delete the printer context
00122                 DeleteDC(m_printDLG.hDC);
00123 
00124                 printf( "SetPixelFormat() failed %lx\n", GetLastError() );
00125                 return false;
00126                 }
00127 
00128         // Create the Rendering context and make it current
00129         if ( m_printMode == RENDER_TO_PRINTER )
00130         {
00131                 m_printerHGLRC = wglCreateContext(m_printDLG.hDC);
00132                 wglMakeCurrent(m_printDLG.hDC, m_printerHGLRC);
00133         }
00134         else 
00135         {
00136                 memset( &m_bitmapInfo, 0, sizeof(BITMAPINFO) );
00137                 m_bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
00138                 if ( m_printMode == READ_BITMAP )
00139                 {
00140                         GLint vp[4];
00141                         glGetIntegerv( GL_VIEWPORT, vp );
00142                         m_bitmapInfo.bmiHeader.biWidth = vp[2];
00143                         m_bitmapInfo.bmiHeader.biHeight = (vp[3] + 3) & ~3;
00144                 }
00145                 else
00146                 {
00147                         if ( m_printMode == RENDER_TO_BITMAP )
00148                         {
00149                                 m_bitmapInfo.bmiHeader.biWidth = m_pageWidth;
00150                                 m_bitmapInfo.bmiHeader.biHeight = m_pageHeight;
00151                         }
00152                         else
00153                         {
00154                                 // PRINT_BITMAP
00155                                 m_bitmapInfo.bmiHeader.biWidth = w;
00156                                 m_bitmapInfo.bmiHeader.biHeight = h;
00157                         }
00158                 }
00159                 m_bitmapInfo.bmiHeader.biPlanes = 1;
00160                 m_bitmapInfo.bmiHeader.biBitCount = 24;
00161                 m_bitmapInfo.bmiHeader.biCompression = BI_RGB;
00162                 m_bitmapInfo.bmiHeader.biSizeImage = m_bitmapInfo.bmiHeader.biWidth*m_bitmapInfo.bmiHeader.biHeight*3;
00163                 m_bitmapInfo.bmiHeader.biXPelsPerMeter = 2952; // 75dpi
00164                 m_bitmapInfo.bmiHeader.biYPelsPerMeter = 2952; // 75dpi
00165                 m_bitmapInfo.bmiHeader.biClrUsed = 0;
00166                 m_bitmapInfo.bmiHeader.biClrImportant = 0;
00167                 bitmapHandle = CreateDIBSection( NULL, &m_bitmapInfo, DIB_RGB_COLORS, &m_bitmap, NULL, 0);
00168                 m_bitmapDC = CreateCompatibleDC( NULL );
00169                 if ( m_bitmapDC == NULL )
00170                 {
00171                         DeleteDC(m_printDLG.hDC);
00172                         printf( "CreateCompatibleDC() failed %lx\n", GetLastError() );
00173                         return false;
00174                 }
00175                 if ( SelectObject( m_bitmapDC, bitmapHandle ) == NULL )
00176                 {
00177                         DeleteDC(m_printDLG.hDC);
00178                         DeleteDC(m_bitmapDC);
00179                         printf( "SelectObject() failed %lx\n", GetLastError() );
00180                         return false;
00181                 }
00182                 PIXELFORMATDESCRIPTOR pfd;
00183                 memset( &pfd, 0, sizeof(PIXELFORMATDESCRIPTOR) );
00184                 pfd.nVersion = 1 ;
00185                 pfd.dwFlags = PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL;
00186                 pfd.iPixelType = PFD_TYPE_RGBA ; 
00187                 pfd.cColorBits = 24;
00188                 pfd.iLayerType = PFD_MAIN_PLANE;
00189                 int pixelFormat = ::ChoosePixelFormat(m_bitmapDC, &pfd);
00190                 SetPixelFormat (m_bitmapDC, pixelFormat, &pfd);
00191                 if ( m_printMode == RENDER_TO_BITMAP )
00192                 {
00193                         m_bitmapHGLRC = wglCreateContext( m_bitmapDC );
00194                         wglMakeCurrent( m_bitmapDC, m_bitmapHGLRC );
00195                 }
00196         }
00197 
00198         if ( m_printMode == RENDER_TO_PRINTER || m_printMode == RENDER_TO_BITMAP )
00199         {
00200                 // Set viewing volume info
00201                 //glViewport(0,0,m_pageWidth/2,m_pageHeight/2); // Put this in to restrict area of page.
00202 
00203                 GLfloat nRange = 100.0f;
00204 
00205                 // Reset projection matrix stack
00206                 glMatrixMode(GL_PROJECTION);
00207                 glLoadIdentity();
00208 
00209                 // Establish clipping volume (left, right, bottom, top, near, far)
00210                 // This keeps the perspective square regardless of window or page size
00211 
00212                 if (m_pageHeight <= m_pageWidth) 
00213                 {
00214                         glOrtho (-nRange, nRange, -nRange*m_pageHeight/m_pageWidth, nRange*m_pageHeight/m_pageWidth, -nRange, nRange);
00215                 }
00216                 else 
00217                 {
00218                         glOrtho (-nRange*m_pageWidth/m_pageHeight, nRange*m_pageWidth/m_pageHeight, -nRange, nRange, -nRange, nRange);
00219                 }
00220 
00221                 // Reset Model view matrix stack
00222                 glMatrixMode(GL_MODELVIEW);
00223                 glLoadIdentity();
00224                 glRotatef(270.0f, 1.0, 0.0, 0.0);
00225         }
00226 
00227         return true;
00228 }
00229 
00230 inline void CGlPrinter::End( GLubyte *bm )
00231 {
00232         if ( m_printDLG.hDC )
00233         {
00234                 glFinish();
00235 
00236                 if ( m_printMode == RENDER_TO_PRINTER )
00237                 {
00238                         if ( m_printerHGLRC )
00239                         {
00240                                 wglDeleteContext( m_printerHGLRC );
00241                         }
00242                 }
00243                 else
00244                 {
00245                         if ( m_printMode == RENDER_TO_BITMAP )
00246                         {
00247                                 BitBlt( m_printDLG.hDC, 0,0, m_pageWidth,m_pageHeight, m_bitmapDC, 0,0, SRCCOPY );
00248                         }
00249                         else
00250                         {
00251                                 if ( m_printMode == READ_BITMAP )
00252                                 {
00253                                         glPixelStorei( GL_PACK_ALIGNMENT, 4 );
00254                                         glPixelStorei( GL_PACK_ROW_LENGTH, 0 );
00255                                         glPixelStorei( GL_PACK_SKIP_ROWS, 0 );
00256                                         glPixelStorei( GL_PACK_SKIP_PIXELS, 0 );
00257                                         //GLubyte *tempbitmap = (GLubyte *) malloc(m_bitmapInfo.bmiHeader.biWidth*m_bitmapInfo.bmiHeader.biHeight*4);
00258                                         glReadPixels( 0,0, m_bitmapInfo.bmiHeader.biWidth,m_bitmapInfo.bmiHeader.biHeight,
00259                                                 GL_RGB, GL_UNSIGNED_BYTE, m_bitmap );
00260                                 }
00261                                 else
00262                                 {
00263                                         //PRINT_BITMAP
00264                                         memcpy( m_bitmap, bm, m_bitmapInfo.bmiHeader.biSizeImage );
00265                                 }
00266                                 int i,j;
00267                                 GLubyte *rgb, temp;
00268                                 for ( i = 0; i < m_bitmapInfo.bmiHeader.biHeight; i++ )
00269                                 {
00270                                         for ( j = 0, rgb = ((GLubyte *)m_bitmap) + i * m_bitmapInfo.bmiHeader.biWidth * 3;
00271                                         j < m_bitmapInfo.bmiHeader.biWidth;
00272                                         j++, rgb +=3 )
00273                                         {
00274                                                 temp = rgb[0];
00275                                                 rgb[0] = rgb[2];
00276                                                 rgb[2] = temp;
00277                                         }
00278                                 }
00279                                 long width = m_pageWidth;
00280                                 long height = width * m_bitmapInfo.bmiHeader.biHeight / m_bitmapInfo.bmiHeader.biWidth;
00281                                 if ( height > m_pageHeight )
00282                                 {
00283                                         height = m_pageHeight;
00284                                         width = height * m_bitmapInfo.bmiHeader.biWidth / m_bitmapInfo.bmiHeader.biHeight;
00285                                 }
00286                                 long xoffset = (m_pageWidth - width) / 2;
00287                                 long yoffset = (m_pageHeight - height) / 2;
00288                                 StretchBlt( m_printDLG.hDC, xoffset, yoffset, width, height, m_bitmapDC, 0, 0,
00289                                         m_bitmapInfo.bmiHeader.biWidth, m_bitmapInfo.bmiHeader.biHeight, SRCCOPY );
00290                         }
00291                         if ( m_bitmapDC ) 
00292                         {
00293                                 DeleteDC( m_bitmapDC );
00294                         }
00295                         if ( bitmapHandle )
00296                         {
00297                                 DeleteObject( bitmapHandle );
00298                         }
00299                         if ( m_bitmapHGLRC )
00300                         {
00301                                 wglDeleteContext( m_bitmapHGLRC );
00302                         }
00303                 }
00304 
00305                 /* EndPage... */
00306                 if ( EndPage( m_printDLG.hDC ) <=0 )
00307                 {
00308                         printf( "EndPage() failed\n" );
00309                 }
00310 
00311                 /* EndDoc... */
00312                 if ( EndDoc( m_printDLG.hDC ) <=0 )
00313                 {
00314                         printf( "EndDoc() failed\n" );
00315                 }
00316 
00317                 // Delete the printer context when done with it
00318                 DeleteDC(m_printDLG.hDC);
00319                 
00320                 // Restore window rendering context
00321                 //wglMakeCurrent(hDC, hRC);
00322                 wglMakeCurrent( NULL, NULL );
00323 
00324         }
00325 }

Generated on Mon Dec 17 09:30:56 2007 for SimGear by  doxygen 1.5.1