Link to home
Start Free TrialLog in
Avatar of Sohela
Sohela

asked on

Printing : Using win32 (print to pdf file)

I have to develop a dll application in visual studio .net 2003 to print any file to pdf file format.I am presently  using a unigraphics part file(or any other text file ) to print. With what code i have written that is when i execute a pdf file is being generated but it is empty, only a plain white sheet is present.I dont know where i am going wrong. I think there is some problem in input.I am using a printdlg function and im using GetActiveWindow() to get the handleof the present window and i am passing it in the structure.This function i am calling after UF_intialise
but if I try to create a new part in unigraphics(nx4) or after creating any simple sketch then call this handle is returning null value whereas after  UF_intialise it is not null. I am attaching my code below.I think it is not able to identify which page to print.

HDC GetPrinterDC(HWND hWndParent)
{
       PRINTDLG pdlg;
       // Initialize the PRINTDLG structure.
       memset( &pdlg, 0, sizeof( PRINTDLG ) );
       pdlg.lStructSize = sizeof( PRINTDLG );
 
      // Set the flag to return printer DC.
       pdlg.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
 
       pdlg.hwndOwner = hWndParent;
 
      PrintDlg( &pdlg );
 
     // hDC member of the PRINTDLG structure contains the printer DC.
        return pdlg.hDC;
}
 
void InitDocStruct( DOCINFO* di, char* docname)
{
 
      // Always zero it before using it.
      memset( di, 0, sizeof( DOCINFO ) );
 
     // Fill in the required members.
     di->cbSize = sizeof( DOCINFO );
     di->lpszDocName = "test";        
}
 
BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{
            hInstance = (HINSTANCE)hModule;
            return TRUE;
}
 
