お世話になっています、GGです。
PDFファイルを開きたいのですが、どうしたらいいでしょうか。
例:
ダイアログ上であるボタンをクリックするとEfg.pdfを開くということです。
環境:.Net MFC使用、Win2000
アドバイスよろしくお願いします。
拡張子に関連づいたアプリケーションを動かすのではダメなんでしょうか?
(たとえば、AcrobatReaderとかを動かす)
→ShellExecture関数で出来る。
それとも、自分で pdf の構造を解析して、自分のアプリ上で表示したいのでしょうか?
これをやるとしたら、まずは pdf の構造を理解して、とカナリの工数になりそうです。
訂正)
>→ShellExecture関数で出来る
ShellExecute
Blueさん
いつもお世話になっています。
>ShellExecuteEx関数で出来る
うまくできました。
>それとも、自分で pdf の構造を解析して、自分のアプリ上で表示したいのでしょうか?
>これをやるとしたら、まずは pdf の構造を理解して、とカナリの工数になりそうです。
今回はPdfファイルを開くだけです、そこまでにするには、実力がないです。
貴重なアドバイスありがとう。
ほんとに、ありがとうございました。
追加質問があります。
開いたpdfファイルを閉じると
どうしたらいいでしょうか。
よろしくお願いします。
>開いたpdfファイルを閉じると
>どうしたらいいでしょうか
???閉じたら 何か不都合でも起きたのですか
たとえば自分のアプリにもどらないとか
何のために、PDFを表示させるんでしょうか?
確認用に「一定時間だけ表示させたい」ということでしょうか?
ShellExecuteのヘルプを読むとわかると思いますが、
別プロセスとして起動するので、呼び出し元がそのプロセスに対して
どうこうするってことは普通は考えません。
ユーザが普通に×ボタンかなんかで閉じてもらうようにするのが普通です。
(まぁできないこともないが。)
?, Blueさん、
ご返事ありがとう
説明が不足ですが、
ダイアログのボタンでPDFファイルを開きます、
まだ、このボタンを押すと、既に開いたPDFを閉じて、
別のPDFファイルを開くということです.
当然、PDFのアプリ自身の閉じるボタンがあるのですが、
でも、そのボタンを押さない場合は、
ダイアログ側のボタンを押すと複数PDFを開いた、
そのことを避けたいのです。
(ダイアログ側のボタンを押すと、PDFを閉じる)
よろしくお願いします。
なにが、PDFを表示していますか?
Adobe Readerでしょうか?
私の環境では、デフォルトで、Adobe Readerの起動オプションに /n がついていないの
で、別のインスタンスとして起動されるようなことはありません。
どんなコマンドで実行されているか確認してください。
(エクスプローラのフォルダオプションあたりで拡張子PDFのものを確認。
Windows2000はどうなっているのか忘れたので詳しくはかけません。)
ShellExecuteだと開きっぱなしになるので、
呼び出し元のプロセスから操作(閉じる)をしたければ、
CreateProcessを使いましょう。
「他のAP実行」の実装例
http://www24.cds.ne.jp/~neg/pro/piyo1/index.html#ap
Blueさん
ご返事ありがとう.
>なにが、PDFを表示していますか?
>Adobe Readerでしょうか?
はい、Adobe Reader Ver.7.0です、
ShellExecuteEx関数で起動が出来ています。
問題なのは、開いたAdobe Readerを閉じるということです。
ようするに、自作したアプリのダイアログ上に配置したボタン
を押すと、Adobe Readerを起動(終了)することです。
よろしくお願いします。
まぁ、CreateProcessでも出来なくはないですが、Adobe Readerのフルパスが必要になっ
てしまうので、ShellExecuteEx関数で起動後、対象のウィンドウハンドルを探して、
WM_CLOSEをSendMessageするようにしてはどうでしょうか?
※対象のウィンドウハンドルを探すには、FindWindowあたりの関数を使ってください。
ウィンドウタイトルで探せばいいと思います。
> ウィンドウタイトルで探せばいいと思います。
クラス名で探したほうがよかったかも。
ダイアログクラスにCWnd*型のメンバ変数を用意して、
ShellExecuteEx関数の実行後、ウィンドウハンドルを探して保持しておき、
閉じるボタンを押したときに、そのメンバ変数に対してSendMessageします。
適当にやってみた。
○XXXXDlg.h
CXXXXDlgクラス内に
private:
CWnd* m_pPDFExeWnd;
を記述
○XXXXDlg.cpp
CXXXXDlgクラスのコンストラクタにm_pPDFExeWndの初期化処理を記述
CXXXXDlg::CXXXXDlg(CWnd* pParent /*=NULL*/)
: CDialog(CXXXXDlg::IDD, pParent), m_pPDFExeWnd(NULL) // ←これ
{
ボタン1で開く
void CXXXXDlg::OnButton1()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
TCHAR PDFPath[MAX_PATH];
_tcscpy(PDFPath, _T(E:\\test.pdf)); // 適当なファイルのパス
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.hwnd = this->m_hWnd;
sei.lpVerb = _T(open);
sei.lpFile = PDFPath;
sei.lpParameters = NULL;
sei.lpDirectory = NULL;
sei.nShow = SW_SHOW;
if (::ShellExecuteEx(&sei))
{
// アイドル状態になるまでまつ
::WaitForInputIdle(sei.hProcess, INFINITE);
// すでに開いていないとき、クラス名 AdobeAcrobat として対象の
// アプリを探す。
// ※クラス名はVer6.0のAdobe Readerですので、Ver7.0で取得できない場合
// Spy++でクラス名を確認して適切に変更してください。
if (!this->m_pPDFExeWnd)
this->m_pPDFExeWnd = this->FindWindow(_T(AdobeAcrobat), NULL);
}
}
ボタン2で閉じる
void CXXXXDlg::OnButton2()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
if (this->m_pPDFExeWnd)
{
if (!this->m_pPDFExeWnd->SendMessage(WM_CLOSE))
this->m_pPDFExeWnd = NULL; // 閉じたので
}
}
たいちうさん、Blueさん
ご返事ありがとう.
>CreateProcessを使いましょう。
CreateProcess()とEnumWindows()で、
閉じることが出来ました。
>if (!this->m_pPDFExeWnd)
> this->m_pPDFExeWnd = this->FindWindow(_T(AdobeAcrobat), NULL);
で閉じることも出来ました。
ありがとうございました。
>CreateProcess()とEnumWindows()で、
>閉じることが出来ました。
本当にそれでよかったんでしょうか?
前述どおりAdobe Readerのフルパスが必要になります。
きめうちでフルパスを書くと、Adobe Readerのバージョンや
インストールしてあるドライブによっては動きません。
ですので、やはりShellExecuteExを使ったほうがよさそうですけど。
(拡張子PDFに関連づいているアプリのフルパスを取得するにはレジストリを見ることに
なります。)
> if (!this->m_pPDFExeWnd->SendMessage(WM_CLOSE))
> this->m_pPDFExeWnd = NULL; // 閉じたので
ちなみに、ここには間違いがあります。
ボタンでなくユーザが手動でAdobe Readerを閉じると、デバッグモードではASSERTしま
す。
ですので、条件として、ウィンドウハンドルが有効かどうか調べる必要があるでしょ
う。
if (!::IsWindow(this->m_pPDFExeWnd->GetSafeHwnd()) ||
!this->m_pPDFExeWnd->SendMessage(WM_CLOSE))
this->m_pPDFExeWnd = NULL;