第13章 使用打印机_13.2 打印图形和文字

13.2 打印图形和文字

(1)注册打印异常终止过程 SetAbortProc(hdcPrn,AbortProc);//在StartDoc前注册

(2)异常终止过程——取消打印

①调用时间:当调用EndPage之前,程序每次调用一个GDI函数时,GDI模块会把另一个记录追加到磁盘上的图元文件。当调用EndPage时(也就是把图元文件送设备驱动程序和创建临时打印文件时),GDI会频繁地调用异常终止过程。(如生成临时文件导致磁盘空间不足,会调用该过程,并传入iCode为SP_OUTOFDISK的参数)

②异常终止过程

BOOL CALLBACK AbortProc(HDC hdcPrn, int iCode)
{
   MSG msg;

   while(!bUserAbort && PeekMessage(&msg,NULL,0,0,PM_REMOVE))
   {
         if(!hDlgPrint || !IsDialogMessage(hDlgPrint,&msg))
         {
              TranslateMessage(&msg);//本例主窗口被Disable,收不到键盘和鼠标消息,该句可省略

              DispatchMessage(&msg);
         }
  }

  return !bUserAbort;
}

说明:

A、因本例开始打印时,会出现产生自定义的“取消对话框”(非模态的),为了在GDI模块将图元文件送给设备驱动程序时,用户能随时点击“取消”按钮终止打印,得在异常终止过程中用“消息循环”(因为这时程序己进入异常中止过程的处理,要在这个过程中能处理对话框的消息,这时就必须从消息队列中获取消息,并分配出去!),如果用户点击了“取消”,则会把全局变量bUserAbort设为TRUE,从而退出打印。

B、PeekMessage查看消息,可立即返回,而不用等待消息的出现。

C、异常处理过程中当返回TRUE时,继续打印,返回FALSE时终止打印。

D、为防止用户在打印作业开始以后,又选择主菜单中的“Print”菜单项,甚至选择退
 出程序,这种情况下程序的所有窗口都被销毁了,但当程序从异常中止过程中返回的时候,会
 找出现不到窗口错误。所以在打印作业开始前,要禁用掉主窗口(EnableWindow函数,参数为
  FALSE)。但主窗口仍可以收到WM_PAINT等消息。

③打印结束不必去除异常终止过程

【获取打印机设备环境——程序】

/*----------------------------------------------------------------------------------
GETPNTDC.C ——GetPrinterDC function
----------------------------------------------------------------------------------*/
//#pragma warning(disable: 4996)  //win8.1以上GetVersion己过时,加上这句关闭句
#include <windows.h>
#include <VersionHelpers.h>  //VS2013用来判断系统版本的头文件
HDC GetPrinterDC(void)
{
    DWORD  dwNeeded, dwReturned;
    HDC    hdc;
    PRINTER_INFO_4   *pinfo4;
    PRINTER_INFO_5   *pinfo5;

    if (!IsWindowsXPOrGreater())
        //  if (GetVersion() && 0x80000000)   //Windows98
    {
        EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, NULL, 0, &dwNeeded, &dwReturned); //获取所需缓冲区的字节数和所需结构体的数量
        pinfo5 = malloc(dwNeeded); //分配所需的字节数
        EnumPrinters(PRINTER_ENUM_DEFAULT, NULL, 5, (PBYTE)pinfo5, dwNeeded, &dwNeeded, &dwReturned);
        hdc = CreateDC(NULL, pinfo5->pPrinterName, NULL, NULL); //pinfo5为打1个打印机,pinfo5+1为第2个打印机
        free(pinfo5);
    } else
    {
        EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwNeeded, &dwReturned);
        pinfo4 = malloc(dwNeeded);
        EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, (PBYTE)pinfo4, dwNeeded, &dwNeeded, &dwReturned);
        hdc = CreateDC(NULL, pinfo4->pPrinterName, NULL, NULL);
        free(pinfo4);
    }
    return hdc;
}
//#pragma warning (default : 4996)

【打印程序框架】