extern "C" DllExport void ufusr( char *parm, int *returnCode, int rlen )
{
       int nErr = 0;
       HWND  hWnd = NULL;
       HDC        hDC;
       DOCINFO    di;
 
       nErr = UF_initialize();
       if (nErr != 0)
       {
           uc1601 ("Failed to initialise UG session", 1);
           return;
       }
       hWnd = GetActiveWindow();
       if (hWnd != NULL)
       {
             hDC = GetPrinterDC(hWnd);
             if( !hDC)
             {
 
                MessageBox(NULL, "Error creating DC", "Error",
                           MB_APPLMODAL | MB_OK );
             }
             InitDocStruct( &di, "Test");
 
            StartDoc( hDC, &di );
 
            StartPage( hDC );
 
            EndPage( hDC );
 
            EndDoc( hDC );
 
           DeleteDC( hDC );
      }
      nErr = UF_terminate();

Open in new window

Avatar of DanRollins
DanRollins
Flag of United States of America image

Your code does not do any output.  
After the StartPage call, you need to draw to the HDC.  For instance, add this line right after StartPage:
    TextOut(hDc, 300, 300, "here is a long line of text", 26 );
Avatar of Sohela
Sohela

ASKER

Thanks for the reply but i want to print the whole page what is displayed on my screen not a line , like not what i give  manually how we do we go to File->Print->Pdf then the whole page is printed so i want like that which window is open how do we give input as that page.
>>>> but i want to print the whole page what is displayed on my screen not a line , l

Then you have to get your screen as bitmap and call StretchBlt to copy the bits to the printer HDC.

Note, you would get better results in the PDF if you would individually draw all elements (text, lines, images) of the page to the printer, cause by copying from the screen you'll get a very bad resolution (compared to printer) what especially would be seen with text output.
Avatar of Sohela

ASKER

Thanks for your reply but how do we know how much of the screen is to be captured through the code and i dont know what function or code is to be used  to get screen as bitmap.
>>>> but i want to print the whole page what is displayed on my screen not a line
Uh....  Duh.
The code I provided was to demonstrate the important flaw in your posted program.  Do as I suggested to verify that doing some output at that point will indeed create a PDF that is not a blank page.
 Then we can move on to the next step.
Avatar of Sohela

ASKER

I am sorry i didnt mean it like that i thought you didnt get my question correctly so i wrote that. I have included that TextOut function but the pdf document is still blank i used the GetLastError () function and there is a error in the StartDoc () function which is returning 13 that is The data is invalid. I dont know where is the error and even the docname is not coming as the filename.Thanks for your reply.
Avatar of Sohela

ASKER

I have changed some values in the textout function and the line is getting printed but after the function is executed it is still showing  the same error i.e the data is invalid.
TextOut(hDC, 0,0, "Test Printing", lstrlen( "Test Printing" );
>>>> lstrlen( "Test Printing" );
it either should be

       strlen( "Test Printing" );

or

     wcslen(L"Test Printing" );
Avatar of Sohela

ASKER

Ok to print the page as you mentioned i am trying to use BitBlt function but i dont know which functions i am supposed to use or where to like for using BitBlt  function i need to do CreateDC (), CreateCompatibleDC, CreateCompatibleBitmap () functions so i still need to use PrintDlg () ,InitDocStruct,(), StartDoc(), StartPage () or i need to skip anything i dont understand it. i dont know what changes should i make in the above code to include the code given below and where to fit this.Thanks.
HDC hdcScreen; 
	hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL); 
	d = GetLastError();
 
	HDC hdcCompatible;
	hdcCompatible = CreateCompatibleDC(hdcScreen); 
	d = GetLastError();
 
	HBITMAP hbmScreen;
	hbmScreen = CreateCompatibleBitmap(hdcScreen, 
									   GetDeviceCaps(hdcScreen, HORZRES), 
									   GetDeviceCaps(hdcScreen, VERTRES));
	d = GetLastError();
 
	HGDIOBJ  selObj;
	selObj = SelectObject(hdcCompatible, hbmScreen);
	d = GetLastError();
 
	BOOL shWin;
	shWin = ShowWindow(hWnd, SW_SHOW); 
	d = GetLastError();
 
	BOOL bit;
	bit = BitBlt(hdcCompatible, 0, 0, 10,10, 
			hdcScreen, 0, 0, SRCCOPY); 
	d = GetLastError();

Open in new window

The value returned from StartDoc (13) is the "print job ID" -- it is not an error code.  See:
    StartDoc
    http://msdn.microsoft.com/en-us/library/ms535793(VS.85).aspx
>>>> i am trying to use BitBlt function
Ok the BitBlt copied the screen contents to the compatible device context. But you woull need to copy it to the printer HDC. Use the StretchBlt for that as you have different dimensions (and you might have to rotate the bits).
Avatar of Sohela

ASKER

>>>>.Use the StretchBlt for that as you have different dimensions (and you might have to rotate the bits).
I have mad esome changes in the code the ooutput of this is like when we give print screen manually.I dont know what to give to get only the screen not the total with menu bars and title bars.I think i have to make changes in GetMetricSystem() arguments but what to make i am unable to understand.Thanks.
void PrintScreen (HWND hWnd)
{
	HDC hScreenDC;
 
	if ((hScreenDC = GetDC (hWnd)) != NULL) {
		HDC hMemDC;
 
		if ((hMemDC = CreateCompatibleDC (hScreenDC)) != NULL) {
			HBITMAP hFullScreenBitmap;
 
			int iScreenWidth  = GetSystemMetrics (SM_CXFULLSCREEN
);		   
		int iScreenHeight = GetSystemMetrics (SM_CYFULLSCREEN);		   
			
			if ((hFullScreenBitmap = CreateCompatibleBitmap (hScreenDC, iScreenWidth, iScreenHeight)) != NULL) {
				HBITMAP hDefaultBitmap = (HBITMAP) SelectObject (hMemDC, hFullScreenBitmap);
 
				// From screen to memory:
				BitBlt (hMemDC, 0, 0, iScreenWidth, iScreenHeight, hScreenDC, 0, 0, SRCCOPY);
				SelectObject (hMemDC, hDefaultBitmap);
				SelectObject (hMemDC, hFullScreenBitmap);
 
				// Printing:
				PRINTDLG pd = {0}; // Reset on declare
 
				pd.lStructSize = sizeof (pd);
				pd.Flags = PD_RETURNDEFAULT | PD_ALLPAGES | PD_RETURNDC;
				pd.nFromPage = 1;
				pd.nToPage =  1;
				pd.nCopies = 1;
 
				if (PrintDlg (&pd)) {
					if (pd.hDC) {
						// Scaling to fit on a printer page:
						double dblScreenRatio = (double) iScreenWidth / (double) iScreenHeight;
						int xPrnPixelsPerPage = GetDeviceCaps (pd.hDC, PHYSICALWIDTH);
						int xPrnPixelsMargin = GetDeviceCaps (pd.hDC, PHYSICALOFFSETX);
						int yPrnPixelsMargin = GetDeviceCaps (pd.hDC, PHYSICALOFFSETY);
						int printedWidth = xPrnPixelsPerPage - xPrnPixelsMargin * 2;
						int printedHeight = (int) ((double) printedWidth / dblScreenRatio);
 
						DOCINFO di = {0};
 
						di.cbSize = sizeof (di);
						di.lpszDocName = "Print Full Screen";
 
						StartDoc (pd.hDC, &di);
						StartPage (pd.hDC);
 
						// FINALLY!
						StretchBlt (pd.hDC,
									xPrnPixelsMargin, yPrnPixelsMargin, printedWidth, printedHeight,
									hMemDC, 0, 0, iScreenWidth, iScreenHeight, SRCCOPY);
 
						EndPage (pd.hDC);
						EndDoc (pd.hDC);
						DeleteDC (pd.hDC);
					}
					// Clean up after print dlg:
					if (pd.hDevMode) {
						GlobalFree (pd.hDevMode);
					}
					if (pd.hDevNames) {
						GlobalFree (pd.hDevNames);
					}
				}
				SelectObject (hMemDC, hDefaultBitmap);
				DeleteObject (hFullScreenBitmap);
			}
			DeleteDC (hMemDC);
		}
		ReleaseDC (NULL, hScreenDC);
	}
}

Open in new window

>>>> what to give to get only the screen not the total
You need to call GetWindowRect for the window/frame you want to print.

Then supply these coordinates to the BitBlt where you do the SRC_COPY

   RECT rect = { 0 };
   GetWindowRect(hwndFrame, &rect);
   BitBlt (hMemDC, 0, 0, rect.right-rect.left,  rect.bottom-rect.top, hScreenDC, rect.left, rect.top, SRCCOPY);
Avatar of Sohela

ASKER

>>>>>>..You need to call GetWindowRect for the window/frame you want to print.
 RECT rect = { 0 };
   GetWindowRect(hwndFrame, &rect);
   BitBlt (hMemDC, 0, 0, rect.right-rect.left,  rect.bottom-rect.top, hScreenDC, rect.left, rect.top, SRCCOPY);
Ater using this also i am getting the same whole screen is getting printed not with title bars ,menu bars and all.I dont know where more should i make changes.



Usw GetClientRect(), as I described in your other question.
>>>> the same whole screen is getting printed not with title bars ,

What is the hwndFrame (what window) ? And what are the coordinates you got back when calling GetWindowRect?

>>>> I dont know where more should i make changes

I would have a few ideas. You first could try to describe more thoroughly what you have done and waht were the results. I actually don't know whether you had any printouts til yet or whether you still were grabbing bitmaps from your screen.

>>>> Usw GetClientRect(), as I described in your other question.
GetClientRect returns a rectangle with top-left = (0, 0). I can't see why it should give better results when using it in a (source-)copying from screen to bitmap.
Avatar of Sohela

ASKER

>>>>>>>>>>What is the hwndFrame (what window) ? And what are the coordinates you got back hwndFrame i am passing the handle of the window which i have to print to pdf format.

>>>>>>>>>when calling GetWindowRect?
When i am calling GetWindowRect i am getting values
rect.right= 1280,
rect.left = 0,
rect.bottom = 904,
rect.top = 0,

>>>>>>I actually don't know whether you had any printouts til yet or whether you still were grabbing bitmaps from your screen.
Like i didnt understand what you meant by this i am trying to print to pdf file that is i give print option in the name of printer i select pdf complete.The changes what you told i made but it is still the same .I am attaching the code should i skip any thig from the code or replace anything .I have tried using GetClientRect() also it is giving the same output.
void PrintScreen (HWND hWnd)
{
	HDC hScreenDC;
 
	if ((hScreenDC = GetDC (hWnd)) != NULL) {
		HDC hMemDC;
 
		if ((hMemDC = CreateCompatibleDC (hScreenDC)) != NULL) {
			HBITMAP hFullScreenBitmap;
 
			int iScreenWidth  = GetSystemMetrics (SM_CXFULLSCREEN);		   
		    int iScreenHeight = GetSystemMetrics (SM_CYFULLSCREEN);
			
			 RECT rect = { 0 };
			 GetWindowRect(hwndFrame, &rect);
  
			if ((hFullScreenBitmap = CreateCompatibleBitmap (hScreenDC, iScreenWidth, iScreenHeight)) != NULL) {
				HBITMAP hDefaultBitmap = (HBITMAP) SelectObject (hMemDC, hFullScreenBitmap);
 
				// From screen to memory:
				 BitBlt (hMemDC, 0, 0, rect.right-rect.left,  rect.bottom-rect.top, hScreenDC, rect.left, rect.top, SRCCOPY);
				SelectObject (hMemDC, hDefaultBitmap);
				SelectObject (hMemDC, hFullScreenBitmap);
 
				// Printing:
				PRINTDLG pd = {0}; // Reset on declare
 
				pd.lStructSize = sizeof (pd);
				pd.Flags = PD_RETURNDEFAULT | PD_ALLPAGES | PD_RETURNDC;
				pd.nFromPage = 1;
				pd.nToPage =  1;
				pd.nCopies = 1;
 
				if (PrintDlg (&pd)) {
					if (pd.hDC) {
						// Scaling to fit on a printer page:
						double dblScreenRatio = (double) iScreenWidth / (double) iScreenHeight;
						int xPrnPixelsPerPage = GetDeviceCaps (pd.hDC, PHYSICALWIDTH);
						int xPrnPixelsMargin = GetDeviceCaps (pd.hDC, PHYSICALOFFSETX);
						int yPrnPixelsMargin = GetDeviceCaps (pd.hDC, PHYSICALOFFSETY);
						int printedWidth = xPrnPixelsPerPage - xPrnPixelsMargin * 2;
						int printedHeight = (int) ((double) printedWidth / dblScreenRatio);
 
						DOCINFO di = {0};
 
						di.cbSize = sizeof (di);
						di.lpszDocName = "Print Full Screen";
 
						StartDoc (pd.hDC, &di);
						StartPage (pd.hDC);
 
						// FINALLY!
						StretchBlt (pd.hDC,
									xPrnPixelsMargin, yPrnPixelsMargin, printedWidth, printedHeight,
									hMemDC, 0, 0, iScreenWidth, iScreenHeight, SRCCOPY);
 
						EndPage (pd.hDC);
						EndDoc (pd.hDC);
						DeleteDC (pd.hDC);
					}
					// Clean up after print dlg:
					if (pd.hDevMode) {
						GlobalFree (pd.hDevMode);
					}
					if (pd.hDevNames) {
						GlobalFree (pd.hDevNames);
					}
				}
				SelectObject (hMemDC, hDefaultBitmap);
				DeleteObject (hFullScreenBitmap);
			}
			DeleteDC (hMemDC);
		}
		ReleaseDC (NULL, hScreenDC);
	}
}

Open in new window

hg.pdf
ghhg.pdf
>>>> rect.left = 0
>>>> rect.top = 0,
It is the wrong window frame. You were taking mainframe window which is maximum sized on screen. Instead you should use the client window which should be a view or dialog window.

>>>> Like i didnt understand what you meant by this
I ask whether you already got a pdf printout or not?
Avatar of Sohela

ASKER

>>>> rect.left = 0
>>>> rect.top = 0,
It is the wrong window frame. You were taking mainframe window which is maximum sized on screen. Instead you should use the client window which should be a view or dialog window.

I have used even that but still i am getting the same output and like if i use either GetWindowRect  () and GetClientRect () the values what they are coming im storing it in iScreenHeight and iScreenWidth and these both i am using in various places in my code so should these values be in BitBlt function or everywhere i should use them as rect.right-rect.left,  rect.bottom-rect.top as you mentioned.

>>>>I ask whether you already got a pdf printout or not?
I attached two pdf files in the above post one is the pdf i am getting using code the other pdf i am getting when i do it manually there is a lot of variation. Would you please see them once.
>>>> I have used even that but still i am getting the same output
You need a window (handle) which has a top.left and top.right different to 0 cause point (0,0) is the top-left of the screen. GetClientRec always is wrong cause top-left is always (0,0) cause client coordinates are relative coordinates to the window itself.

>>>> Would you please see them once.
I was in a environment where I couldn't open attachments because of security reasons. I could look at them now and the second wasn't so bad, right?

>>>> the other pdf i am getting when i do it manually

In order to not have to do it manually, you need to identify the client window of your frame window. It should be the same hwnd which you use for drawing the shapes. If you call GetWindowRect for that you must get a top-left point different to (0,0).

Avatar of Sohela

ASKER

>>>>>>>>>>>I was in a environment where I couldn't open attachments because of security reasons. I could look at them now and the second wasn't so bad, right?

Actually the first pdf is the one which i am getting through code and the output should be like the one i showed in the second pdf file(the second pdf file i generated it manually) so i am supposed to get output like the second one whereas i am getting like the first one.

>>>>>>>. If you call GetWindowRect for that you must get a top-left point different to (0,0).
I am calling GetWindowRect but still i am getting (0, 0) how do i get other value for that.

>>>>>>>You need a window (handle) which has a top.left and top.right different to 0 cause point (0,0) is the top-left of the screen. GetClientRec always is wrong cause top-left is always (0,0) cause client coordinates are relative coordinates to the window itself.


And about the handle i am using GetActiveWindow()
i.e  hWnd = GetActiveWindow(); and i am passing this handle other than this i dont have any handles.I am sorry because it is taking a lot of your time but this is my first application in win32 thats why i am having so many problems.Thanks.

>>>>>>It is the wrong window frame. You were taking mainframe window which is maximum sized on screen. Instead you should use the client window which should be a view or dialog window.

How do we get view or dialog window.

>>>> I am calling GetWindowRect but still i am getting (0, 0) how do i get other value for that.

The window you were taking is the mainframe window. You need the client window of that which you could get by GetWindow(hwndFrame, GW_CHILD);

You also could try to save the client window when drawing the shapes into some global variable. That way you easoier could decide what is th right window cause the mainframe might have multiple child windows.
Avatar of Sohela

ASKER

>>>>>>>>GetWindow(hwndFrame, GW_CHILD);
I have used the above function in my code that i passed the handle from which we get from GetActiveWindow() to GetWindow() and inturn that handle to GetWindowRect function but i am not getting the required output.The output which i am getting from code is attatched to file i.e latest.pdfand ther equired output is OutRequired.pdf which i have atached below.Thanks.
	
{
	hWnd = GetActiveWindow();
	DWORD d = GetLastError();
 
	HWND hChild				= NULL;
	hChild = GetWindow(hWnd, GW_CHILD); 
	d = GetLastError();
 
	PrintScreen (hChild);
}
 
void PrintScreen (HWND hWnd)
{
	HDC hScreenDC;
 
	if ((hScreenDC = GetDC (hWnd)) != NULL) {
		HDC hMemDC;
 
		if ((hMemDC = CreateCompatibleDC (hScreenDC)) != NULL) {
			HBITMAP hFullScreenBitmap;
 
			RECT rect = { 0 };
			GetWindowRect(hWnd, &rect);
 
			int iScreenWidth = GetSystemMetrics (SM_CXFULLSCREEN);
			int iScreenHeight = GetSystemMetrics (SM_CYFULLSCREEN); 
					
			
			if ((hFullScreenBitmap = CreateCompatibleBitmap (hScreenDC, iScreenWidth, iScreenHeight)) != NULL)
			{
				HBITMAP hDefaultBitmap = (HBITMAP) SelectObject (hMemDC, hFullScreenBitmap);
 
				// From screen to memory:
			    BitBlt (hMemDC, 0, 0, rect.right-rect.left,  rect.bottom-rect.top, hScreenDC, rect.left, rect.top, SRCCOPY);
 
				SelectObject (hMemDC, hDefaultBitmap);
				SelectObject (hMemDC, hFullScreenBitmap);
 
				// Printing:
				PRINTDLG pd = {0}; // Reset on declare
 
				pd.lStructSize = sizeof (pd);
				pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;  // PD_RETURNDEFAULT | PD_ALLPAGES | PD_RETURNDC;
				pd.nFromPage = 1;
				pd.nToPage = 1;
				pd.nCopies = 1;
 
				if (PrintDlg (&pd)) 
				{
					if (pd.hDC)
					{
						// Scaling to fit on a printer page:
						double dblScreenRatio = (double) iScreenWidth / (double) iScreenHeight;
						int xPrnPixelsPerPage = GetDeviceCaps (pd.hDC, PHYSICALWIDTH);
						int xPrnPixelsMargin = GetDeviceCaps (pd.hDC, PHYSICALOFFSETX);
						int yPrnPixelsMargin = GetDeviceCaps (pd.hDC, PHYSICALOFFSETY);
						int printedWidth = xPrnPixelsPerPage - xPrnPixelsMargin * 2;
						int printedHeight = (int) ((double) printedWidth / dblScreenRatio);
 
						DOCINFO di = {0};
 
						di.cbSize = sizeof (di);
						di.lpszDocName = "Print123";
											
						StartDoc (pd.hDC, &di);
						StartPage (pd.hDC);
 
						StretchBlt (pd.hDC, xPrnPixelsMargin, yPrnPixelsMargin, printedWidth, printedHeight,
									hMemDC, 0, 0, iScreenWidth, iScreenHeight, SRCCOPY);
						EndPage (pd.hDC);
						EndDoc (pd.hDC);
						DeleteDC (pd.hDC);
					}
 
					// Clean up after print dlg:
					if (pd.hDevMode) {
						GlobalFree (pd.hDevMode);
					}
					if (pd.hDevNames) {
						GlobalFree (pd.hDevNames);
					}
				}
				SelectObject (hMemDC, hDefaultBitmap);
				DeleteObject (hFullScreenBitmap);
			}
			DeleteDC (hMemDC);
		}
		ReleaseDC (NULL, hScreenDC);
	}
}

Open in new window

latest.pdf
OutRequired.pdf
Avatar of Sohela

ASKER

>>>>>>>GetWindow(hwndFrame, GW_CHILD);
Also now i am getting some values in rect.left and rect.top instead of 0 which i was getting previously.
>>>> hChild = GetWindow(hWnd, GW_CHILD);
The problem with this is that it only gets the first child window which probably is one of the toolbar buttons or the menu window.

You would need to iterate by calling

   hNextChild = GetWindow(hWnd, GW_HWNDNEXT);

in a loop until you finally got the client window. It would be much easier if you would check how the whole thing was created. Framewindow, menus, toolbar buttuns and finally the client window which is the window where you made your drawings of the rectangles and lines.

You definitively would get a windows handle back when that window was created. Store this handle to a global variable which you define at the top of your source file below include statements:

#include <windows.h>

HWND hwndClient = NULL;

.....
// somewhere in your code the client window was created ...

       hwnd = CreateWindow(....
       // store the hwnd for later use
       hwndClient = hwnd;


// and later you may use

     if (hwndClient != NULL)
     {
           PrintScreen(hwndClient);      
     }


The problem with the GW_CHILD approach could be that the client window wasn't a direct child from frame window but a 'grand' child. You really better save it at creating time cause that is much easier.



>>>> hFullScreenBitmap = CreateCompatibleBitmap (hScreenDC, iScreenWidth, iScreenHeight))
don't create the bitmap using screen sizes but only sizes of the rectangle .

     hFullScreenBitmap = CreateCompatibleBitmap (hScreenDC, rect.right-rect.left, rect.bottom-rect.top);
Avatar of Sohela

ASKER

>>>> if (hwndClient != NULL)
     {
           PrintScreen(hwndClient);      
     }
.Why do we have to use this code as you mentioned without using this previously it was printing no in my code (Im just asking as to why we have to use this anything specific).

>>>>>You really better save it at creating time cause that is much easier
How can we save this at the time of creating.

>>>>>don't create the bitmap using screen sizes but only sizes of the rectangle .
>>>>> hFullScreenBitmap = CreateCompatibleBitmap (hScreenDC, rect.right-rect.left, rect.bottom-rect.top);

I am using  iScreenWidth and iScreenHeight in four places for all the places shoul i replace it with   rect.right-rect.left,  rect.bottom-rect.top values .
hFullScreenBitmap = CreateCompatibleBitmap (hScreenDC, iScreenWidth, iScreenHeight)

BitBlt (hMemDC, 0, 0, iScreenWidth, iScreenHeight, hScreenDC, 0, 0, SRCCOPY);

double dblScreenRatio = (double) iScreenWidth / (double) iScreenHeight;

StretchBlt (pd.hDC, xPrnPixelsMargin, yPrnPixelsMargin, printedWidth, printedHeight,
             hMemDC, 0, 0, iScreenWidth, iScreenHeight, SRCCOPY);

From my code should i remove anything or comment out some step which is not necessary since you have mentioned me to add PrintScreen function. Where can i place this function after which step.

Thanks a lot.


>>>> How can we save this at the time of creating
Check your sources for CreateWindow. One of these must be the window we are looking for. You might see some comments. But actually I don't expect that you have more than 2 or 3 windows created (but I might be wrong with that).

>>>> Why do we have to use this code as you mentioned ...

I only used the code you posted and tried to show you how to take the correct window ...

When I told you to have

   GetWindowRect(hwndFrame, &rect);

I assumed that your application has multiple frame windows where one is that you wanted to print.

But obviously I was wrong with that - as I saw from your total screen image.

>>>> I am using  iScreenWidth and iScreenHeight in four places ...
>>>> shoul i replace it with   rect.right-rect.left,  rect.bottom-rect.top values .


Yes. As you want to print only a partial screen you might not use full screen sizes. For the output things might be different. You could increase  the sizes up to the sizes of the print device (but not changing the ratio between width and height).
Another way to find the target window is to use Spy++ (availube under the Visual Studios Tools menu)
Use its Find Window feature --- just move the mouse around until the inner window has a highlighting border, then check that window's properties. The classname or other attribute might provide enough identifying information so that you can use Win API funtctions such as GetWindow to focus in on the child window you want.
=-=-=-=
Going back to the original question -- you want to be able to "print any file to PDF."
Well, the route we are going will only allow you to print the visible content of a specific window. It does not generalize at all. If part of the data is "below the bottom" of the window, then it will not be printed.
I just thought we should clarify that now. If you want to make screen dumps to PDFs, then we are on the right track. If you want to print "any file" then we are not.
Avatar of Sohela

ASKER

>>>>>>>>I just thought we should clarify that now. If you want to make screen dumps to PDFs, then we are on the right track. If you want to print "any file" then we are not.

I want print to pdf file i dont want screen dumps and about the print any file i meant that it can a text file or a cad part file all these files content  should be printed to pdf file.At present what i am getting output is like when we do print screen because for the same file the output is different when we do it manualy(without code for checking).I have shown files in the above posts output.pdf is that which i am getting presently through code and OutRequired.pdf is the format in which i want the output to get printed.
Avatar of Sohela

ASKER

>>>>>When I told you to have
>>>>>  GetWindowRect(hwndFrame, &rect);
>>>>I assumed that your application has multiple frame windows where one is that you wanted to print.
>>>>>But obviously I was wrong with that - as I saw from your total screen image.

Then what should i do now should i change the code now.
Avatar of Sohela

ASKER

I mentioned about my output which i am getting through code it is you can refer to latest.pdf or hg.pdf i mentioned it as output.pdf by mistake inj my above post.
>>>> Then what should i do now should i change the code now.
You already did some changes that were good but we still have problems to get the right window and you were still using wrong sizes and rectangles.

1. Find the client window

Did you check your code for calls of CreateWindow?
 
If yes, did any of these calls look like the creation of a client window?
     Did you save the hwnd returned from that CreateWindow then into a global variable for later use?  

If no, did you find the function where the drawing of the construction image was made?
     Did you save the hwnd used in that drwaing function into a global variable for later use?

if again no, did you loop thru all child windows of the hwndFrame by calling hwnd = GetWindow(hwnd, GW_CHILD)  and hwnd = GetWindow(hwnd, GW_HWNDNEXT) and check all rectangles of these child windows if one of them could be the client window?

If you don't find the client window (hwnd) by neither way you could calculate the client window rectangle by taking rectangle of hwndFrame and add/subtract the sizes for title, menu, lines until you reached the left-top of the client area. The sizes for those elements you would get by GetSystemMetrics.

2. Use the correct sizes for BitBlt and StretchBlt.

The first BitBlt where you were grabbing picture from screen *MUST* have 0, 0 for the target (bitmap) origin, must have the width and height of the client area to grab, must have the left-top of the client area in windows coordinates in order to grab the total client area but nothing else.

For all further BitBlt or StretchBlt you might take the same sizes and always (0, 0) as top-left as well for target and source cause if you already picked only the image to print you may not make this image smaller (as it looked in your latest.pdf) by using an offset in the top-left of the source to copy.

Finally, if your image has not the correct output size in the pdf (I assume it will be smaller), you may increase the sizes of output image by increasing the output sizes in StretchBlt (but not changing the ratio).

     
Avatar of Sohela

ASKER

At present i cannot check the code because i am not at work place is it ok if i cannot check the code now.It may take another two days before i check the code again is it fine with you or should i accept the solution and give you points.Please reply.Thanks
>>>> It may take another two days before i check the code
That is ok. You may not close the question if there is still something open.

Avatar of Sohela

ASKER

>>>>>>>>That is ok. You may not close the question if there is still something open.
Thanks a lot
Avatar of Sohela

ASKER

hiiii,
>>> hwndFrame by calling hwnd = GetWindow(hwnd, GW_CHILD)  and hwnd = GetWindow(hwnd, GW_HWNDNEXT) and check all rectangles of these child windows if one of them could be the client window?

i have done the above step what you specified but still i am getting the same result

>>>>.If you don't find the client window (hwnd) by neither way you could calculate the client window rectangle by taking rectangle of hwndFrame and add/subtract the sizes for title, menu, lines until you reached the left-top of the client area. The sizes for those elements you would get by GetSystemMetrics.

I am using GetSystemMetrics (SM_CXBORDER) or what argument should i pass in GetSystemMetrics function to get the size of the menu.Thanks
Avatar of Sohela

ASKER

Here when i do hNextChild = GetWindow(hWnd, GW_HWNDNEXT); and pass hNextChild in GetWindowRect(hNextChild , &rect); instead of GetWindowRect(hWnd, &rect); i am getting output as balckscreen.Maybe i am not doing it correctly.

	HWND hChild				= NULL;
	hChild = GetWindow(hWnd, GW_CHILD); 
	d = GetLastError();
 
	HWND hNextChild				= NULL;
	hNextChild = GetWindow(hWnd, GW_HWNDNEXT); 
	d = GetLastError();
 
	PrintScreen (hWnd, hNextChild);
 
void PrintScreen (HWND hWnd, HWND hChild)
{
     HDC hScreenDC;
     if ((hScreenDC = GetDC (hWnd)) != NULL) {
     HDC hMemDC;
 
    if ((hMemDC = CreateCompatibleDC (hScreenDC))!=NULL) 
    {
	HBITMAP hFullScreenBitmap;
         RECT rect = { 0 };
         GetWindowRect(hWnd, &rect);
 
         int iScreenWidth = GetSystemMetricsSM_CXFULLSCREEN);
	int iScreenHeight = GetSystemMetrics (SM_CYFULLSCREEN); 
 
         if ((hFullScreenBitmap = CreateCompatibleBitmap (hScreenDC,   
                                                         rect.right-                                                         rect.left, 
                                                         rect.bottom-                                                         rect.top)) != 
                                                         NULL)
        {
	  HBITMAP hDefaultBitmap = (HBITMAP) SelectObject (hMemDC, 
                                                 hFullScreenBitmap);
 
	// From screen to memory:
	BitBlt (hMemDC, 0, 0, rect.right-rect.left, rect.bottom- 
                 rect.top, hScreenDC, rect.left, rect.top, SRCCOPY);
 
	SelectObject (hMemDC, hDefaultBitmap);
	SelectObject (hMemDC, hFullScreenBitmap);
 
	// Printing:
	PRINTDLG pd = {0}; // Reset on declare
 
	pd.lStructSize = sizeof (pd);
         pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;  		pd.nFromPage = 1;
	pd.nToPage = 1;
	pd.nCopies = 1;
 
	if (PrintDlg (&pd)) 
	{
	    if (pd.hDC)
	    {
	       // Scaling to fit on a printer page:
	      double dblScreenRatio = (double) iScreenWidth /    
                                       (double) iScreenHeight;
						
              int xPrnPixelsPerPage = GetDeviceCaps (pd.hDC, 
                                      PHYSICALWIDTH);
						
             int xPrnPixelsMargin = GetDeviceCaps (pd.hDC, 
                                      PHYSICALOFFSETX);
						
             int yPrnPixelsMargin = GetDeviceCaps (pd.hDC, 
                                    PHYSICALOFFSETY);
						
            int printedWidth = xPrnPixelsPerPage - xPrnPixelsMargin * 2;
						
            int printedHeight = (int) ((double) printedWidth /        
                                 dblScreenRatio);
 
	  DOCINFO di = {0};
 
	 di.cbSize = sizeof (di);
	 di.lpszDocName = "Print123";
								StartDoc (pd.hDC, &di);
	StartPage (pd.hDC);
 
	StretchBlt (pd.hDC, xPrnPixelsMargin, yPrnPixelsMargin, 
                     printedWidth, printedHeight,hMemDC, 0, 0, 
                     iScreenWidth, iScreenHeight, SRCCOPY);
 
	EndPage (pd.hDC);
	EndDoc (pd.hDC);
	DeleteDC (pd.hDC);
     }
    // Clean up after print dlg:
    if (pd.hDevMode) {GlobalFree (pd.hDevMode);}
    if (pd.hDevNames) {GlobalFree (pd.hDevNames);}
  }
  SelectObject (hMemDC, hDefaultBitmap);
  DeleteObject (hFullScreenBitmap);
 }
 DeleteDC (hMemDC);
}
ReleaseDC (NULL, hScreenDC);
}
}

