« シェル拡張-エクスプローラのコンテキストメニューを拡張 [5] | トップページ | PDF作成の自動化・省力化 [2] (CtrlSaveas.exeをVBから使う) »

2009年6月29日 (月)

PDF作成の自動化・省力化 [1] (「名前を付けて保存」を外から操作する)

ある仕事で、VB6で作成したアプリからエクセルのドキュメントを生成するプログラムがありました。
そのプログラムは完成しすでに運用に乗っているのですが、その後、そのエクセルドキュメントをPDFにもしたいという話が出てきました。
各クライアントPCには廉価版のPDF作成ソフト(プリンタドライバとしてインストールされる)がインストールされているので、現状はオペレータに手作業でPDF化してもらっています。しかし、「名前を付けて保存」ダイアログでフォルダを選択してから名前を入力する作業がわずらわしいので何とか自動化または省力化ができないか、というわけです。

そこで「名前を付けて保存」ダイアログに"外部から"出力ファイル名をセットしENTERを入力するプログラムを作ってみました。開発言語はVC++6。
プログラムの構造はループの中でタイムアウトが来るまで「名前を付けて保存」ウインドウを待ち、それが出てきたらダイアログ上のEditにファイルパスをセットしENTERを送る、というものです。このプログラムを印刷に先立って起動しておきます。

このプログラムは
 ・ダイアログ上にはEditは一つしかなく、それが出力ファイル名欄であること。
 ・OKボタンがDefault Buttonであること。
が前提であり
 ・起動時に他のプログラム(メモ帳など)の「名前を付けて保存」ダイアログが出ていたらそれに反応してしまう。
などの問題があります。(GetTickCount関数の"巻き戻し"も無視している。出力ファイルが既存の時、無条件に削除するか、独自に上書き確認するか、PDFプリンタの上書き確認に任せるか、などが必要。)

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

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

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

  if (argc == 1){
    printf("CtrlSaveas.exe ファイルパス タイムアウト秒\n");
    return 0;
  }
  timeout = atol(argv[2]);

  WaitAndCtrlSaveas(argv[1], timeout, TRUE);
  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)
{
  DWORD  starttime;
  HWND  hWnd;
  BOOL  ret = FALSE;

  timeout *= 1000;
  starttime = GetTickCount();
  for (;;){
    if ((GetTickCount() - starttime) > timeout){ // タイムアウトチェック
      break;
    }
    hWnd = FindWindow(NULL, "名前を付けて保存");
    if (hWnd && IsWindowVisible(hWnd)){ // ダイアログが表示されている
      HWND  hWndEdt = NULL;
      // ダイアログ上のEditを取得
      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);
    }
  }
  return (ret);
}

« シェル拡張-エクスプローラのコンテキストメニューを拡張 [5] | トップページ | PDF作成の自動化・省力化 [2] (CtrlSaveas.exeをVBから使う) »

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

コメント

コメントを書く

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

トラックバック

« シェル拡張-エクスプローラのコンテキストメニューを拡張 [5] | トップページ | PDF作成の自動化・省力化 [2] (CtrlSaveas.exeをVBから使う) »