/*------------------------------------------------------------
PRINT.C -- Common routines for Print1,Print2,and Print3
(c) Charles Petzold, 1998
------------------------------------------------------------*/
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL PrintMyPage(HWND);
extern HINSTANCE hInst;
extern TCHAR     szAppName[];
extern TCHAR     szCaption[];
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX     wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }
    hInst = hInstance;
    hwnd = CreateWindow(szAppName,                  // window class name
                        szCaption, // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
void PageGDICalls(HDC hdcPrn, int cxPage, int cyPage)
{
    static TCHAR szTextStr[] = TEXT("Hello Printer!");
    //画边框
    Rectangle(hdcPrn, 0, 0, cxPage, cyPage);
    //画对角线
    MoveToEx(hdcPrn, 0, 0, NULL);
    LineTo(hdcPrn, cxPage, cyPage);
    MoveToEx(hdcPrn, cxPage, 0, NULL);
    LineTo(hdcPrn, 0, cyPage);
    SaveDC(hdcPrn);
    SetMapMode(hdcPrn, MM_ISOTROPIC);//各向同性
    //将坐标系改为坐标系原点在客户区中心,y向上为正,x、y均为范围(-1000,1000)
    SetWindowExtEx(hdcPrn, 1000, 1000, NULL);
    SetViewportExtEx(hdcPrn, cxPage / 2, -cyPage / 2, NULL); //y轴向上为正
    SetViewportOrgEx(hdcPrn, cxPage / 2, cyPage / 2, NULL);

    //画圆(因为是各向同性的)
    Ellipse(hdcPrn, -500, 500, 500, -500);

    SetTextAlign(hdcPrn, TA_BASELINE | TA_CENTER); //对齐的基准点要对准基线
    TextOut(hdcPrn, 0, 0, szTextStr, lstrlen(szTextStr));
    RestoreDC(hdcPrn, -1);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC         hdc;
    PAINTSTRUCT ps;
    static int  cxClient, cyClient;
    HMENU       hMenu;
    switch (message)
    {
    case WM_CREATE:
        //在系统菜单中增加"Print"菜单项,菜单ID为1;
        hMenu = GetSystemMenu(hwnd, FALSE);
        AppendMenu(hMenu, MF_SEPARATOR, 0, NULL);
        AppendMenu(hMenu, 0, 1, TEXT("&Print"));  //菜单ID=1;
        return 0;
    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;
    case WM_SYSCOMMAND: //wParam为菜单ID
        if (wParam == 1)
        {
            if (!PrintMyPage(hwnd))
                MessageBox(hwnd, TEXT("Could not print page!"),
                szAppName, MB_OK | MB_ICONEXCLAMATION);
            return 0;
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        PageGDICalls(hdc, cxClient, cyClient);

        EndPaint(hwnd, &ps);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

【Print1程序】

/*------------------------------------------------------------------
PRINT1.C —— Bare Bones Printing
(c) Charles Petzold, 1998
-------------------------------------------------------------------*/
#include <windows.h>
HDC  GetPrinterDC(void);              // in GETPRNDC.C
void PageGDICalls(HDC, int, int);     // in PRINT.C
HINSTANCE hInst;
TCHAR  szAppName[] = TEXT("Print1");
TCHAR  szCaption[] = TEXT("Print Program 1");
BOOL PrintMyPage(HWND hwnd)
{
    static DOCINFO di = { sizeof(DOCINFO), TEXT("Print1:Printing"), TEXT("Print1.prn") };
    BOOL           bSuccess = TRUE;
    HDC            hdcPrn;
    int            xPage, yPage;
    if (NULL == (hdcPrn = GetPrinterDC()))
    {
        return FALSE;
    }
    xPage = GetDeviceCaps(hdcPrn, HORZRES); //水平像素规模
    yPage = GetDeviceCaps(hdcPrn, VERTRES); //垂直像素规模
    if (StartDoc(hdcPrn, &di)>0) //打印作业开始
    {
        if (StartPage(hdcPrn)>0)  //一页的开始
        {
            PageGDICalls(hdcPrn, xPage, yPage); //打印内容

            if (EndPage(hdcPrn) > 0) //一页的结束
                EndDoc(hdcPrn);      //作业完成
            else
                bSuccess = FALSE;

        }
    } else
        bSuccess = FALSE;

    DeleteDC(hdcPrn);
    return TRUE;
}

【Print2程序】

/*-------------------------------------------
PRINT2.C -- Printing with Abort Procedure
(c) Charles Petzold, 1998
-------------------------------------------*/
#include <windows.h>
HDC GetPrinterDC(void);             //in GETPRNDC.C
void PageGDICalls(HDC, int, int);   //in PRINT.C
HINSTANCE hInst;
TCHAR szAppName[] = TEXT("Print2");
TCHAR szCaption[] = TEXT("Print Program 2(Abort Procedure)");
BOOL CALLBACK AbortProc(HDC hdcPrn, int iCode)
{
    MSG msg;
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return TRUE;
}
BOOL PrintMyPage(HWND hwnd)
{
    static DOCINFO di = { sizeof(DOCINFO), TEXT("Print2:Printing") };
    HDC  hdcPrn;
    BOOL bSuccess = TRUE;
    short xPage, yPage;
    if (NULL == (hdcPrn = GetPrinterDC()))
    {
        return FALSE;
    }
    xPage = GetDeviceCaps(hdcPrn, HORZRES);
    yPage = GetDeviceCaps(hdcPrn, VERTRES);
    EnableWindow(hwnd, FALSE);
    SetAbortProc(hdcPrn, AbortProc);
    if (StartDoc(hdcPrn, &di) > 0)
    {
        if (StartPage(hdcPrn) > 0)
        {
            PageGDICalls(hdcPrn, xPage, yPage);
            if (EndPage(hdcPrn) > 0)
                EndDoc(hdcPrn);
            else
                bSuccess = FALSE;
        }
    } else
        bSuccess = FALSE;
    EnableWindow(hwnd, TRUE);
    DeleteDC(hdcPrn);
    return bSuccess;
}
时间: 2024-10-22 02:23:08

第13章 使用打印机_13.2 打印图形和文字的相关文章

第13章 使用打印机_13.1 打印基础

13.1 打印基础 13.1.1 打印和后台处理 说明: (1)此图的GDI模块的程序是16位的,打印驱动程序也是16位的. (2)spooler为windows提供的后台打印处理程序.可能用户有更好硬件或后台打印处理程序,那么可以去掉Windows自带的spooler,以加快打印速度,因为打印机输出可以不被存储在硬盘上,而是直接输出到打印机,或被硬件或软件后台打印处理程序截获. (3)如果不使用Windows后台打印处理程序,GDI模块不会把来自设备驱动的打印输出存在文件.而是直接传到打印机并

第 13 章 装饰模式【Decorator Pattern】

以下内容出自:<<24种设计模式介绍与6大设计原则>> Ladies and gentlemen,May I get your attention,Please?,Now I’m going to talk about decoratorpattern.装饰模式在中国使用的那实在是多,中国的文化是中庸文化,说话或做事情都不能太直接,需要有技巧的,比如说话吧,你要批评一个人,你不能一上来就说你这个做的不对,那个做的不对,你要先肯定他的成绩,表扬一下优点,然后再指出瑕疵,指出错误的地方

第13章 map映照容器

/* 第13章 map映照容器 13.1 map技术原理 13.2 map应用基础 13.3 本章小结 */ // 第13章 map映照容器 // 13.1 map技术原理 --------------------------------------------------------------------------------- // 13.2 map应用基础 -----------------------------------------------------------------

第13章 网络编程

1 /***************** 2 ***第13章 网络编程 3 *******知识点: 4 **************1.基本概念 5 ******************1.1 网络OSI模型 6 ******************1.2 IP地址 7 ******************1.3 端口地址 8 ******************1.4 通讯协议 9 **************2.Java网络相关类 10 ******************2.1 URLDe

《Python学习手册 第五版》 -第11章 赋值、表达式和打印

上一章对Python的语句和语法已经进行了基本的说明,接下来就是每个章节的详细说明,本章的主要内容就是标题中涵盖的三点:赋值语句.表达式语句.打印语句 本章重点内容如下: 1.赋值语句 1)赋值语句的特点(注意事项) 2)赋值语句的形式:基本形式.元组及列表解包赋值.序列赋值.扩展的序列解包.多目标赋值.增量赋值 3)变量命名规则 2.表达式语句 1)常见的表达式语句 2)表达式语句和原位置修改 3.打印操作 1)调用形式 2)应用示例 以下是针对以上重点内容的详细说明 1.赋值语句 1)赋值语

JavaScript权威指南第13章 web浏览器中的javascript

13.1 客户端javascript window对象是所有的客户端javascript特性和api的主要接入点.表示浏览器的一个窗口,可以通过window对象来引用它. window 的方法 alert() prompt() confirm() 13.2 在html里嵌入javascript 4种方法: 内联:放置在<script></script>标签之中 外部引入:<script src="   "></script> html程序

《深入Java虚拟机学习笔记》- 第13章 逻辑运算

<深入Java虚拟机学习笔记>- 第13章 浮点运算 <深入Java虚拟机学习笔记>- 第13章 逻辑运算,布布扣,bubuko.com

阅读《实例化需求》1-3章有感

今天我阅读了<实例化需求>的1-3章. 第一章主要是讲实例化需求的好处.实例化需求说明是一组过程模式,他帮助团队构建正确的产品. 使用实例化需求说明,团队编写的文档恰到好处,在短迭代或基于流的开发中可以有效地协助变更. <实例化需求>这本书不是以理论的方式来构建一个案例来阐述实例化需求说明的好处,而是来自 于那些来自于那些大大受益于实例化需求说明的团队. 实例化需求可以更有效地实施变更,主要是通过活文档.活文档是系统功能的一个信息源,与程序 代码一样可靠,但更容易使用和理解.他帮助

js高程笔记13章

第13章 事件 1.事件流:描述从页面中接收事件的顺序. 三个阶段:捕获,处于目标,冒泡. 2.事件处理程序:局部变量event表示事件对象,this值为事件目标元素. (1)HTML事件处理程序:可以访问特性.弊端:可能调用事件处理程序时,函数还未定义.同时代码紧密耦合,修改不便. (2)DOM0级事件处理程序:this引用当前元素.弊端:一个元素只能添加一个事件处理程序. (3)DOM2级事件处理程序:addEventListener()和removeEventListener().无法移除