« PDF作成の自動化・省力化 [2] (CtrlSaveas.exeをVBから使う) | トップページ | PDF作成の自動化・省力化 [4] (改良版CtrlSaveas.exeをVBから使う) »

2009年6月29日 (月)

PDF作成の自動化・省力化 [3] (「名前を付けて保存」を外から操作するプログラムの改良版)

[1]のCtrlSaveas.exeは「名前を付けて保存」ダイアログが表示されるのを待つわけですが、このダイアログの表示は印刷処理の一部です。つまりこのダイアログが表示されたときには印刷処理が開始しているわけです。
そこでさらに印刷処理の終了まで待つ機能も付けました。

---------------------------------------------------------------------------
[ CtrlSaveas.cpp ]

BOOL WaitAndCtrlSaveas(LPCSTR filepath, DWORD timeout, BOOL ExecEnter, LPCSTR printer);

int main(int argc, char* argv[])
{
  DWORD  timeout;
  TCHAR  printer[64];

  if (argc == 1){
    printf("CtrlSaveas.exe ファイルパス タイムアウト秒 [プリンタ名]\n");
    return 0;
  }
  timeout = atol(argv[2]);
  if (argc >= 4){
    _tcscpy(printer, argv[3]);
  } else {
    printer[0] = '\0';
  }

  WaitAndCtrlSaveas(argv[1], timeout, TRUE, printer);
  return 0;
}

// EnumChildWindowsのコールバック関数。
BOOL CALLBACK GetEdit(
  HWND hwnd,      // 子ウィンドウのハンドル
  LPARAM lParam   // アプリケーション定義の値
){

  TCHAR  clname[32];

  if (GetClassName(hwnd, clname, 32) > 0){
    if (strcmp(clname, "Edit") == 0){
      *((HWND *)(lParam)) = hwnd;
    }
  }

  return TRUE;
}

BOOL WaitAndCtrlSaveas(LPCSTR filepath, DWORD timeout, BOOL ExecEnter, LPCSTR printer)
{
  DWORD  starttime;
  HWND  hWnd;
  BOOL  ret = FALSE;

  timeout *= 1000;
  starttime = GetTickCount();
  for (;;){
    if ((GetTickCount() - starttime) > timeout){
      break;
    }
    hWnd = FindWindow(NULL, "名前を付けて保存");
    //if (hWnd != NULL /*&& hWnd == GetForegroundWindow()*/){
    if (hWnd && IsWindowVisible(hWnd)){
      HWND  hWndEdt = NULL;
      EnumChildWindows(hWnd, (WNDENUMPROC)GetEdit, (LPARAM)&hWndEdt);
      //
      if (hWndEdt != NULL){
        SendMessage(hWndEdt, WM_SETTEXT, 0, (LPARAM)filepath);
        if (ExecEnter != FALSE){
          PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0);
        }
        hWndEdt = NULL;
        ret = TRUE;
        break;
      }
    } else {
      Sleep(100);
    }
  }
  // ↑ここまで[1]と同じ。
  // プリンタが指定されているときは印刷ジョブの終了も待つ
  if (ret == TRUE){
    if (printer[0]){
      HANDLE  hPrinter;
      PRINTER_INFO_2  *pPrinterInfo = NULL;  // プリンタ情報取得
      DWORD  dwPrinterInfo = 0;
      DWORD  bytes, jobs;
      
      ret = FALSE;
      for (;;){
        if ((GetTickCount() - starttime) > timeout){
          break;
        }
        jobs = 0xFFFF;
        if (OpenPrinter((char *)printer, &hPrinter, NULL) != 0){
          for (;;){  // このループは2回しか回らない。最初は必要なメモリ量の取得、次に印刷ジョブ数の取得
            // プリンタ情報取得
            if (GetPrinter(hPrinter, 2, (LPBYTE)pPrinterInfo, dwPrinterInfo, &bytes) == 0){
              if (GetLastError() == ERROR_INSUFFICIENT_BUFFER){
                if (pPrinterInfo != NULL) free(pPrinterInfo);
                dwPrinterInfo = bytes;
                pPrinterInfo = (PRINTER_INFO_2 *)malloc(dwPrinterInfo);
                continue;
              }    // その他エラーを無視
            } else {
              jobs = pPrinterInfo->cJobs;    // 現在の印刷ジョブ数
            }
            break;
          }
          ClosePrinter(hPrinter);
          if (jobs == 0){
            ret = TRUE;
            break;
          }
        }
        Sleep(1000);  // 印刷ジョブ数が0でない場合、時間を置いて再度ジョブ数を取得
      }
      if (pPrinterInfo != NULL) free(pPrinterInfo);
    }
  }
  return (ret);
}

« PDF作成の自動化・省力化 [2] (CtrlSaveas.exeをVBから使う) | トップページ | PDF作成の自動化・省力化 [4] (改良版CtrlSaveas.exeをVBから使う) »

ソフトウエア」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

« PDF作成の自動化・省力化 [2] (CtrlSaveas.exeをVBから使う) | トップページ | PDF作成の自動化・省力化 [4] (改良版CtrlSaveas.exeをVBから使う) »