zoukankan      html  css  js  c++  java
  • 第13章 使用打印机_13.2 打印图形和文字

    第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;
    }

     【print3程序】

    /*-------------------------------------------
    PRINT3.C -- Printing with Dialog Box
    (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("Print3");
    TCHAR szCaption[] = TEXT("Print Program 3(Dialog Box)");
    BOOL bUserAbort;
    HWND hDlgPrint;
    BOOL CALLBACK PrintDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
        case WM_INITDIALOG:
            SetWindowText(hDlg, szAppName);
            EnableMenuItem(GetSystemMenu(hDlg, FALSE), SC_CLOSE, MF_GRAYED);
            return TRUE;
        case WM_COMMAND:
            bUserAbort = TRUE;
            EnableWindow(GetParent(hDlg), TRUE);
            DestroyWindow(hDlg);
            hDlgPrint = NULL;
            return TRUE;
        }
        return FALSE;
    }
    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);
                DispatchMessage(&msg);
            }
        }
        return !bUserAbort;
    }
    BOOL PrintMyPage(HWND hwnd)
    {
        static DOCINFO di = { sizeof(DOCINFO), TEXT("Print3:Printing"), TEXT("Print3.prn") };
        HDC  hdcPrn;
        BOOL bSuccess = TRUE;
        short xPage, yPage;
        if (NULL == (hdcPrn = GetPrinterDC()))
        {
            return FALSE;
        }
        xPage = GetDeviceCaps(hdcPrn, HORZRES);
        yPage = GetDeviceCaps(hdcPrn, VERTRES);
        bUserAbort = FALSE;
        hDlgPrint = CreateDialog(hInst, TEXT("PrintDlgBox"), hwnd, PrintDlgProc); //“取消”对话框(非模态)
    
        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;
        if (!bUserAbort)
        {
            EnableWindow(hwnd, TRUE);
            DestroyWindow(hDlgPrint);
        }
    
        DeleteDC(hdcPrn);
        return bSuccess && !bUserAbort;
    }

    13.3 增加打印功能的POPPAD程序

    (1)PRINTDLG结构体

    字段

    含义

    lStructSize

    结构大小(字节数)

    hwndOwner

    父窗口句柄(可为NULL)

    hDevMode

    包含打印机设备与环境信息的DEVMODE结构句柄。

    ①如果 hDevMode 不为 NULL ,则必须分配 DEVMODE 结构可移动的内存块,并初始化它的成员。 PrintDlg 函数使用输入数据以初始化对话框中的控件。 当PrintDlg 返回时, DEVMODE 的成员显示用户的输入。

    ②如果 hDevMode 输入为 NULL , PrintDlg 为 DEVMODE 结构分配内存,初始化它的成员。以指示用户的输入,并返回一个句柄,标识它。

    hDevNames

    包含驱动器名、打印机名和输出端口名的设备名结构DEVNAMES句柄。

    ①如果 hDevNames 不为 NULL ,你必须分配 DEVNAMES 结构可移动的内存块,并初始化它的成员。 PrintDlg 函数使用输入数据以初始化对话框中的控件。 当PrintDlg 返回时, DEVNAMES 成员包含由用户选择的打印机的信息。

     ②当 hDevNames 成员是 NULL ,在这种情况下, PrintDlg 为 DEVNAMES 结构分配内存,初始化它的成员。 以指示用户的输入,并返回一个句柄,标识它。

    ③可以使用此信息来创建一个设备上下文或信息上下文。

    hDC

    确定DC或IC(information context),由Flags是否设置PD_RETURNDC或PC_RETURNIC标志来决定。如果没有指定标志,这个成员的值是不确定的。如果指定了这两个标志, PD_RETURNDC 优先

    Flags

    初始化打印对话框。当对话框返回时,它将会设置这些标志,以指示用户的输入。

    PD_ALLPAGES  默认的标志,选“打印所有页单”的单选按钮。

    PD_PAGENUMS 和 PD_SELECTION:选中“页码”、“范围”单选按钮。

    PD_COLLATE:副本逐份打印 复选框在初始时被选中。

                逐份打印:如1、2、3,1、2、3

                非逐份打印:如1、1、2、2、3、3

    PD_RETURNDC:返回一个用户在对话框中选择的设备环境句柄。

    PD_NOSELECTION:禁止选择单选按钮

    nFromPage

    打印开始页码

    nToPage

    打印结束页码

    nMinPage

    开始/结束页码编辑控件的页码范围的最小值

    nMaxPage

    开始/结束页码编辑控件的页码范围的最大值

    nCopies

    打印的份数

    (2)获取编辑框中某行的文本

    SendMessage( hWnd, EM_GETLINE,(WPARAM) wParam,(LPARAM) lParam);

    ①wParam:为编辑框中的某行

    ②lParam:指向接收字符的缓冲区(pstrBuffer),其中发送消息时,要事先将pstrBuffer的第一个字设为要读取的字符个数。读出该行后,这个字位置会被返回的文字所覆盖。

    ③返回值为实际读取的字符数

    (3)AbortDoc函数很少用到(注意不是EndDoc)

    (4)多页打印时函数的调用顺序

    【PopPad4 程序】


     //PopPad4.c

    /*------------------------------------------------------------
    POPPAD4.C -- Popup Editor Version4
    (c) Charles Petzold, 1998
    ------------------------------------------------------------*/
    #include <windows.h>
    #include "resource.h"
    #include "CommFunc.h"
    #define ID_EDIT 1
    #define UNTITLED TEXT("(untitled)")
    static TCHAR szAppName[] = TEXT("PopPad4");
    static HWND hDlgModeless;
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                       PSTR szCmdLine, int iCmdShow)
    {
        HACCEL hAccel;
        HWND         hwnd;
        MSG          msg;
        WNDCLASS     wndclass;
        wndclass.style = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc = WndProc;
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(NULL, szAppName);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = szAppName;
        wndclass.lpszClassName = szAppName;
        if (!RegisterClass(&wndclass))
        {
            MessageBox(NULL, TEXT("This program requires Windows NT!"),
                       szAppName, MB_ICONERROR);
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                  // window class name
                            TEXT("edit4"), // 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);
    
        hAccel = LoadAccelerators(hInstance, szAppName);
        while (GetMessage(&msg, NULL, 0, 0))
        {
            if (hDlgModeless == NULL || !IsDialogMessage(hDlgModeless, &msg))
            {
                //处理键盘加速键
                if (!TranslateAccelerator(hwnd, hAccel, &msg))
                {
                    //非键盘加速键消息的处理
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }
            }
        }
        return msg.wParam;
    }
    void OkMessage(HWND hwnd, TCHAR* szMessage, TCHAR* szTitleName)
    {
        TCHAR szBuffer[64 + MAX_PATH];
        wsprintf(szBuffer, szMessage, szTitleName[0] ? szTitleName : UNTITLED);
        MessageBox(hwnd, szBuffer, szAppName, MB_OK | MB_ICONEXCLAMATION);
    }
    int AskConfirmation(HWND hwnd)
    {
        return MessageBox(hwnd, TEXT("Really Want to close PopPad3?"),
                          szAppName, MB_YESNO | MB_ICONQUESTION);
    }
    short AskAboutSave(HWND hwnd, TCHAR* szTitleName)
    {
        TCHAR szBuffer[64 + MAX_PATH];
        int iRet;
        wsprintf(szBuffer, TEXT("Save current changes in %s?"), szTitleName[0] ? szTitleName : UNTITLED);
        iRet = MessageBox(hwnd, szBuffer, szAppName, MB_YESNOCANCEL | MB_ICONQUESTION);
        if (iRet == IDYES)
        {
            if (!SendMessage(hwnd, WM_COMMAND, IDM_FILE_SAVE, 0))  //IDM_FILE_SAVE返回0为失败,1成功
                iRet = IDCANCEL;
        }
        return  iRet;
    }
    //设置标题
    void DoCaption(HWND hwnd, TCHAR* szTitleName)
    {
        TCHAR szCaption[64 + MAX_PATH];
        wsprintf(szCaption, TEXT("%s - %s"), szAppName,
                 szTitleName[0] ? szTitleName : UNTITLED);
        SetWindowText(hwnd, szCaption);
    }
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static HWND hwndEdit;
        int iSelect, iEnable;
        static int iOffset;
        static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
        static bNeedSave = FALSE;
        static UINT messageFindReplace;
        LPFINDREPLACE pfr;
        static HINSTANCE     hInst;
        switch (message)
        {
        case WM_CREATE:
            hInst = ((LPCREATESTRUCT)lParam)->hInstance;
            hwndEdit = CreateWindow(TEXT("edit"), NULL,
                                    WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL |
                                    WS_BORDER | ES_LEFT | ES_MULTILINE | ES_NOHIDESEL |  //ES_NOHIDESEL,编辑框在没有输入焦点时被选择的文字仍然被加亮
                                    ES_AUTOHSCROLL | ES_AUTOVSCROLL,
                                    0, 0, 0, 0, hwnd, (HMENU)ID_EDIT,
                                    hInst, NULL);
            //限制编辑框的文本最大长度
            SendMessage(hwndEdit, EM_LIMITTEXT, 32000, 0L);
            PopFileInitialize(hwnd);
            PopFontInitialize(hwndEdit);
            messageFindReplace = RegisterWindowMessage(FINDMSGSTRING); //申请获取“查找”、“替换”发出的特殊消息的ID
            DoCaption(hwnd, szTitleName);
            return 0;
        case WM_SETFOCUS:
            SetFocus(hwndEdit);
            return 0;
        case WM_INITMENUPOPUP: //lParam:item position and indicator
            switch (lParam)
            {
            case 1:
                //Undo菜单项
                EnableMenuItem((HMENU)wParam, IDM_EDIT_UNDO,
                               SendMessage(hwndEdit, EM_CANUNDO, 0, 0) ? MF_ENABLED : MF_GRAYED);
                //Paste菜单项
                EnableMenuItem((HMENU)wParam, IDM_EDIT_PASTE,
                               IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED);
                iSelect = SendMessage(hwndEdit, EM_GETSEL, 0, 0);
                if (HIWORD(iSelect) == LOWORD(iSelect))
                    iEnable = MF_GRAYED;
                else
                    iEnable = MF_ENABLED;
                EnableMenuItem((HMENU)wParam, IDM_EDIT_CUT, iEnable);
                EnableMenuItem((HMENU)wParam, IDM_EDIT_COPY, iEnable);
                EnableMenuItem((HMENU)wParam, IDM_EDIT_CLEAR, iEnable);
                break;
            case 2:  //“查找”菜单项
                //如果非模态对话框==NULL时,激活菜单
                iEnable = hDlgModeless == NULL ? MF_ENABLED : MF_GRAYED;
                EnableMenuItem((HMENU)wParam, IDM_SEARCH_FIND, iEnable);
                EnableMenuItem((HMENU)wParam, IDM_SEARCH_NEXT, iEnable);
                EnableMenuItem((HMENU)wParam, IDM_SEARCH_REPLACE, iEnable);
                break;
            }
            return 0;
        case WM_COMMAND:
            if (lParam && LOWORD(wParam == ID_EDIT))  //控件消息
            {
                switch (HIWORD(wParam)) //控件通知码
                {
                case EN_UPDATE:
                    bNeedSave = TRUE;
                    return 0;
                case EN_ERRSPACE:
                case EN_MAXTEXT:
                    MessageBox(hwnd, TEXT("Edit Control out of space."),
                               szAppName, MB_OK | MB_ICONSTOP);
                    return 0;
                }
                break;
            };
            switch (LOWORD(wParam))//加速键ID或菜单ID,这里两个ID相等
            {
                //菜单消息
            case IDM_FILE_NEW:
                //保存旧文件,如果保存时失败,则什么都不做,直接返回。
                if (bNeedSave&& IDCANCEL == AskAboutSave(hwnd, szTitleName))
                    return 0;
                SetWindowText(hwndEdit, TEXT("")); //清除编辑框内容
                szFileName[0] = '';
                szTitleName[0] = '';
                DoCaption(hwnd, szTitleName);
                bNeedSave = FALSE;
                return 0;
            case IDM_FILE_OPEN:
                //保存旧文件,如果保存时失败,则什么都不做,直接返回。
                if (bNeedSave && IDCANCEL == AskAboutSave(hwnd, szTitleName))
                    return 0;
                if (PopFileOpenDlg(hwnd, szFileName, szTitleName))
                {
                    if (!PopFileRead(hwndEdit, szFileName))
                    {
                        OkMessage(hwnd, TEXT("Could not read file %s!"), szTitleName);
                        szFileName[0] = '';
                        szTitleName[0] = '';
                    }
                }
                DoCaption(hwnd, szTitleName);
                bNeedSave = FALSE;
                return 0;
            case IDM_FILE_SAVE:
                if (szFileName[0])
                {
                    if (PopFileWrite(hwndEdit, szFileName))
                    {
                        bNeedSave = FALSE;
                        return 1;
                    } else
                    {
                        OkMessage(hwnd, TEXT("Could not write file %s"), szTitleName);
                        return 0;
                    }
                }
                //如果是UNTITLE,则弹出保存对话框
            case IDM_FILE_SAVE_AS:
                if (PopFileSaveDlg(hwnd, szFileName, szTitleName))
                {
                    DoCaption(hwnd, szTitleName);
                    if (PopFileWrite(hwndEdit, szTitleName))
                    {
                        bNeedSave = FALSE;
                        return 1;
                    } else
                    {
                        OkMessage(hwnd, TEXT("Could not write file %s"), szTitleName);
                        return 0;
                    }
                }
                return 0;
            case IDM_FILE_PRINT:
                if (!PopPrntPrintFile(hInst, hwnd, hwndEdit, szTitleName))
                    OkMessage(hwnd, TEXT("Could not print file %s"), szTitleName);
                MessageBeep(0);
                return 0;
            case IDM_FORMAT_FONT:
                if (PopFontChooseFont(hwnd))
                {
                    PopFontSetFont(hwndEdit);
                }
                return 0;
            case IDM_SEARCH_FIND:
                //将查找将从iOffset位置开始(首获取选中文本后面的位置iOffset)
                SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);
                hDlgModeless = PopFindFindDlg(hwnd);
                return 0;
            case IDM_SEARCH_NEXT:
                //查找将从iOffset位置开始(首获取选中文本后面的位置iOffset)
                SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);
                if (PopFindValidFind())
                    PopFindNextText(hwndEdit, &iOffset);
                else
                    hDlgModeless = PopFindFindDlg(hwnd);
                return 0;
            case IDM_SEARCH_REPLACE:
                //查找将从iOffset位置开始(首获取选中文本后面的位置iOffset)
                SendMessage(hwndEdit, EM_GETSEL, 0, (LPARAM)&iOffset);
                hDlgModeless = PopFindReplaceDlg(hwnd);
                return 0;
            case IDM_APP_EXIT:
                SendMessage(hwnd, WM_CLOSE, 0, 0);
                return 0;
            case IDM_EDIT_UNDO:
                SendMessage(hwndEdit, WM_UNDO, 0, 0);
                return 0;
            case IDM_EDIT_CUT:
                SendMessage(hwndEdit, WM_CUT, 0, 0);
                return 0;
            case IDM_EDIT_COPY:
                SendMessage(hwndEdit, WM_COPY, 0, 0);
                return 0;
            case IDM_EDIT_PASTE:
                SendMessage(hwndEdit, WM_PASTE, 0, 0);
                return 0;
            case IDM_EDIT_CLEAR:
                SendMessage(hwndEdit, WM_CLEAR, 0, 0);
                return 0;
            case IDM_EDIT_SELECT_ALL:
                SendMessage(hwndEdit, EM_SETSEL, 0, -1);
                return 0;
            case IDM_HELP_HELP:
                MessageBox(hwnd, TEXT("Help not yet implement!"),
                           szAppName, MB_OK | MB_ICONEXCLAMATION);
                return 0;
            case IDM_APP_ABOUT:
                MessageBox(hwnd, TEXT("POPPAD3(c) Charles Petzold 1998!"),
                           szAppName, MB_OK | MB_ICONINFORMATION);
                return 0;
            }
            break;
        case WM_SIZE:
            MoveWindow(hwndEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
            return 0;
        case WM_CLOSE: //选择窗口关闭按钮时收到该消息
            if (!bNeedSave || IDCANCEL != AskAboutSave(hwnd, szTitleName))
                DestroyWindow(hwnd);
            return 0;
        case WM_QUERYENDSESSION: //系统关机或注销时收到该消息
            if (!bNeedSave || IDCANCEL != AskAboutSave(hwnd, szTitleName))
                return 1;
            return 0;
        case WM_DESTROY:
            PopFontDeinitialize();
            PostQuitMessage(0);
            return 0;
        default:
            //处理“查找”、“替换”发送的特殊消息
            if (message == messageFindReplace)
            {
                pfr = (LPFINDREPLACE)lParam;
                //用户点击了“取消”按钮
                if (pfr->Flags & FR_DIALOGTERM)
                    hDlgModeless = NULL;
                //用户点击了“查找下一个”按钮
                if (pfr->Flags& FR_FINDNEXT)
                {
                    if (!PopFindFindText(hwndEdit, &iOffset, pfr))
                        OkMessage(hwnd, TEXT("Text not Find!"), TEXT(""));
                }
    
                //用户点击了“替换全部”
                if (pfr->Flags & FR_REPLACEALL)
                    while (PopFindReplaceText(hwndEdit, &iOffset, pfr));
                return 0;
            }
            break;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

     //PopPrnt.c

    #pragma once
    #include "CommFunc.h"
    #include <windows.h>
    #include "resource.h"
    BOOL bUserAbort;
    HWND hDlgPrint;
    BOOL CALLBACK PrintDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch (msg)
        {
        case WM_INITDIALOG:
            // 使系统菜单中的“退出项”不可选
            EnableMenuItem(GetSystemMenu(hDlg, FALSE), SC_CLOSE, MF_GRAYED);
            return TRUE;
        case WM_COMMAND:
            bUserAbort = TRUE;
            //使对话框父窗口为有效,接受键盘鼠标输入
            EnableWindow(GetParent(hDlg), TRUE);
            DestroyWindow(hDlg);
            hDlgPrint = NULL;
            return TRUE;
        }
        return FALSE;
    }
    BOOL CALLBACK AbortProc(HDC hPrinterDC, int iCode)
    {
        MSG msg;
        // 如果用户点击“取消打印”则会退出消息检查循环 ,并返回 FALSE 
        // PM_REMOVE 表示 PeekMessage 处理后,消息从队列里除掉
        while (!bUserAbort && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (!hDlgPrint || !IsDialogMessage(hDlgPrint, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
        return !bUserAbort;
    }
    BOOL PopPrntPrintFile(HINSTANCE hInst, HWND hwnd, HWND hwndEdit, PTSTR szTitleName)
    {
        static DOCINFO di = { sizeof(DOCINFO) };
        static PRINTDLG pd;
        TEXTMETRIC tm;
        PTSTR  pstrBuffer;
        TCHAR  szJobName[64 + MAX_PATH];
        BOOL bSuccess = TRUE;
        int yChar, iCharsPerLine, iLinesPerPage, iTotalLines, iTotalPages;
    
        WORD iColCopy, iNoiColCopy;
        int iLine, iLineNum, iLineChars;
        //调用打话通用对话框
        pd.lStructSize = sizeof(PRINTDLG);
        pd.hwndOwner = hwnd;
        pd.hDevMode = NULL;
        pd.hDevNames = NULL;
        pd.hDC = NULL;
        pd.Flags = PD_ALLPAGES | PD_COLLATE | PD_RETURNDC | PD_NOSELECTION;
        pd.nFromPage = 0;
        pd.nToPage = 0;
        pd.nMaxPage = 0;
        pd.nMinPage = 0;
        pd.nCopies = 1;
        pd.hInstance = NULL;
        pd.lCustData = 0L;
        pd.lpfnPrintHook = NULL;
        pd.lpfnSetupHook = NULL;
        pd.lpPrintTemplateName = NULL;
        pd.lpSetupTemplateName = NULL;
        pd.hPrintTemplate = NULL;
        pd.hSetupTemplate = NULL;
        if (!PrintDlg(&pd))
            return TRUE;
        //获取文本总行数
        iTotalLines = SendMessage(hwndEdit, EM_GETLINECOUNT, 0, 0);
        if (0 == iTotalLines)
            return TRUE;
        //计算文件所需的各种度量
        GetTextMetrics(pd.hDC, &tm);
        yChar = tm.tmHeight + tm.tmExternalLeading;
        iCharsPerLine = GetDeviceCaps(pd.hDC, HORZRES) / tm.tmAveCharWidth;
        iLinesPerPage = GetDeviceCaps(pd.hDC, VERTRES) / yChar;
        /*
        因为隐式转换的问题:如取整3.14 =3,但我们要的是向上取整,即取4,
        所以(iTotalLines +iLinesPerpage)/iLinesPerPage,可以向上取值。
        又因为如果iTotalLines=iLinesPerPage时,即总行数刚好一页时,此时
        只须一页,但根据上式取整后得到的是2页,为了防止这种情况出现。分子-1,
        即iTotalLines + iLinesPerPage - 1。
        */
        iTotalPages = (iTotalLines + iLinesPerPage - 1) / iLinesPerPage;
        //分配一个可以容纳一行文本的内存(含)
        pstrBuffer = malloc(sizeof(TCHAR)*(iCharsPerLine + 1));
        //显示取消对话框——非模态
        EnableWindow(hwnd, FALSE);  //使主窗口不能接受键盘和鼠标消息
        bUserAbort = FALSE;
        hDlgPrint = CreateDialog(hInst, TEXT("PrintDlgBox"), hwnd, PrintDlgProc);
    
        SetDlgItemText(hDlgPrint, IDC_FILENAME, szTitleName);
        SetAbortProc(pd.hDC, AbortProc);
        //开始打印作业
        GetWindowText(hwnd, szJobName, sizeof(szJobName));
        di.lpszDocName = szJobName;//在打印作业队列中显示的名称
        if (StartDoc(pd.hDC, &di) > 0)
        {
            //逐份打印时, 则循环打印实际设置的份数, 
            //否则循环一次, 内层循环中先将当前页打印出需要的份数。
            for (iColCopy = 0; iColCopy < (WORD)(pd.Flags & PD_COLLATE ? pd.nCopies : 1); iColCopy++)
            {
                //从第1页,打印到最后一项
                for (int iPage = 0; iPage < iTotalPages; iPage++)
                {
                    //如果是逐份打印,则打印当前页1份,否则打印实际设置的份数。
                    for (iNoiColCopy = 0;
                         iNoiColCopy < (pd.Flags&PD_COLLATE ? 1 : pd.nCopies);
                         iNoiColCopy++)
                    {
                        //新一页打印开始
                        if (StartPage(pd.hDC)<0)
                        {
                            bSuccess = FALSE;
                            break;
                        }
                        //打印每一行,iLinesPerPage为每页的行数
                        for (iLine = 0; iLine < iLinesPerPage; iLine++)
                        {
                            //计算当前应该是编辑控件中的第几行
                            iLineNum = iLinesPerPage*iPage + iLine;
    
                            //如果超过了编辑控件中的文字行数,则跳出
                            if (iLineNum>iTotalLines) break;
                            //将每行的字符个数存到pstrBuffer的第一个字中。这是EM_GETLINE的要求,要求在
                            //SendMessage中指定要读取的行数(wParam),和该行要读取的字符数(存于lParam所指
                            //向的缓冲区的第一个字中)。
                            *(int*)pstrBuffer = iCharsPerLine;
                            //读取控件第iLineNum的文字
                            iLineChars = (int)SendMessage(hwndEdit, EM_GETLINE, (WPARAM)iLineNum, (LPARAM)pstrBuffer);
                            TextOut(pd.hDC, 0, yChar*iLine, pstrBuffer, iLineChars);
                        }
                        //结束当前的一页,如果用户“取消”打印 ,则 EndPage 不会传回错误。 
                        //由于这个原因,在下一页开始之前,要直接测试 bUserAbort .
                        if (EndPage(pd.hDC)<0)
                        {
                            bSuccess = FALSE;
                            break;
                        }
                        //如果用户点击取消,跳出循环
                        if (bUserAbort)
                            break;
                    }
                    //用户取消或打印出错,跳出
                    if (!bSuccess || bUserAbort)
                        break;
                }
                //用户取消或打印出错,跳出
                if (!bSuccess || bUserAbort)
                    break;
            }
        } else
            bSuccess = FALSE;
    
        //如果一切正常,则结束打印
        if (bSuccess)
        {
            EndDoc(pd.hDC);
        }
    
        //如果用户没有取消,至此,打印完全正确
        if (!bUserAbort)
        {
            EnableWindow(hwnd, TRUE);
            DestroyWindow(hDlgPrint);
        }
        free(pstrBuffer);
        DeleteDC(pd.hDC); //删除打开的打印机设备句柄
        return bSuccess && !bUserAbort;
    }

    //resource.h

    //{{NO_DEPENDENCIES}}
    // Microsoft Visual C++ 生成的包含文件。
    // 供 PopPad.rc 使用
    //
    #define IDC_FILENAME                    1000
    #define IDM_FILE_NEW                    40001
    #define IDM_FILE_OPEN                   40002
    #define IDM_FILE_SAVE                   40003
    #define IDM_FILE_SAVE_AS                40004
    #define IDM_FILE_PRINT                  40005
    #define IDM_APP_EXIT                    40006
    #define IDM_EDIT_UNDO                   40007
    #define IDM_EDIT_CUT                    40008
    #define IDM_EDIT_COPY                   40009
    #define IDM_EDIT_PASTE                  40010
    #define IDM_EDIT_CLEAR                  40011
    #define IDM_EDIT_SELECT_ALL             40012
    #define IDM_HELP_HELP                   40013
    #define IDM_APP_ABOUT                   40014
    #define IDM_SEARCH_FIND                 40015
    #define IDM_SEARCH_NEXT                 40016
    #define IDM_SEARCH_REPLACE              40017
    #define IDM_FORMAT_FONT                 40018
    // Next default values for new objects
    // 
    #ifdef APSTUDIO_INVOKED
    #ifndef APSTUDIO_READONLY_SYMBOLS
    #define _APS_NEXT_RESOURCE_VALUE        106
    #define _APS_NEXT_COMMAND_VALUE         40051
    #define _APS_NEXT_CONTROL_VALUE         1001
    #define _APS_NEXT_SYMED_VALUE           101
    #endif
    #endif

    //PopPad4.rc

    // Microsoft Visual C++ generated resource script.
    //
    #include "resource.h"
    #define APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 2 resource.
    //
    #include "winres.h"
    /////////////////////////////////////////////////////////////////////////////
    #undef APSTUDIO_READONLY_SYMBOLS
    /////////////////////////////////////////////////////////////////////////////
    // 中文(简体,中国) resources
    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
    LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
    #ifdef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // TEXTINCLUDE
    //
    1 TEXTINCLUDE
    BEGIN
    "resource.h"
    END
    2 TEXTINCLUDE
    BEGIN
    "#include ""winres.h""
    "
    ""
    END
    3 TEXTINCLUDE
    BEGIN
    "
    "
    ""
    END
    #endif    // APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Menu
    //
    POPPAD4 MENU
    BEGIN
    POPUP "&File"
    BEGIN
    MENUITEM "&New", IDM_FILE_NEW
    MENUITEM "&Open", IDM_FILE_OPEN
    MENUITEM "&Save", IDM_FILE_SAVE
    MENUITEM "Save &As...", IDM_FILE_SAVE_AS
    MENUITEM SEPARATOR
    MENUITEM "&Print", IDM_FILE_PRINT
    MENUITEM SEPARATOR
    MENUITEM "E&xit", IDM_APP_EXIT
    END
    POPUP "&Edit"
    BEGIN
    MENUITEM "&Undo	Ctrl+Z", IDM_EDIT_UNDO
    MENUITEM SEPARATOR
    MENUITEM "Cu&t	Ctrl+X", IDM_EDIT_CUT
    MENUITEM "&Copy	Ctrl+C", IDM_EDIT_COPY
    MENUITEM "&Paste	Ctrl+V", IDM_EDIT_PASTE
    MENUITEM "De&lete	Del", IDM_EDIT_CLEAR
    MENUITEM SEPARATOR
    MENUITEM "&Select All", IDM_EDIT_SELECT_ALL
    END
    POPUP "&Search"
    BEGIN
    MENUITEM "&Find...	Ctrl+F", IDM_SEARCH_FIND
    MENUITEM "Find &Next	F3", IDM_SEARCH_NEXT
    MENUITEM "&Replace...	Ctrl+R", IDM_SEARCH_REPLACE
    END
    POPUP "F&ormat"
    BEGIN
    MENUITEM "&Font...", IDM_FORMAT_FONT
    END
    POPUP "&Help"
    BEGIN
    MENUITEM "&Help...", IDM_HELP_HELP
    MENUITEM "&About PopPad...", IDM_APP_ABOUT
    END
    END
    /////////////////////////////////////////////////////////////////////////////
    //
    // Icon
    //
    // Icon with lowest ID value placed first to ensure application icon
    // remains consistent on all systems.
    POPPAD                  ICON                    "POPPAD.ICO"
    /////////////////////////////////////////////////////////////////////////////
    //
    // Accelerator
    //
    POPPAD ACCELERATORS
    BEGIN
    VK_DELETE, IDM_EDIT_CLEAR, VIRTKEY, NOINVERT
    VK_INSERT, IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
    VK_DELETE, IDM_EDIT_CUT, VIRTKEY, SHIFT, NOINVERT
    VK_INSERT, IDM_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
    VK_BACK, IDM_EDIT_UNDO, VIRTKEY, ALT, NOINVERT
    VK_F1, IDM_HELP_HELP, VIRTKEY, NOINVERT
    "^C", IDM_EDIT_COPY, ASCII, NOINVERT
    "^V", IDM_EDIT_PASTE, ASCII, NOINVERT
    "^X", IDM_EDIT_CUT, ASCII, NOINVERT
    "^Z", IDM_EDIT_UNDO, ASCII, NOINVERT
    END
    /////////////////////////////////////////////////////////////////////////////
    //
    // Dialog
    //
    PRINTDLGBOX DIALOGEX 0, 0, 161, 107
    STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
    CAPTION "PopPad"
    FONT 8, "MS Shell Dlg", 400, 0, 0x1
    BEGIN
    PUSHBUTTON      "Cancel", IDCANCEL, 54, 81, 50, 14
    CTEXT           "Sending", IDC_STATIC, 63, 12, 26, 8
    CTEXT           "", IDC_FILENAME, 11, 33, 139, 8
    CTEXT           "to print spooler.", IDC_STATIC, 54, 57, 52, 8
    END
    /////////////////////////////////////////////////////////////////////////////
    //
    // DESIGNINFO
    //
    #ifdef APSTUDIO_INVOKED
    GUIDELINES DESIGNINFO
    BEGIN
    "PRINTDLGBOX", DIALOG
    BEGIN
    LEFTMARGIN, 7
    RIGHTMARGIN, 154
    TOPMARGIN, 7
    BOTTOMMARGIN, 100
    END
    END
    #endif    // APSTUDIO_INVOKED
    #endif    // 中文(简体,中国) resources
    /////////////////////////////////////////////////////////////////////////////
    #ifndef APSTUDIO_INVOKED
    /////////////////////////////////////////////////////////////////////////////
    //
    // Generated from the TEXTINCLUDE 3 resource.
    //
    /////////////////////////////////////////////////////////////////////////////
    #endif    // not APSTUDIO_INVOKED

    //CommFunc.h

    #pragma once
    #include<windows.h>
    //Function in POPFILE.C
    void PopFileInitialize(HWND);
    BOOL PopFileOpenDlg(HWND, PTSTR, PTSTR);
    BOOL PopFileSaveDlg(HWND, PTSTR, PTSTR);
    BOOL PopFileRead(HWND, PTSTR);
    BOOL PopFileWrite(HWND, PTSTR);
    //Function in POPFIND.C
    HWND PopFindFindDlg(HWND);
    HWND PopFindReplaceDlg(HWND);
    BOOL PopFindFindText(HWND, int*, LPFINDREPLACE);
    BOOL PopFindNextText(HWND, int*);
    BOOL PopFindReplaceText(HWND, int*, LPFINDREPLACE);
    BOOL PopFindValidFind(void);
    //Functions in POPFONT.C
    void PopFontInitialize(HWND);
    BOOL PopFontChooseFont(HWND);
    void PopFontSetFont(HWND);
    void PopFontDeinitialize(void);
    //Functions in POPPRINT.C
    BOOL PopPrntPrintFile(HINSTANCE, HWND, HWND, PTSTR);

    //PopFile.C、PopFind.C、PopFont.C等文件见第11章 PopPad3程序

  • 相关阅读:
    Python爬虫一
    Python爬虫二
    DRF框架中的演变View
    计算时间复杂度例题
    vue2.x webpack打包资源路径问题
    vs code运行c语言 控制台乱码 问题
    解决视频的声音和画面不同步问题
    c语言数据结构,静态链表,结构体数组
    swagger @ApiModel添加实体类不生效
    计算及校验海明码的3个举例
  • 原文地址:https://www.cnblogs.com/5iedu/p/4695175.html
Copyright © 2011-2022 走看看