概要

Visual C++ 2005 Express に対応。
PrintDlg APIはWindows 98等にも対応。

実行結果

表示されるダイアログ

印刷結果

ソース

printdlg.cpp

#include <windows.h>
#include <TCHAR.H>
#include "resource.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);

TCHAR szClassName[] = TEXT("PrintDlg");    //ウィンドウクラス
HINSTANCE hInst;

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst,
                   LPSTR lpsCmdLine, int nCmdShow){
    MSG msg;
    
    hInst = hCurInst;
    if (!InitApp(hCurInst))
        return FALSE;
    if (!InitInstance(hCurInst, nCmdShow)) 
        return FALSE;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}


//ウィンドウプロシージャ

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){
    HPEN hPen;
    PRINTDLG pd;
    DOCINFO di;
    TEXTMETRIC tm;
        TCHAR szStr[128];

    switch (msg) {
        case WM_COMMAND:
            switch (LOWORD(wp)) {
                case IDM_END:
                    SendMessage(hWnd, WM_CLOSE, 0, 0);
                    break;
                case IDM_PRINT:
                    memset(&pd, 0, sizeof(PRINTDLG));
                    pd.lStructSize = sizeof(PRINTDLG);
                    pd.hwndOwner = hWnd;
                    pd.hDevMode = NULL;
                    pd.hDevNames = NULL;
//      pd.Flags = デバイスコンテキストを返す 「選択した部分」ラジオボタンを使用不可にします 「ファイルへ出力」チェックボックスを隠します。
                                        pd.Flags = PD_RETURNDC |
                        PD_NOPAGENUMS | PD_NOSELECTION | PD_HIDEPRINTTOFILE;
                    pd.nCopies = 1;             //      印刷部数1
                                        pd.nFromPage = 1;       //      スタートページ1
                    pd.nToPage = 1;             //      最後のページ1
                    pd.nMinPage = 1;    //      ページ範囲の最小値1
                    pd.nMaxPage = 1;    //      ページエディットコントロールの最大値1
                    memset(&di, 0, sizeof(DOCINFO));
                    di.cbSize = sizeof(DOCINFO);
                    di.lpszDocName = TEXT("PrintDlg API");
                    
                    if (PrintDlg(&pd)==TRUE) {      //      ダイアログ表示
                                                StartDoc(pd.hDC, &di);
                        StartPage(pd.hDC);

//      印刷される内容
                        DEVNAMES  * DevNames   = (DEVNAMES *)(GlobalLock(pd.hDevNames));
                        DEVMODE   * DevMode    = (DEVMODE *)(GlobalLock(pd.hDevMode));

                        TCHAR     * szDriverName = (TCHAR *)(DevNames) + DevNames->wDriverOffset;
                        TCHAR     * szDeviceName = (TCHAR *)(DevNames) + DevNames->wDeviceOffset;

                        int cx=int(3.5*double(GetDeviceCaps(pd.hDC , LOGPIXELSX))/25.4);        //3.5ミリの文字幅を計算(ピクセル)
                        int cy=cx;
#ifdef UNICODE
                        HFONT hfont=CreateFont(cx,cy,0,0,0,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH | FF_DONTCARE,TEXT("MS 明朝"));

#else
                        HFONT hfont=CreateFont(cx,cy,0,0,0,0,0,0,SHIFTJIS_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH | FF_DONTCARE,TEXT("MS 明朝"));

#endif
                        SelectObject(pd.hDC,hfont);

                        GetTextMetrics(pd.hDC, &tm);
                        int sx=0,sy=cy; //      印刷開始位置(ピクセル)

                        wsprintf(szStr, TEXT("プリンタ名  %s"),szDeviceName );
                        TextOut(pd.hDC, sx, sy, szStr, (int)_tcslen(szStr));

                        wsprintf(szStr, TEXT("ドライババージョン  %i"), GetDeviceCaps(pd.hDC , DRIVERVERSION) );
                        TextOut(pd.hDC, sx, sy+=cy, szStr, (int)_tcslen(szStr));

                        wsprintf(szStr, TEXT("解像度 %i*%i (DPI)") , GetDeviceCaps(pd.hDC , LOGPIXELSX), GetDeviceCaps(pd.hDC , LOGPIXELSY));
                        TextOut(pd.hDC, sx,sy+=cy , szStr, (int)_tcslen(szStr));
                                                
                        wsprintf(szStr, TEXT("印刷範囲 %i*%i (ピクセル)") , GetDeviceCaps(pd.hDC ,PHYSICALWIDTH ), GetDeviceCaps(pd.hDC , PHYSICALHEIGHT));
                        TextOut(pd.hDC, sx, sy+=cy, szStr, (int)_tcslen(szStr));

                        GlobalUnlock(pd.hDevNames);  GlobalFree(pd.hDevNames);
                        GlobalUnlock(pd.hDevMode);   GlobalFree(pd.hDevMode);

                        double p=double(GetDeviceCaps(pd.hDC , LOGPIXELSY))/25.4;       //      1mの線幅を計算(ピクセル)

                        wsprintf(szStr, TEXT("漢字 %i*%i") , tm.tmAveCharWidth , tm.tmHeight);
                        TextOut(pd.hDC, sx, sy+=cy, szStr, (int)_tcslen(szStr));

//      印刷範囲を1mの線で印刷
                        hPen = CreatePen(PS_SOLID,int(p) , RGB(255, 0, 0));
                        SelectObject(pd.hDC, hPen);

                        MoveToEx(pd.hDC, 0, 0, NULL);
                        LineTo(pd.hDC, GetDeviceCaps(pd.hDC ,PHYSICALWIDTH ),0);
                        LineTo(pd.hDC, GetDeviceCaps(pd.hDC ,PHYSICALWIDTH ),GetDeviceCaps(pd.hDC , PHYSICALHEIGHT));
                        LineTo(pd.hDC, 0,GetDeviceCaps(pd.hDC , PHYSICALHEIGHT));
                        LineTo(pd.hDC, 0,0);
                                                
//      印刷される内容終了
                        EndPage(pd.hDC);
                        EndDoc(pd.hDC);
                        DelDeleteObject(hfont);
                        DeleteDC(pd.hDC);
                    }
            }
            break;
        case WM_CLOSE:
            DestroyWindow(hWnd);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return (DefWindowProc(hWnd, msg, wp, lp));
    }
    return 0;
}

ATOM InitApp(HINSTANCE hInst){
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = TEXT("PRINTMENU");
    wc.lpszClassName = szClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    return (RegisterClassEx(&wc));
}


BOOL InitInstance(HINSTANCE hInst, int nCmdShow){
    HWND hWnd;

    hWnd = CreateWindow(szClassName,
            TEXT("PrintDlg"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL,
            hInst,
            NULL);
    if (!hWnd)
        return FALSE;
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}

printdlg.rc

#include <windows.h>
#include "resource.h"

PRINTMENU MENU DISCARDABLE 
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "印刷(&P)..."      , IDM_PRINT
        MENUITEM "終了(&X)"         , IDM_END
    END
END

resource.h

#define IDM_END 100
#define IDM_PRINT 110