印刷コモンダイアログ


VC++ でページ設定(PageSetupDlg) と印刷コモンダイアログ(PrintDlg) を使って印字します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. 新規プロジェクトを作成して、メニューを設定して下さい。
    キャプションID
    FILE(&F) 親メニュー
    Page Setup(&U) IDM_PAGESETUP
    Print...(&P) IDM_PRINT
    SEPARATOR SEPARATOR
    Exit(&X) IDM_EXIT
  2. psd はページ設定ダイアログの構造体です。
    hEdit は EditBox のハンドルです。
    lpszText は印字する文字列です。
        PAGESETUPDLG    psd;
        HWND            hEdit = NULL;
        LPCTSTR         lpszText = "This sample text\r\nwill be printed to the printer.";
        
  3. CALLBACK 関数の WM_CREATE: でページ設定ダイアログの構造体を初期設定します。
    top などの 1000 は、印刷用紙の余白の設定です。
    Edit Control を生成してウインドウに貼り付けて、lpszText を表示します。
            case WM_CREATE :
                psd.lStructSize     = sizeof(PAGESETUPDLG);
                psd.hwndOwner       = hWnd;
                psd.rtMargin.top    = 1000;
                psd.rtMargin.left   = 1000;
                psd.rtMargin.bottom = 1000;
                psd.rtMargin.right  = 1000;
                psd.hDevMode        = GlobalAlloc(GHND, sizeof(DEVMODE));
                psd.hDevNames       = GlobalAlloc(GHND, sizeof(DEVNAMES));
                psd.Flags           = PSD_MARGINS | PSD_INTHOUSANDTHSOFINCHES;
    
                hEdit = CreateWindow("EDIT", "",
                        WS_CHILD | ES_LEFT | WS_VISIBLE | ES_MULTILINE | ES_NOHIDESEL,
                        0, 0, 0, 0, hWnd, (HMENU)101, g_hInst, NULL);
                SendMessage( hEdit, WM_SETTEXT, 0, (LPARAM)lpszText );
                break;
        
  4. メニューから IDM_PAGESETUP: が呼ばれたときの処理です。
    ページ設定コモンダイアログの表示は PageSetupDlg() を実行するだけです。
            case IDM_PAGESETUP :
                PageSetupDlg( &psd );
                break;
        
  5. メニューから IDM_PRINT: が呼ばれたときの処理です。
    PRINTDLG 構造体を初期化して、PrintDlg() で印刷コモンダイアログを呼び出します。
    DOCINFO 構造体を初期化して、印刷情報を設定します。
    RECT 構造体に印刷する矩形をピクセル単位で設定します。
    prnw と prnh は印刷用紙の幅と高さ(ピクセル単位)です。
    Edit Control から印刷する TEXT を取得します。
    DrawText() で RECT 構造体を指定して TEXT を印字します。
    印字の説明は 印字をする を参照して下さい。
    リソースを解放して印字を終了します。
            case IDM_PRINT :
                {   PRINTDLG pd;
                    // PRINTDLG構造体を初期化する。
                    memset( &pd, 0, sizeof( PRINTDLG ) );
                    pd.lStructSize    = sizeof( PRINTDLG );
                    pd.hwndOwner      = hWnd;
                    pd.Flags          = PD_RETURNDC;
                    pd.hDevMode       = psd.hDevMode;
                    pd.hDevNames      = psd.hDevNames;
    
                    // [印刷]ダイアログを作成する。
                    if (PrintDlg(&pd))
                    {   WORD      wCopies;
                        char      szBuf[512];
                        RECT      rect;
                        DOCINFO   di;
    
                        // 文書のタイトルを指定するDOCINFO 構造体を初期化する。
                        memset( &di, 0, sizeof( DOCINFO ) );
                        di.cbSize      = sizeof( DOCINFO );
                        di.lpszDocName = lpszTitle;
    
                        // ページのサイズに対する矩形を初期化する。
                        int prnw= GetDeviceCaps(pd.hDC, HORZRES);
                        int prnh= GetDeviceCaps(pd.hDC, VERTRES);
                        rect.top =
                               ( GetDeviceCaps( pd.hDC, LOGPIXELSY )*
                               (psd.rtMargin.top/1000 ))-
                               GetDeviceCaps( pd.hDC, PHYSICALOFFSETY );
                        rect.left =
                               ( GetDeviceCaps( pd.hDC, LOGPIXELSX )*
                               (psd.rtMargin.left/1000 ))-
                               GetDeviceCaps( pd.hDC, PHYSICALOFFSETX );
                        rect.right =
                               prnw -
                               ( GetDeviceCaps( pd.hDC, LOGPIXELSX )*
                               (psd.rtMargin.right/1000 ))-
                               GetDeviceCaps( pd.hDC, PHYSICALOFFSETX );
                        rect.bottom =
                               prnh -
                               ( GetDeviceCaps( pd.hDC, LOGPIXELSY )*
                               (psd.rtMargin.bottom/1000 ))-
                               GetDeviceCaps( pd.hDC, PHYSICALOFFSETY );
    
                        // 編集コントロールからテキストを取得する。
                        SendMessage( hEdit, WM_GETTEXT, sizeof( szBuf ), (LPARAM)szBuf );
    
                        // テキストを印刷する。
                        if ( StartDoc( pd.hDC, &di ) > 0 )
                        {
                            for( wCopies = 0; wCopies < pd.nCopies; wCopies++ )
                            {
                                StartPage(pd.hDC);
                                DrawText(pd.hDC,szBuf,strlen(szBuf),&rect,DT_LEFT | DT_WORDBREAK);
                                EndPage(pd.hDC);
                            }
                            EndDoc( pd.hDC );
                        }
    
                        // リソースをロック解除し、解放する。
                        DeleteDC( pd.hDC );
                    }
                    else if ( CommDlgExtendedError() == PDERR_NODEFAULTPRN )
                         MessageBox( hWnd, "No default printer selected.",
                                           "Print", MB_OK | MB_ICONSTOP );
                }
                break;
        
  6. WM_SIZE: の処理です。
    ウインドウのサイズに合わせて Edit Control のサイズを設定します。
            case WM_SIZE :
                MoveWindow(hEdit,0,0,LOWORD(lParam),HIWORD(lParam),TRUE);
                break;
        
  7. WM_DESTROY: で割り当てた領域を開放して下さい。
            case WM_DESTROY:
                GlobalFree( psd.hDevMode );
                GlobalFree( psd.hDevNames );
                PostQuitMessage(0);
                return 0L;
        

【演習】

  1. プログラムを完成させて下さい。
  2. IDM_PAGESETUP で、上下左右の余白を設定して試してみて下さい。

超初心者の方のために全ソースコードを掲載します。 (^_^;)
全ソースコード

超初心者のプログラム入門(Win32API C++)