Open in new window

Avatar of Sohela

ASKER

>>>>>>>>>The problem with this is that it only gets the first child window which probably is one of the toolbar buttons or the menu window.

You would need to iterate by calling

   hNextChild = GetWindow(hWnd, GW_HWNDNEXT);

in a loop until you finally got the client window.
I am iterating this value hNextChild = GetWindow(hWnd, GW_HWNDNEXT); but i am getting the same valuee in the handle.

>>>>> It would be much easier if you would check how the whole thing was created. Framewindow, menus, toolbar buttuns and finally the client window which is the window where you made your drawings of the rectangles and lines.

How can we check how was the whole thing created like which window it is



ASKER CERTIFIED SOLUTION
Avatar of itsmeandnobodyelse
itsmeandnobodyelse
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Sohela

ASKER

>>>>>>The hWnd argument need to be changed with each iteration:

          HWND hwndNext = GetWindow(hWnd, GW_FIRSTCHILD);
          while (hwndNext != NULL)
          {
                RECT rect = { 0 };
                GetWindowRect(hwndNext, &rect);
                // check here the rectangle whether it could be the client rect you were looking for


                // next iteration
                hwndNext = GetWindow(hwndNext , GW_HWNDNEXT);

          }

I have implemented the code and i was debugging it iterated 11 times how should i know over here which is the correct window. Each time i notd the values of rect.left, rect.right, rect.top, rect.bottom i checked for the first and last handle values i am adding the file for the first handle value.And whenever i am going into debug mode it is printing the code screen not my part screen whereas if i am executing it is taking the coorect screen can u try to tell me why this is happening.Here the output what i am getting and what i am supposed to get is different should i make anymore changes.Thanks.
latest-output.pdf
required-output.pdf
Avatar of Sohela

