|
Hello there,
I see some questions on the forum regarding this subject, I have solved it for myself through the following function. If you call this function like this
int PreviousOrientation = SetDefaultPrinterOrientation(DMORIENT_LANDSCAPE);
It will switch printing to Landscape, and you can use the returned value to set it back to whatever it was set before the call, by passing that value and calling it again.
Hope someone can find this useful
Cheers
Alex
#include "winspool.h"
int SetDefaultPrinterOrientation(short dmOrientation)
{
HANDLE hPrinter = NULL;
DWORD dwNeeded = 0;
PRINTER_INFO_2 *pi2 = NULL;
DEVMODE *pDevMode = NULL;
PRINTER_DEFAULTS pd;
BOOL bFlag;
LONG lFlag;
LPTSTR pPrinterName = NULL;
DWORD size;
GetDefaultPrinter(NULL, &size);
TCHAR* buffer = new TCHAR[size];
if(GetDefaultPrinter(buffer, &size))
pPrinterName = buffer;
else
{
if(buffer != NULL)
delete buffer;
return 0;
}
// Open printer handle (on Windows NT, you need full-access because you
// will eventually use SetPrinter)...
ZeroMemory(&pd, sizeof(pd));
pd.DesiredAccess = PRINTER_ALL_ACCESS;
bFlag = OpenPrinter(pPrinterName, &hPrinter, &pd);
if (!bFlag || (hPrinter == NULL))
{
if(buffer != NULL)
delete buffer;
return 0;
}
// The first GetPrinter tells you how big the buffer should be in
// order to hold all of PRINTER_INFO_2. Note that this should fail with
// ERROR_INSUFFICIENT_BUFFER. If GetPrinter fails for any other reason
// or dwNeeded isn't set for some reason, then there is a problem...
SetLastError(0);
bFlag = GetPrinter(hPrinter, 2, 0, 0, &dwNeeded);
if ((!bFlag) && (GetLastError() != ERROR_INSUFFICIENT_BUFFER) || (dwNeeded == 0))
{
ClosePrinter(hPrinter);
if(buffer != NULL)
delete buffer;
return 0;
}
// Allocate enough space for PRINTER_INFO_2...
pi2 = (PRINTER_INFO_2 *)GlobalAlloc(GPTR, dwNeeded);
if (pi2 == NULL)
{
ClosePrinter(hPrinter);
if(buffer != NULL)
delete buffer;
return 0;
}
// The second GetPrinter fills in all the current settings, so all you
// need to do is modify what you're interested in...
bFlag = GetPrinter(hPrinter, 2, (LPBYTE)pi2, dwNeeded, &dwNeeded);
if (!bFlag)
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
if(buffer != NULL)
delete buffer;
return 0;
}
// If GetPrinter didn't fill in the DEVMODE, try to get it by calling DocumentProperties...
if (pi2->pDevMode == NULL)
{
dwNeeded = DocumentProperties(NULL, hPrinter,pPrinterName,NULL, NULL, 0);
if (dwNeeded <= 0)
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
if(buffer != NULL)
delete buffer;
return 0;
}
pDevMode = (DEVMODE *)GlobalAlloc(GPTR, dwNeeded);
if (pDevMode == NULL)
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
if(buffer != NULL)
delete buffer;
return 0;
}
lFlag = DocumentProperties(NULL, hPrinter,pPrinterName, pDevMode, NULL,DM_OUT_BUFFER);
if (lFlag != IDOK || pDevMode == NULL)
{
GlobalFree(pDevMode);
GlobalFree(pi2);
ClosePrinter(hPrinter);
if(buffer != NULL)
delete buffer;
return 0;
}
pi2->pDevMode = pDevMode;
}
// Driver is reporting that it doesn't support this change...
if (!(pi2->pDevMode->dmFields & DM_ORIENTATION))
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
if (pDevMode)
GlobalFree(pDevMode);
if(buffer != NULL)
delete buffer;
return 0;
}
// Specify exactly what we are attempting to change...
pi2->pDevMode->dmFields = DM_ORIENTATION;
// Make note of the current Orientation setting
// If the functions works, return it to the calling program
// So that, the application can set it back to whatever
// it used to be before the call
int OriginalOrientation = pi2->pDevMode->dmOrientation;
// Now, change it to whatever was requested by the calling application
pi2->pDevMode->dmOrientation = dmOrientation;
// Do not attempt to set security descriptor...
pi2->pSecurityDescriptor = NULL;
// Make sure the driver-dependent part of devmode is updated...
lFlag = DocumentProperties(NULL, hPrinter, pPrinterName, pi2->pDevMode, pi2->pDevMode, DM_IN_BUFFER | DM_OUT_BUFFER);
if (lFlag != IDOK)
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
if (pDevMode)
GlobalFree(pDevMode);
if(buffer != NULL)
delete buffer;
return 0;
}
// Update printer information...
bFlag = SetPrinter(hPrinter, 2, (LPBYTE)pi2, 0);
if (!bFlag) // The driver doesn't support, or it is unable to make the change...
{
GlobalFree(pi2);
ClosePrinter(hPrinter);
if (pDevMode)
GlobalFree(pDevMode);
if(buffer != NULL)
delete buffer;
return 0;
}
// Tell other apps that there was a change...
SendMessageTimeout(HWND_BROADCAST, WM_DEVMODECHANGE, 0L,(LPARAM)(LPCSTR)pPrinterName, SMTO_NORMAL, 1000, NULL);
// Clean up...
if (pi2)
GlobalFree(pi2);
if (hPrinter)
ClosePrinter(hPrinter);
if (pDevMode)
GlobalFree(pDevMode);
if(buffer != NULL)
delete buffer;
return OriginalOrientation;
}
|
|
|
|
|
Thanks for this useful addition. Personally, I think the above should be made a mini-article of its own.
|
|
|
|
|
Hi Johan
Thanks for your feedback, I just uploaded something to the site, including one extra function to set up paper type / size
Cheers
Alex
|
|
|
|
|
Hi Again
if Ruler measurment is Pixel
the above Method makes HorzRuler & VertRuler to fall in endless loop because of negative segment and application crashs !
the quick workaround could be this that makes Rulers stable if
m_zoomMin is not less than 0.5
<br />
SetZoom( max(min( zoomx, zoomy ),m_zoomMin) );<br />
<big>OR BETTER SOLUTION</big><br />
void CReportEditor::SetZoom( double zoom )<br />
{ <br />
int z = static_cast< int >( zoom * 100.0 );<br />
CDiagramEditor::SetZoom( zoom );<br />
GetParent()->SendMessage( UWM_ZOOM, z );<br />
}<br />
<big>change to</big><br />
void CReportEditor::SetZoom( double zoom )<br />
{ <br />
CDiagramEditor::SetZoom( zoom );<br />
int z = static_cast< int >( CDiagramEditor::GetZoom() * 100.0 );<br />
GetParent()->SendMessage( UWM_ZOOM, z );<br />
}<br />
but i think u should also revise the DrawScale loop of Rulers.
REGARDS PEIMAN
i really love this code
|
|
|
|
|
Thanks a lot for the feedback!
The latter method would indeed be prefered - but I'll also do something to the UWM_ZOOM -handler.
|
|
|
|
|
Hi Dear Johan thanks for ur Nice Work .
BTW
The thickness for those items are not handled while zoom is changed and they were displayed with fixed thickness.
REGARDS PEIMAN
|
|
|
|
|
Thanks for the feedback!
If the thickness is not changed, and you've set an explicit width, it's a bug, I must admit.
|
|
|
|
|
Hi
just because of topic relation .
setting the value of thickness in thier respective property dialogs had been omitted except for Line.:->
REGARDS Peiman
|
|
|
|
|
How can me makes the images as the Reports background?
crystalice
|
|
|
|
|
I might be missing something here? The answer would seem to be "put an image field in the report and the other fields above it" - as this seems a bit simple, perhaps I'm misunderstanding you?
|
|
|
|
|
Hi there!
I have a template with a couple of fields at the top (combined page head/report head), below that a indefinite amount of data, and below that a couple of fields which sums the data in the grid (side foot/report foot). How do I get the size/height/number of rows of the grid to be minimal? I do not want the fields under the grid at the bottom of the page - they shold "follow" the last row of the grid.
* When I make three templates (one for the head, one for the data and one for the foot), it will be page brekings between the templates which I don't want.
* When I put all the three templates in one template, I will not get the sum exactly under the last row in the grid.
How do I solve the problem? All solutions and hints are very appreciated!
Johan - mycket bra verktyg förövrigt!
/Felix
|
|
|
|
|
Felix,
This is not supported functionality supported, but indeed already suggested. Given that I have a todo-list long as an arm and a leg, I have no idea when I'll get time to go through it, though
The functionality you need is not trivial to add, although it will sooner or later be implemented. In wait for that, you might perhaps try to arrange the grid in such a way that you can reuse cells for the sums? With gridlines turned of, perhaps using separators, you might get an acceptable layout anyway?
|
|
|
|
|
Oh...!
Of course... Almost embarrassing that I didn't figured out that solution by my self.
Thanks alot for the answer, and good luck with the huuuuuuuuge todo-list!
/Felix
|
|
|
|
|
Helo Johan,
It is possible to print to a fax using the fax printer driver, local o server?.
I am making tests and the result is negative at the moment.
Thanks in anticipation.
Tomas
-- modified at 6:33 Friday 28th October, 2005
|
|
|
|
|
My experience of fax servers is not exactly fresh, I would rather call the positively ancient
I the olden days, far, far back, some faxes emulated printers - you'd just have to select them as any other printer, and then print away. Some special treatment was necessary for adding the phone number, but the heavily calcinated brain I call my own remembers no details. This is a typical question for your fax server software. You might, of course, not have any documentation relating to development for the unit, but the manufacturer homepage might have info on how to do it.
|
|
|
|
|
First of all, congratulations for this good work.
I am trying to use this class in an MFC-MDI application.
I want to use the class ReportGenerator in some views derived from CListView.
I have created a member m_reportGenerator in each class where I need to print a report.
In each view there is a button to print. This button call a function that generate the report and when the report is generated I use m_reportGenerator.Print() and the report is printed in the default printer. This work perfect without problems.
Now I would like to do PrintPreview but not exist the function m_reportGenerator.PrintPreview().
Three questions:
1 - How can I do PrintPreview in each view where I need?.
2 - How can I set the LANDSCAPE or PORTRAIT mode for each report?.
3 - Wich is the correct way to print in special paper, for example labels in folders or in continuous paper?.
Any example or link will be appreciated.
Thanks in anticipation.
Tomas.
|
|
|
|
|
Thanks for your feedback, appreciated!
For print previews, you use Print as well. The demo application contains an example on how to do this - here, the print preview previews not the normal view, but the report instead.
Changing orientation is something you do in the printer driver. And example from MSDN is here:http://support.microsoft.com/default.aspx?scid=kb;en-us;214617[^]
Special paper is the same - you tell the driver that you want to use it. The report templae will - of course - have to match the paper size.
|
|
|
|
|
I am trying to prove the code in VC 2003 but I have a error in this class:
class CBorderLine
{
public:
// Construction/destruction
CBorderLine();
virtual ~CBorderLine();
operator = ( const CBorderLine& line )
{
m_visible = line.m_visible;
m_style = line.m_style;
m_color = line.m_color;
m_thickness = line.m_thickness;
};
...
Error C4716: 'CBorderLine::operator=' : must return a value
Anybody knows the solution.
Thanks in anticipation.
Tomas.
|
|
|
|
|
Tomas,
You'll have to return a:
return *this;
at the end of the function.
|
|
|
|
|
Sorry Johan, I am very beginner.
operator=( const CBorderLine& line )
{
m_visible = line.m_visible;
m_style = line.m_style;
m_color = line.m_color;
m_thickness = line.m_thickness;
} return *this; <---- Is here?
Sintax error.
Can you tell me the correct syntax of this function?.
Thanks.
Tomas.
|
|
|
|
|
Tomas,
One step up, so:
operator=( const CBorderLine& line )
{
m_visible = line.m_visible;
m_style = line.m_style;
m_color = line.m_color;
m_thickness = line.m_thickness;
return *this;}
|
|
|
|
|
operator=( const CBorderLine& line )
{
m_visible = line.m_visible;
m_style = line.m_style;
m_color = line.m_color;
m_thickness = line.m_thickness;
return *this;
}
Error C2440: 'return': it is not possible to be made conversion of 'CBorderLine' to 'int'
Any suggestion?
Thanks in anticipation.
Tomas.
|
|
|
|
|
If you need to write an expression like:
a=b=c;
where a,b,c are CBorderLine objects, change the method like this:
CBorderLine& operator=( const CBorderLine& line )
{
m_visible = line.m_visible;
m_style = line.m_style;
m_color = line.m_color;
m_thickness = line.m_thickness;
return *this;
}
otherwise you can also write it in this way:
void operator=( const CBorderLine& line )
{
m_visible = line.m_visible;
m_style = line.m_style;
m_color = line.m_color;
m_thickness = line.m_thickness;
}
Fil (il genio)
|
|
|
|
|
Now no longer it shows an error message.
Thanks a lot.
Tomas
|
|
|
|
|
Hello!
First of all, congratulations for this pretty piece of work!
Now, i've been trying Report Generator as an alternative to my own report engine, but some weird things came up..
I started playing with Report Creator and Report Generator Demo, previewing and printing the reports, and all went fine. The problem happenned when i tried to use these same reports with one of my apps, wich works as a set of forms switched programmaticaly (in other terms, that doesn't rely on mfc doc/view architecture for managing views) and the reports print with clipped margins. The paper size of the output is correct, but for what i can see all elements have been moved to the upper left corner, and some of then are not even appearing in the output.
The print function is very simple, since i'm begginning to adjust it to my needs, and uses the CReportGenerator::Print() method to actually print the reports. As i wansn't able to manage what was going on with the output, i created a blank sdi project and associated a menuitem with the same print function i was using with the original app, and as it happenned with the demo, the output was perfect.
I've compiled all the apps with Visual Studio .NET 2003.
Since i have no idea what's going on, hope you can help me.
Regards,
Marlon Gaspar.
|
|
|
|
|