MFC對話方塊使用CPrintDialog實現列印,指定印表機、後台列印

來源:互聯網
上載者:User

http://blog.csdn.net/xuqiang918/article/details/39962341

http://blog.csdn.net/xjkstar/article/details/25828097 推薦下 不錯。
對話方塊列印,網上一搜一大堆,基本分2類:
A類: CPrintDialog.DoModal,然後在模態對話方塊裡選印表機、列印配置;
B類:GetPrinterDeviceDefaults,調用預設印表機。
我的工作內容是理解以上2類後,再根據MSDN,實現MDF對話方塊後台指定印表機列印。
廢話不多說,上菜~


功能:基於對話方塊的MFC列印(非文檔視圖結構),指定印表機,後台列印(不彈出對話方塊)


思路:
1、枚舉印表機,並選擇其中一個;
2、CPrintDialog執行個體指定到選中的印表機;
3、CPrintDialog後台列印


具體實現:
1、變數(控制項)。在對話方塊上添加一個combobox(IDC_COMBO1,對應變數m_cboPrint)、一個edit(IDC_EDIT1),edit允許斷行符號,多行(代碼就不貼了,知道MFC應該就懂);
2、在OnInitDialog裡枚舉印表機裝置,如果報函數未定義,加入標頭檔#include <winspool.h>
需要調用兩次EnumPrinters函數,第一次的到結構體的大小,第二次得到印表機列表
[cpp] view plaincopy在CODE上查看代碼片派生到My Code片 
// TODO: 在此添加額外的初始化代碼  
    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、操作對話方塊,在IDC_EDIT1裡輸入列印的內容,在IDC_COMBO1裡選中印表機;
4、列印(我是用OK按鈕列印的,大家隨便)
[cpp] view plaincopy在CODE上查看代碼片派生到My Code片 
// TODO: 在此添加控制項通知處理常式代碼  
//  CDialogEx::OnOK();  
    this->UpdateData();  
  
    CString strMessage;  
    CString strPrintDevice;  
  
    this->GetDlgItem(IDC_EDIT1)->GetWindowTextW(strMessage);  
    strMessage += _T("\r\n");       //添加結尾,方便後面迴圈讀取列印資料  
  
    this->GetDlgItem(IDC_COMBO1)->GetWindowTextW(strPrintDevice);  
  
    DWORD dwFlag = PD_ALLPAGES | PD_NOPAGENUMS | PD_USEDEVMODECOPIES | PD_HIDEPRINTTOFILE;  //列印配置介面的按鈕可用性,因為後台列印,其實這個配置沒什麼意義  
  
    CPrintDialog pPrintdlg(FALSE, dwFlag, this);                                            //CPrintDialog執行個體化,因為MFC的列印裝置無關性,可以理解為這就是一台印表機  
  
    HGLOBAL hDevMode = NULL;  
    HGLOBAL hDevNames = NULL;  
    if (GetPrinterDevice(strPrintDevice.GetBuffer(0), &hDevNames, &hDevMode))               //獲得指定印表機的配置、名字  
        AfxGetApp()->SelectPrinter(hDevNames, hDevMode);  
    else  
        AfxMessageBox(_T("Failed to select custom printer"));  
  
    strPrintDevice.ReleaseBuffer();  
  
    pPrintdlg.m_pd.hDevMode = hDevMode;                                                     //讓pPrintdlg使用我們指定的印表機  
    pPrintdlg.m_pd.hDevNames = hDevNames;  
  
    CDC dc;  
    dc.Attach(pPrintdlg.CreatePrinterDC());                                                 //後台列印建立法,如果需要彈出列印對話方塊,請用DoModal  
  
    DOCINFO di;                                                                             //下面的內容網上很多,就不解釋了  
    di.cbSize = sizeof(DOCINFO);  
    di.lpszDocName = _T("有驅列印測試");  
    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(120, _T("宋體"), &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);                           //根據當前字型的寬、高,後面以此高度為行高  
  
    while ((nIndex = strMessage.Find(_T("\r\n"))) > -1)                  //將IDC_EDIT1編輯框中內容列印,支援換行,一次換行等於'\r\n',所以在開頭strMessage += _T("\r\n")  
    {  
        strPrint = strMessage.Left(nIndex);  
        strMessage = strMessage.Mid(nIndex+2);  
  
        dc.TextOutW(x, y, strPrint);  
  
        y += textSize.cy;                                               //下移一行,行高為字型高度  
    }  
  
    dc.SelectObject(oldFont);  
    newFont.DeleteObject();  
    dc.EndPage();  
    dc.EndDoc();  
    DeleteDC(dc.Detach());  


關於GetPrinterDevice,來自微軟的一篇文章,點我跳轉
代碼也貼出來
[cpp] view plaincopy在CODE上查看代碼片派生到My Code片 
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::pDevMode  
    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;  
}  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.