ASKER

Thanks a lot for replying for the question i still have some doubts but thanks a lotttt.
>>>> it iterated 11 times how should i know over here which is the correct window.

You could call your PrintScreen for each of it (maybe by adding some kind of name or the rectangle coordinates).


>>>> it is printing the code screen not my part screen whereas if i am executing it is taking the coorect screen can u try to tell me why this is happening.
If you were grabbing from screen while the debugger is active you rarely have a chance to grab your application's screen but that what the screen shows to the time of grabbing ... beside you would grab the whole screen only once - before breaking into the debugger - and then take that 'hardcopy' as source for any further grab.

Could you post all calls to BitBlt, StretchBlt including how you determind the rectangles used for each of the calls?  
Avatar of Sohela

ASKER

hiii thanks for replying i checked  the rect values for each iteration and for the first iteration what values i was getting that only was giving correct screen but at the bottom it was giving the task bar so i subtracted some values from that.But there is still some difference like in the output file it is capturing screen and printing but when i do it without using code output is different right (i am attaching the files) only the lines are getting printed.Thanks.
    hWnd = GetActiveWindow();
	DWORD d = GetLastError();
 
	HWND hwndNext				= NULL;
	hwndNext = GetWindow(hWnd, GW_CHILD); 
	d = GetLastError();
 
	RECT rect = { 0 };
	GetWindowRect(hwndNext, &rect);
 
	PrintScreen (hWnd, hwndNext);
 
	void PrintScreen (HWND hWnd, HWND hChild)
	{
		HDC hScreenDC;
		char szmessage[133] = "";
 
		if ((hScreenDC = GetDC (hWnd)) != NULL) {
		HDC hMemDC;
		
		if ((hMemDC = CreateCompatibleDC (hScreenDC)) != NULL)
		{
			HBITMAP hFullScreenBitmap;
 
			int iScreenWidth = GetSystemMetrics (SM_CXFULLSCREEN);
			int iScreenHeight = GetSystemMetrics (SM_CYFULLSCREEN); 
 
			int nLeft, nTop, nWidth, nHeight;
			RECT rect = { 0 };
			RECT rect1 = { 0 };
			char szNewExp[1024]      = "\0";				// String value
 
			GetWindowRect(hChild, &rect);
 
			if ((hFullScreenBitmap = CreateCompatibleBitmap (hScreenDC, rect.right-rect.left, rect.bottom-rect.top)) != NULL)
			{
				HBITMAP hDefaultBitmap = (HBITMAP) SelectObject (hMemDC, hFullScreenBitmap);
 
				// From screen to memory:
				BitBlt (hMemDC, 0, 0, rect.right-rect.left, rect.bottom-rect.top, hScreenDC, rect.left, rect.top, SRCCOPY);
				SelectObject (hMemDC, hDefaultBitmap);
				SelectObject (hMemDC, hFullScreenBitmap);
 
				// Printing:
				PRINTDLG pd = {0};				//  Reset on declare
 
				pd.lStructSize = sizeof (pd);
				pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;  // PD_RETURNDEFAULT | PD_ALLPAGES | PD_RETURNDC;
				pd.nFromPage = 1;
				pd.nToPage = 1;
				pd.nCopies = 1;
 
				if (PrintDlg (&pd)) 
				{
					if (pd.hDC)
					{
						// Scaling to fit on a printer page:
						double dblScreenRatio = (double) iScreenWidth / (double) iScreenHeight;
						int xPrnPixelsPerPage = GetDeviceCaps (pd.hDC, PHYSICALWIDTH);
						int xPrnPixelsMargin = GetDeviceCaps (pd.hDC, PHYSICALOFFSETX);
						int yPrnPixelsMargin = GetDeviceCaps (pd.hDC, PHYSICALOFFSETY);
						int printedWidth = xPrnPixelsPerPage - xPrnPixelsMargin * 2;
						int printedHeight = (int)((double) printedWidth / dblScreenRatio);
 
						DOCINFO di = {0};
						di.cbSize = sizeof (di);
						di.lpszDocName = "C:\\Printing.pdf";
															
						StartDoc (pd.hDC, &di);
						StartPage (pd.hDC);
 
						StretchBlt (pd.hDC, xPrnPixelsMargin, yPrnPixelsMargin, printedWidth, printedHeight,
									hMemDC, 0, 0, rect.right-rect.left, ((rect.bottom-rect.top)-27), SRCCOPY);
 
						EndPage (pd.hDC);
						EndDoc (pd.hDC);
						DeleteDC (pd.hDC);
					}
 
					// Clean up after print dlg:
					if (pd.hDevMode) {
						GlobalFree (pd.hDevMode);
					}
					if (pd.hDevNames) {
						GlobalFree (pd.hDevNames);
					}
				}
				SelectObject (hMemDC, hDefaultBitmap);
			
				DeleteObject (hFullScreenBitmap);
			}
			DeleteDC (hMemDC);
		}
		ReleaseDC (NULL, hScreenDC);
	}
}

Open in new window

required-output.pdf
Printing.pdf
This is what I told you before (see: http:#22800030)
You are now printing the screen.  What you really need to do is invoke the function of that program that will cause it to format and print the file.
Avatar of Sohela

ASKER

>>>   (see: http:#22800030)  Going back to the original question -- you want to be able to "print any file to PDF."
Well, the route we are going will only allow you to print the visible content of a specific window. It does not generalize at all. If part of the data is "below the bottom" of the window, then it will not be printed.

I just thought we should clarify that now. If you want to make screen dumps to PDFs, then we are on the right track. If you want to print "any file" then we are not.

Ya i need part of the data is "below the bottom" of the window also to be printed. how can we get it.
As is stated quite clearly in http:#a22865579
What you really need to do is invoke the function of that program that will cause it [that program] to format and print the file.
Avatar of Sohela

ASKER

>>>>What you really need to do is invoke the function of that program that will cause it [that program] to format and print the file.

I dont think i can use spy++ and i am calling that function only can you tell me in the code like which one i am supposed to call.