kkamegawa's weblog

Visual Studio,TFS,ALM,VSTS,DevOps関係のことについていろいろと書いていきます。Google Analyticsで解析を行っています

DEVNAMESの指し示すところ

ここ数日悪戦苦闘したおかげでDEVNAMESとDEVMODE構造体について理解できた。通常プリンタダイアログ使えばいいのだけれど、独自に作る場合はこのサポート技術情報が参考になる。
プログラムで MFC で既定以外のプリンターに印刷する方法
なんでDEVNAMESこれでいいんだろーと思ったら、味噌はこの部分。

    // 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));

DEVNAMES構造体は4つのWORDのみ格納していて、「その後ろに」ドライバ名、プリンタ名、ポート名の領域を確保しておき、涼気へのオフセットのみ格納するという、ちょっとわかりにくいタイプ。このDEVNAMES構造体ってプリンタ選択ダイアログ(PrintDlg())で取得するとプリンタドライバが"winspool"なのね。自分で作るときはPRINTER_INFO_2構造体から作るから、ちゃんとしたドライバ名が入ります。
DEVMODE構造体のdmExtra領域って、ドライバ固有だから何入れていてもサイズさえあっていればいいのだけれど、Unicodeと思われる文字列と、ANSI文字列一緒にしてるってどうなのよ(^^;。手元のNECのNPDL2ドライバではプリンタのステータスパネルに表示するユーザ名とサーバ名はUnicodeで、NPDLという文字列はANSIで入っていてちょっとびっくり。