第300章 ネットワークプリンタを使う その4


今回は、DocumentProperties関数を使って、現在のプリンタ (ネットワークでもローカルでも)の設定を取得するプログラムを作ります。



プリンタがネットワークプリンタの場合は「\\コンピュータ名\プリンタ名」の ように表示されます。

dwNeededはDocumentProperties関数で求めたDEVMODE 構造体全体に必要な最大バイト数 です。

StructSizeは、DEVMODE 構造体の大きさでドライバ固有のデータは含まれていません。

ExtraSizeは、DEVMODE構造体に続くドライバ固有のデータのバイト数です。これに、 StructSizeを加えるとdwNeededになります。

あとの項目は特に説明は必要ないでしょう。



では、プログラムを見てみましょう。

// printer02.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "プリンタ情報(&I)...", IDM_PRNINFO MENUITEM SEPARATOR MENUITEM "終了(&X)", IDM_END END END

メニューのリソース・スクリプトです。

// printer02.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); BOOL MyPrnInfo(HWND, char *); char szClassName[] = "printer02"; //ウィンドウクラス int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 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 = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるプリンタ", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

いつもと同じです。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; PAINTSTRUCT ps; HDC hdc; static char szBuf[1024]; RECT rc; switch (msg) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rc); DrawText(hdc, szBuf, strlen(szBuf), &rc, DT_WORDBREAK); EndPaint(hWnd, &ps); break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_PRNINFO: MyPrnInfo(hWnd, szBuf); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

メイン・ウィンドウのプロシージャです。メニューからIDM_PRNINFOが 選択されたらMyPrnInfo関数を呼び出します。

