http://blog.csdn.net/xuqiang918/article/details/39962341
http://blog.csdn.net/xjkstar/article/details/25828097 recommend it is good.
dialog box print, a lot of online search, basically divided into 2 categories:
Class A: Cprintdialog.domodal, and then in the modal dialog box to select the printer, print configuration;
Class B: Getprinterdevicedefaults, calling the default printer.
My job is to understand the above 2 categories, and then according to MSDN, the MDF dialog box background to specify the printer printing.
No more nonsense, serve the dishes ~
Function: MFC Printing based on dialog box (non-document view structure), specifying printer, spooling (no pop-up dialog box)
Ideas:
1. Enumerate the printers and select one of them;
2, cprintdialog instance designated to the selected printer;
3, CPrintDialog Background printing
Specific implementation:
1, variable (control). In the dialog box to add a ComboBox (IDC_COMBO1, corresponding variable m_cboprint), an edit (idc_edit1), edit allow carriage return, multi-line (code is not pasted, know MFC should understand);
2, in the OnInitDialog to enumerate printer devices, if the report function is not defined, add header file #include <winspool.h>
Need to call two times the EnumPrinters function, the first time to the size of the structure, the second to get the printer list
[CPP] View plaincopy The code slice to my Code slice
TODO: Add additional initialization code here
DWORD dwneeded;
DWORD Dwreturn;
DWORD Dwflag = Printer_enum_connections | printer_enum_local;
EnumPrinters (Dwflag, NULL, 4, NULL, 0, &dwneeded, &dwreturn);
printer_info_4* P4;
P4 = new printer_info_4[dwneeded];
EnumPrinters (Dwflag, NULL, 4, (Pbyte) P4, dwneeded, &dwneeded, &dwreturn);
for (int i = 0; i< (int) Dwreturn; i++)
This->m_cboprint.addstring (P4[i].pprintername);
delete []p4;
3, Operation dialog box, in the IDC_EDIT1 input print content, in the Idc_combo1 selected printer;
4, printing (I use the OK button to print, everyone casually)
[CPP] View plaincopy The code slice to my Code slice
TODO: Add control notification Handler code here
Cdialogex::onok ();
This->updatedata ();
CString strmessage;
CString Strprintdevice;
This->getdlgitem (IDC_EDIT1)->getwindowtextw (strmessage);
strmessage + = _t ("\ r \ n"); Add end to make it easier to read printed data later
This->getdlgitem (IDC_COMBO1)->getwindowtextw (Strprintdevice);
DWORD Dwflag = Pd_allpages | Pd_nopagenums | pd_usedevmodecopies | Pd_hideprinttofile; Print Configuration Interface button availability, because the background printing, in fact, this configuration has no meaning
CPrintDialog Pprintdlg (FALSE, Dwflag, this); CPrintDialog instantiation, because MFC's print device is irrelevant, it can be understood that this is a printer
Hglobal Hdevmode = NULL;
Hglobal hdevnames = NULL;
if (Getprinterdevice (Strprintdevice.getbuffer (0), &hdevnames, &hdevmode))//Get the specified printer configuration, name
AfxGetApp ()->selectprinter (hDevNames, Hdevmode);
Else
AfxMessageBox (_t ("Failed to select Custom Printer"));
Strprintdevice.releasebuffer ();
PPrintdlg.m_pd.hDevMode = Hdevmode; Let Pprintdlg use the printer we specified
PPrintdlg.m_pd.hDevNames = hDevNames;
CDC DC;
dc. Attach (PPRINTDLG.CREATEPRINTERDC ()); Background print creation method, if need to eject the printing dialog box, please use DoModal
DocInfo di; The following content on the Internet a lot, do not explain
di.cbsize = sizeof (DocInfo);
Di.lpszdocname = _t ("Drive print Test");
Di.lpszdatatype = NULL;
Di.lpszoutput = NULL;
Di.fwtype = 0;
dc. STARTDOCW (&DI);
dc. StartPage ();
dc. Setmapmode (Mm_text);
CRect recprint (0, 0, DC. GetDeviceCaps (LOGPIXELSX), DC. GetDeviceCaps (Logpixelsy));
dc. Dptolp (&recprint);
dc. setwindoworg (0, 0);
CFont Newfont;
VERIFY (Newfont.createpointfont, _t ("Song Body"), &DC);
cfont* Oldfont = DC. SelectObject (&newfont);
dc. SetTextAlign (Ta_top | Ta_left);
CString Strprint;
int nindex = 0;
int x = 50;
int y = 50;
CSize Textsize;
Textsize = DC. GetTextExtent (_t ("00"), 2); Based on the width and height of the current font, followed by this height as row height
while (nindex = Strmessage.find (_t ("\ r \ n")) >-1)//print the contents of the Idc_edit1 edit box, support the line break, a newline equals ' \ r \ n ', so at the beginning Strmes Sage + + _t ("\ r \ n")
{
Strprint = Strmessage.left (nindex);
strmessage = Strmessage.mid (nindex+2);
dc. TEXTOUTW (x, y, strprint);
Y + + textsize.cy; Move down one line, height to font
}
dc. SelectObject (Oldfont);
Newfont.deleteobject ();
dc. EndPage ();
dc. EndDoc ();
DeleteDC (DC. Detach ());
About Getprinterdevice, an article from Microsoft, point me to jump
The code is posted.
[CPP] View plaincopy The code slice to my Code slice
BOOL Cmfcapplication2dlg::getprinterdevice (LPTSTR pszprintername, hglobal* phdevnames, hglobal* phDevMode)
{
If NULL is passed, then assume we are setting app object ' s
DEVMODE and DevNames
if (Phdevmode = null | | phdevnames = NULL)
return FALSE;
Open Printer
HANDLE hprinter;
if (OpenPrinter (Pszprintername, &hprinter, NULL) = = FALSE)
return FALSE;
Obtain PRINTER_INFO_2 structure and close PRINTER
DWORD dwbytesreturned, dwbytesneeded;
GetPrinter (Hprinter, 2, NULL, 0, &dwbytesneeded);
printer_info_2* P2 = (printer_info_2*) GlobalAlloc (Gptr,
dwbytesneeded);
if (GetPrinter (Hprinter, 2, (LPBYTE) P2, dwbytesneeded,
&dwbytesreturned) = = 0) {
GlobalFree (p2);
ClosePrinter (hprinter);
return FALSE;
}
ClosePrinter (hprinter);
Allocate a global handle for DEVMODE
Hglobal Hdevmode = GlobalAlloc (ghnd, sizeof (*p2->pdevmode) +
P2->pdevmode->dmdriverextra);
ASSERT (Hdevmode);
devmode* pDevMode = (devmode*) globallock (Hdevmode);
ASSERT (pDevMode);
Copy DEVMODE data from printer_info_2::p DEVMODE
memcpy (pDevMode, P2->pdevmode, sizeof (*p2->pdevmode) +
P2->pdevmode->dmdriverextra);
GlobalUnlock (Hdevmode);
Compute size of DEVNAMES structure from printer_info_2 ' s data
DWORD Drvnamelen = lstrlen (p2->pdrivername) +1; Driver name
DWORD Ptrnamelen = lstrlen (p2->pprintername) +1; Printer Name
DWORD Pornamelen = lstrlen (p2->pportname) +1; Port Name
Allocate a global handle big enough to hold DEVNAMES.
Hglobal hdevnames = GlobalAlloc (GHND,
sizeof (DEVNAMES) +
(Drvnamelen + Ptrnamelen + pornamelen) *sizeof (TCHAR));
ASSERT (hDevNames);
devnames* pdevnames = (devnames*) globallock (hdevnames);
ASSERT (Pdevnames);
Copy the DEVNAMES information from Printer_info_2
Tcoffset = TCHAR Offset into structure
int tcoffset = sizeof (DEVNAMES)/sizeof (TCHAR);
ASSERT (sizeof (DEVNAMES) = = tcoffset*sizeof (TCHAR));
Pdevnames->wdriveroffset = Tcoffset;
memcpy ((LPTSTR) Pdevnames + Tcoffset, P2->pdrivername,
Drvnamelen*sizeof (TCHAR));
Tcoffset + = Drvnamelen;
Pdevnames->wdeviceoffset = Tcoffset;
memcpy ((LPTSTR) Pdevnames + Tcoffset, P2->pprintername,
Ptrnamelen*sizeof (TCHAR));
Tcoffset + = Ptrnamelen;
Pdevnames->woutputoffset = Tcoffset;
memcpy ((LPTSTR) Pdevnames + Tcoffset, P2->pportname,
Pornamelen*sizeof (TCHAR));
Pdevnames->wdefault = 0;
GlobalUnlock (hDevNames);
GlobalFree (p2); Free Printer_info_2
Set the new Hdevmode and hDevNames
*phdevmode = Hdevmode;
*phdevnames = hDevNames;
return TRUE;
}