BOOL MyPrnInfo(HWND hWnd, char *szBuf) { HANDLE hPrn; PRINTDLG pd; DEVMODE *lpDM; char szPrnName[256], szTemp[256]; DWORD dwNeeded; HGLOBAL hMem; DEVMODE *pDev; memset(szPrnName, '\0', sizeof(szPrnName)); memset(&pd, 0, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); pd.Flags = PD_RETURNDEFAULT; pd.hDevMode = NULL; pd.hDevNames = NULL; if (PrintDlg(&pd) == IDOK) { lpDM = (DEVMODE *)GlobalLock(pd.hDevMode); if (lpDM == NULL) { MessageBox(hWnd, "メモリブロックをロックできません", "Error", MB_OK); return FALSE; } strcpy(szPrnName, (LPSTR)(lpDM->dmDeviceName)); if (OpenPrinter(szPrnName, &hPrn, NULL) == 0) { MessageBox(hWnd, "プリンタをオープンできません", "Error", MB_OK); GlobalUnlock(pd.hDevMode); GlobalFree(pd.hDevMode); return FALSE; } //1回目の呼び出しで必要なバッファサイズを求める dwNeeded = DocumentProperties(hWnd, hPrn, szPrnName, NULL, NULL, 0); hMem = GlobalAlloc(GHND, dwNeeded); if (hMem == NULL) { MessageBox(hWnd, "バッファのためのメモリを確保できません", "Error", MB_OK); ClosePrinter(hPrn); GlobalUnlock(pd.hDevMode); GlobalFree(pd.hDevMode); return FALSE; } pDev = (DEVMODE *)GlobalLock(hMem); if (pDev == NULL) { MessageBox(hWnd, "GlobalLockに失敗しました", "Error", MB_OK); GlobalFree(hMem); ClosePrinter(hPrn); GlobalUnlock(pd.hDevMode); GlobalFree(pd.hDevMode); return FALSE; } //2回目の呼び出しの時は5番目の引数をNULLにして、6番目の引数をDM_OUT_BUFFERに if (DocumentProperties(hWnd, hPrn, szPrnName, pDev, NULL, DM_OUT_BUFFER) < 0) { MessageBox(hWnd, "DocumentProperties関数が失敗しました", "Error", MB_OK); GlobalFree(hMem); ClosePrinter(hPrn); GlobalUnlock(pd.hDevMode); GlobalFree(pd.hDevMode); return FALSE; } //DEVMODE構造体から必要な情報をszBufにコピー wsprintf(szBuf, "DeviceName = %s\n", pDev->dmDeviceName); wsprintf(szTemp, "dwNeeded = %d\n", dwNeeded); strcat(szBuf, szTemp); wsprintf(szTemp, "StructSize = %d\n", pDev->dmSize); strcat(szBuf, szTemp); wsprintf(szTemp, "ExtraSize = %d\n", pDev->dmDriverExtra); strcat(szBuf, szTemp); if (pDev->dmFields & DM_ORIENTATION) { if (pDev->dmOrientation == 1) strcpy(szTemp, "PORTRAIT\n"); else strcpy(szTemp, "LANDSCAPE\n"); strcat(szBuf, "Orientation = "); strcat(szBuf, szTemp); } if (pDev->dmFields & DM_PAPERSIZE) { if (pDev->dmPaperSize == DMPAPER_A4) { strcpy(szTemp, "PaperSize = A4\n"); } else if (pDev->dmPaperSize == DMPAPER_A5) { strcpy(szTemp, "PaperSize = A5\n"); } else { strcpy(szTemp, "PaperSize = A4/A5以外\n"); } strcat(szBuf, szTemp); } if (pDev->dmFields & DM_COPIES) { wsprintf(szTemp, "Copies = %d\n", pDev->dmCopies); strcat(szBuf, szTemp); } if (pDev->dmFields & DM_PRINTQUALITY) { if (pDev->dmPrintQuality == DMRES_HIGH) strcpy(szTemp, "Quality = HIGH\n"); else if (pDev->dmPrintQuality == DMRES_MEDIUM) strcpy(szTemp, "Quality = MEDIUM\n"); else if (pDev->dmPrintQuality == DMRES_LOW) strcpy(szTemp, "Quality = LOW\n"); else if (pDev->dmPrintQuality == DMRES_DRAFT) strcpy(szTemp, "Quality = DRAFT\n"); else strcpy(szTemp, "Quality = Unknwon\n"); strcat(szBuf, szTemp); } if (pDev->dmFields & DM_COLOR) { if (pDev->dmColor == DMCOLOR_COLOR) strcpy(szTemp, "Color = Yes\n"); else if (pDev->dmColor == DMCOLOR_MONOCHROME) strcpy(szTemp, "Color = No\n"); else strcpy(szTemp, "Color = Unknown\n"); strcat(szBuf, szTemp); } InvalidateRect(hWnd, NULL, TRUE); ClosePrinter(hPrn); GlobalUnlock(hMem); if (GlobalFree(hMem) != NULL) { MessageBox(hWnd, "GlobalFree(hMem) が失敗しました", "Error", MB_OK); } GlobalUnlock(pd.hDevMode); if (GlobalFree(pd.hDevMode) != NULL) { MessageBox(hWnd, "GlobalFree Error", "Error", MB_OK); return FALSE; } return TRUE; } MessageBox(hWnd, "関数は失敗しました", "Error", MB_OK); return FALSE; }

ちょっと面倒くさいのですが、最初のDocumentProperties関数の呼び出しの時は 最後の引数を0にします。そうすると情報を格納するのに十分なバッファサイズを 得ることができます。

必要サイズがわかったら、メモリを確保しておきます。

もう一度DocumentProperties関数を呼ぶときは、pDevModeOutput(4番目の引数)に メモリを割り当てたDEVMODE構造体へのポインタを指定して、fMode(最後の引数)に DM_OUT_BUFFERを指定します。

あとは、DEVMODE構造体から知りたい情報を引き出します。この時dmFieldsメンバに ビットの立っていないものは、有効な情報ではありません。


[SDK第3部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 28/Jan/2001 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。