none
PrintDlgEx関数でダイアログが表示されません。 RRS feed

  • 質問

  • 皆さん、又、御世話に成ります。何卒、宜しく御願い致します。実は、タイトル通りなのですが、PrintDlgEx関数を使用致しまして、プリント・ダイアログを表示させようと致して居りますが、何故か、表示されません。途中までは、PrintDlgEx関数の戻り値が0x3を返して居りますが、PrintDlgEx関数を実行された瞬間に、戻り値が0x80070057(10進数では、-2147024809)を返してしまいます。自分なりに色々調べましたら、0x80070057は一つ以上の引数が不正との様ですが、私にはどこが不正なのか理解できませんでした。何卒、お力添え下さいますよう、御願い申し上げます。下記に、コードを貼っておきます。因みに、開発環境は、Windows Vista SP2, VS2010Expressです。

    case IDM_PRINT:  //「印刷」ボタンが押された時
           {
            ////////////////////////////////////////////////////////////////////////
            //
            //  構造体の宣言と初期化欄
            //
            ////////////////////////////////////////////////////////////////////////

            //------------------------------------PRINTDLGEX構造体------------------------------------//
            PRINTDLGEX DSPrntDlgEx;

            ::ZeroMemory(&DSPrntDlgEx, sizeof(PRINTDLGEX)); //PRINTDLGEXのメモリを0で埋める
            //----------------------------------------------------------------------------------------//

            //------------------------------------DEVMODE構造体---------------------------------------//
            //DEVMODE*の割り当て(戻り値は、HGLOBAL <- ハンドル)
            HGLOBAL DSglDevMd = ::GlobalAlloc(GHND, sizeof(DEVMODE*));

            //DSglDevMdのロック(戻り値は、ポインター)
            DEVMODE* DSpDevMd = (DEVMODE*)::GlobalLock(DSglDevMd);
            //----------------------------------------------------------------------------------------//

            //------------------------------------DEVNAMES構造体--------------------------------------//
            //DEVNAMES*の割り当て(戻り値は、HGLOBAL <- ハンドル)
            HGLOBAL DSglDVNames = ::GlobalAlloc(GHND, sizeof(DEVNAMES*));

            //DSglDVNamesのロック(戻り値は、ポインター)
            DEVNAMES* DSpDVNames = (DEVNAMES*)::GlobalLock(DSglDVNames);
            //----------------------------------------------------------------------------------------//

            //------------------------------------PRINTPAGERANGE構造体--------------------------------//
            PRINTPAGERANGE DSPprgs[999];

            ::ZeroMemory(&DSPprgs, sizeof(PRINTPAGERANGE));

            LPPRINTPAGERANGE DSlpPprgs = DSPprgs;

            DSlpPprgs->nFromPage = 1;
            DSlpPprgs->nToPage   = 999;
            //----------------------------------------------------------------------------------------//

            //PRINTDLGEX構造体の設定
               //----セットしてPD_RETURNDEFAULTフラグを指定するだけで
               //----上手くいったが、新しいバージョンではhwndOwnerと
               //----nStartPageもセットしてあげないとダメ。さらに
               //----PD_NOPAGENUMSフラグを追加するか、さもなくば
               //----nMaxPageRangesとlpPageRangesをセットする。

            DSPrntDlgEx.lStructSize    = sizeof(PRINTDLGEX);
            DSPrntDlgEx.hwndOwner      = DShWnd;
            DSPrntDlgEx.hDevMode       = (HGLOBAL)DSglDevMd;
            DSPrntDlgEx.hDevNames      = (HGLOBAL)DSglDVNames;
            DSPrntDlgEx.hDC;
            DSPrntDlgEx.Flags          = PD_RETURNDC;
            DSPrntDlgEx.nPageRanges    = 999;
            DSPrntDlgEx.nMaxPageRanges = 999;
            DSPrntDlgEx.lpPageRanges   = DSlpPprgs;
            DSPrntDlgEx.nMinPage       = 1;
            DSPrntDlgEx.nMaxPage       = 999;
            DSPrntDlgEx.nCopies        = 1;
            DSPrntDlgEx.nStartPage     = START_PAGE_GENERAL;

            //上記までは、DShPrintRes の戻り値は、0x3

            //下記の関数が実行されると、戻り値は0x80070057

    HRESULT DShPrintRes = ::PrintDlgEx(&DSPrntDlgEx);

            //以下、テスト用
            if (DShPrintRes == S_OK && DSPrntDlgEx.dwResultAction == PD_RESULT_PRINT)
             {
              ::MessageBeep(MB_OK);
                }

            //------------------------------------後始末----------------------------------------------//
            //DSbRes = ::GlobalUnlock(DSglDevMd);  //DSglDevMdの解除

            HGLOBAL DSglFree = ::GlobalFree(DSglDevMd);  //DSglDevMdの解放

            //DSbRes = ::GlobalUnlock(DSglDVNames);  //DSglDVNamesの解除

            DSglFree = ::GlobalFree(DSglDVNames);  //DSglDVNamesの解放
            //----------------------------------------------------------------------------------------//

            break;

    2011年10月1日 15:00

回答

  • 参考までに私がやってみたこと。

    1. Visual C++ 2010 Express で新規プロジェクトを作成する。(テンプレートは [Win32 プロジェクト])
    2. [Win32 アプリケーション ウィザード] の [アプリケーション設定] で [アプリケーションの種類] を [Windows アプリケーション] にして [完了] する。
    3. ここまでで一旦 [ビルド] して [デバッグ開始] する。

    [ファイル] と [ヘルプ] メニューだけがある白いウィンドウが起動します。起動したことを確認したら、アプリケーションを終了します。

    4. stdafx.h を開き、「#define WIN32_LEAN_AND_MEAN」という行をコメントアウトする。(commdlg.h をインクルードさせるため)
    5. http://msdn.microsoft.com/en-us/library/ms646829(VS.85).aspx をブラウザーで開き、サンプル コードの DisplayPrintPropertySheet 関数をごっそりコピーする。
    6. _tWinMain 関数があるソース コードを開き、コピーしたコードを _tWinMain 関数の直前にコピーする。(プロトタイプ宣言を書くのが面倒だったので...)
    7. WndProc 関数内の「case IDM_ABOUT:」の次にある「DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);」をコメントアウトする。
    8. コメントアウトした行と「break;」の間に「DisplayPrintPropertySheet(hWnd);」を入れる。

    これでアプリケーションの [ヘルプ] - [バージョン情報] を選択すると、印刷ダイアログが表示されるようになるはずです。
    [ヘルプ] - [バージョン情報] を利用したののは、なるべく余計なコードが入る隙を排除したいからです。

    [ビルド] して [デバッグ開始] します。同じく [ファイル] と [ヘルプ] メニューだけがある白いウィンドウが起動するはずです。
    [ヘルプ] - [バージョン情報] を選択します。すると、印刷ダイアログが表示されました。

    残念ながら手元には Vista がないので、Windows 7 と XP とでしか確認できていません。
    時間と実行環境が見つかれば、Vista でも試してみても良いですが、いつになるかは分かりません。
    2011年10月5日 11:16

すべての返信

  • とりあえず、
            DSPrntDlgEx.nPageRanges    = 999;
    の部分をコメントアウトする(値を0のままにする)とダイアログは表示されるので、ここのところを見直してはいかがでしょうか。
    MSDN のサンプルを参考にされるのも良いと思います。

    Using Common Dialog Boxes (Windows)
    http://msdn.microsoft.com/en-us/library/ms646829(v=VS.85).aspx#print_property

    あと、次の部分は正しくないと思います。

            //------------------------------------PRINTPAGERANGE構造体--------------------------------//
            PRINTPAGERANGE DSPprgs[999];

            ::ZeroMemory(&DSPprgs, sizeof(PRINTPAGERANGE));

    2011年10月2日 3:13
  • totojo様、回答有り難う御座いました。

    DSPrntDlgEx.nPageRanges    = 999;
    //の部分をコメントアウトする(値を0のままにする)とダイアログは表示されるので、
    //ここのところを見直してはいかがでしょうか。

    上記、私の環境では、何の変化も御座いませんでした。(コメントアウトと0 <ゼロの代入を試しました。>)

    あと、次の部分は正しくないと思います。
     //--------------------PRINTPAGERANGE構造体----------------//
             PRINTPAGERANGE DSPprgs[999];
     
            ::ZeroMemory(&DSPprgs, sizeof(PRINTPAGERANGE));
    

    上記の部分を

    //--------------------PRINTPAGERANGE構造体----------------//
             PRINTPAGERANGE DSPprgs[999];

            ::ZeroMemory(&DSPprgs, sizeof(DSPprgs));

    //--------------------------------------------------------------//

    の様に書き換えました。この考えで宜しいのでしょうか。

    2011年10月2日 9:53
  • DSPrntDlgEx.nPageRanges    = 999;
    //の部分をコメントアウトする(値を0のままにする)とダイアログは表示されるので、
    //ここのところを見直してはいかがでしょうか。

    上記、私の環境では、何の変化も御座いませんでした。(コメントアウトと0 <ゼロの代入を試しました。>)


    次の 2 つのメンバーについても、有効な値を指定しないのであれば、何もせずに NULL のままにしておかないといけないようです。
            DSPrntDlgEx.hDevMode       = (HGLOBAL)DSglDevMd;
            DSPrntDlgEx.hDevNames      = (HGLOBAL)DSglDVNames;


    あと、次の部分は正しくないと思います。
     //--------------------PRINTPAGERANGE構造体----------------//
             PRINTPAGERANGE DSPprgs[999];
     
            ::ZeroMemory(&DSPprgs, sizeof(PRINTPAGERANGE));
    

    上記の部分を

    //--------------------PRINTPAGERANGE構造体----------------//
             PRINTPAGERANGE DSPprgs[999];

            ::ZeroMemory(&DSPprgs, sizeof(DSPprgs));

    //--------------------------------------------------------------//

    の様に書き換えました。この考えで宜しいのでしょうか。

    私なら、
    ::ZeroMemory(&DSPprgs[0], sizeof(DSPprgs));
    

    とか
    ::ZeroMemory(DSPprgs, sizeof(DSPprgs));
    

    などと書きます。

    • 編集済み totojo 2011年10月2日 11:54
    2011年10月2日 11:54
  • totojo様、回答有り難う御座います。
    次の 2 つのメンバーについても、有効な値を指定しないのであれば、何もせずに NULL のままにしておかないといけないようです。
    >次の 2 つのメンバーについても、有効な値を指定しないのであれば、何もせずに NULL のままにしておかないといけな>いようです。
    DSPrntDlgEx.hDevMode = NULL;
    DSPrntDlgEx.hDevNames = NULL;
    上記の様に修正致しました。
    >私なら、
    >::ZeroMemory(&DSPprgs[0], sizeof(DSPprgs));
    >とか
    >::ZeroMemory(DSPprgs, sizeof(DSPprgs));

    >などと書きます。
    PRINTPAGERANGE DSPprgs[999];
            ::ZeroMemory(&DSPprgs[0], sizeof(DSPprgs));
            LPPRINTPAGERANGE DSlpPprgs = DSPprgs;
            DSlpPprgs->nFromPage = 1;
            DSlpPprgs->nToPage   = 999;
    上記の様に修正致しました。それで、最終的なコードは、下記の通りです。
    case IDM_PRINT:  //「印刷」ボタンが押された時
           {
            ////////////////////////////////////////////////////////////////////////
            //
            //  構造体の宣言と初期化欄
            //
            ////////////////////////////////////////////////////////////////////////
            //------------------------------------PRINTDLGEX構造体------------------------------------//
            PRINTDLGEX DSPrntDlgEx;
            ::ZeroMemory(&DSPrntDlgEx, sizeof(PRINTDLGEX)); //PRINTDLGEXのメモリを0で埋める
            //----------------------------------------------------------------------------------------//
            DSPrntDlgEx.lStructSize    = sizeof(PRINTDLGEX);
            DSPrntDlgEx.hwndOwner      = DShWnd;
            DSPrntDlgEx.hDevMode       = NULL;//(HGLOBAL)DSglDevMd;
            DSPrntDlgEx.hDevNames      = NULL;//(HGLOBAL)DSglDVNames;
            DSPrntDlgEx.hDC;
            DSPrntDlgEx.Flags          = PD_RETURNDC;;
            DSPrntDlgEx.nPageRanges    = 0;
            DSPrntDlgEx.nMaxPageRanges = 999;
            HRESULT DShPrintRes = ::PrintDlgEx(&DSPrntDlgEx);
            //以下、テスト用
            if (DShPrintRes == S_OK && DSPrntDlgEx.dwResultAction == PD_RESULT_PRINT)
             {
              ::MessageBeep(MB_OK);
                }
            break;
           }
    それで結果を申し上げますと、DShPrintRes には最初0(ゼロ)が入り、PrintDlgExが実行されると0x80070057を返します。状況は、やはり変化が御座いませんでした。
    上記のコードでダメという事は、何かインクルードファイルとか必要なのでしょうか。後、気になる事が一つ。時々、上記のコードでPrintDlgEx()が実行されますと、アクセス違反が発生する事が御座います。この原因が分かりません。何が考えられるのでしょうか。
    2011年10月2日 13:54
  • MSDN を読んでいますか?
    nMaxPageRanges は 999 にしないとだめなんですか?nMaxPageRanges = 999 ということは、最大 999 個のページの区間を指定できることですよね?(1-2, 3-4, ..., という調子で 999 個の区間を指定可能にしている)
    その割には最後のコード片は lpPageRanges に設定すらされなくなっていますが…。

     


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2011年10月2日 14:35
    モデレータ
  • Azulean様、御世話に成ります。

    >MSDN を読んでいますか?

    すみません、詳しくは、読んで居りませんでした。今後は、注意致しまして、良く読むように致します。

    >nMaxPageRanges は 999 にしないとだめなんですか?nMaxPageRanges = 999 ということは、最大 999 個の

    >ページの区間を指定できることですよね?(1-2, 3-4, ..., という調子で 999 個の区間を指定可能にしている)

    実際問題と致しまして、999個の区間を指定するという事はあまりないとは存じますが、試験的に999個の区間を指定可能に致したいと存じて居ります。

    又、何か御気付きの点が御座いましたら、御教え下さいますよう宜敷く御願い申し上げます。

    2011年10月2日 23:37
  • なんでZeroMemory()が流行ってるのかわかりませんが、

    PRINTPAGERANGE DSPprgs[999] = {};

    でゼロクリアされるのがC言語の仕様です。

    2011年10月3日 0:03
  • 又、何か御気付きの点が御座いましたら、御教え下さいますよう宜敷く御願い申し上げます。


    Azulean さんの次の言葉は届いていますか?
    その割には最後のコード片は lpPageRanges に設定すらされなくなっていますが…。

    MSDN もスレッドへの回答も読みましょう。
    2011年10月3日 0:57
  • 佐祐理様、totojo様、御世話に成ります。まとめレスで、申し訳御座いません。

    まず、初めに

    >なんでZeroMemory()が流行ってるのかわかりませんが、

    >PRINTPAGERANGE DSPprgs[999] = {};

    >でゼロクリアされるのがC言語の仕様です。

    との事でしたので、その様にコードを書き換えました。

    次に、

    >その割には最後のコード片は lpPageRanges に設定すらされなくなっていますが…。

    色々コードを書き換えましたが、私には分かりませんでした。それで、

    http://msdn.microsoft.com/en-us/library/ms646829(v=VS.85).aspx#print_property

    そのままコピー & ペーストで貼り付けて実行致しましたが、それでも

    「Windows によって DS.exe でブレークポイントが発生しました。

    ヒープが壊れていることが原因として考えられます。DS.exe または読み込まれた DLL にバグがあります。

    あるいは、DSLot.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。

    可能であれば、出力ウィンドウに詳細な診断情報が表示されます。」

    と表示されてしまいます。これは、実行時毎回表示されます。

    因みに、自分で書いたコードは下記の通りですが、これは毎回ではないのですがアクセス違反が生じます。しかし、表示は、毎回されません。何卒、御教授下さいますよう、宜敷く御願い申し上げます。

    //------------------------------------PRINTPAGERANGE構造体--------------------------------//
            PRINTPAGERANGE DSPprgs[999] = {};

            for (int DSnCnt = 0; DSnCnt < 999; DSnCnt++)
             {
              DSPprgs[DSnCnt].nFromPage = DSnCnt;

              DSPprgs[DSnCnt].nToPage = DSPprgs[DSnCnt].nFromPage + 1;
                }

            LPPRINTPAGERANGE DSlpPprgs = DSPprgs;
            //----------------------------------------------------------------------------------------//

            //PRINTDLGEX構造体の設定
            DSPrntDlgEx.lStructSize    = sizeof(PRINTDLGEX);
            DSPrntDlgEx.hwndOwner      = DShWnd;
            DSPrntDlgEx.hDevMode       = (HGLOBAL)DSglDevMd;
            DSPrntDlgEx.hDevNames      = (HGLOBAL)DSglDVNames;
            DSPrntDlgEx.hDC;
            DSPrntDlgEx.Flags          = PD_RETURNDC;
            DSPrntDlgEx.nPageRanges    = 0;//999;
            DSPrntDlgEx.nMaxPageRanges = sizeof(DSPprgs) / sizeof(PRINTPAGERANGE);
            DSPrntDlgEx.lpPageRanges   = DSlpPprgs;
            DSPrntDlgEx.nMinPage       = 1;
            DSPrntDlgEx.nMaxPage       = 999;
            DSPrntDlgEx.nCopies        = 1;
            DSPrntDlgEx.nStartPage     = START_PAGE_GENERAL;

            HRESULT DShPrintRes = ::PrintDlgEx(&DSPrntDlgEx);

            //以下、テスト用
            if (DShPrintRes == S_OK && DSPrntDlgEx.dwResultAction == PD_RESULT_PRINT)
             {
              ::MessageBeep(MB_OK);
                }

    2011年10月3日 2:53
  • 次に、

    >その割には最後のコード片は lpPageRanges に設定すらされなくなっていますが…。

    色々コードを書き換えましたが、私には分かりませんでした。それで、

    http://msdn.microsoft.com/en-us/library/ms646829(v=VS.85).aspx#print_property

    そのままコピー & ペーストで貼り付けて実行致しましたが、それでも

    「Windows によって DS.exe でブレークポイントが発生しました。

    ヒープが壊れていることが原因として考えられます。DS.exe または読み込まれた DLL にバグがあります。

    あるいは、DSLot.exe がフォーカスを持っているときに、ユーザーが F12 キーを押したことが原因として考えられます。

    可能であれば、出力ウィンドウに詳細な診断情報が表示されます。」

    と表示されてしまいます。これは、実行時毎回表示されます。


    MSDN のサンプルからコピーしたコードで実行しましたが、さすがに上記のようなエラーは発生しませんでした。
    Dominico Savio さんのコードには、今回の質問の箇所とは別のところに、致命的なバグがあるのではないでしょうか。

    因みに、自分で書いたコードは下記の通りですが、これは毎回ではないのですがアクセス違反が生じます。しかし、表示は、毎回されません。何卒、御教授下さいますよう、宜敷く御願い申し上げます。


    毎回アクセス違反が発生しないのは、たまたまエラー メッセージが出ないだけであって、アクセス違反は確実に発生しているはずです。

    hDevMode と hDevNames に有効な値を指定できないのであれば、NULL を指定すべきだという話も無視されてるし...。
    ちゃんと MSDN を読んだ上で戻したのであればいいんですがね。

    PRINTDLGEX structure (Windows)
    http://msdn.microsoft.com/en-us/library/ms646844(v=VS.85).aspx
    2011年10月3日 3:19
  • totojo様、回答有り難う御座います。

    >MSDN のサンプルからコピーしたコードで実行しましたが、さすがに上記のようなエラーは発生しませんでした。
    >Dominico Savio さんのコードには、今回の質問の箇所とは別のところに、致命的なバグがあるのではないでしょうか。

    新しいプロジェクトで印刷機能だけを付けて、またコピー & ペーストで実行してみました。さすがにブレーキポイント発生云々のエラーは出なかったのですが、HRESULTの戻り値はゼロでプリントダイアログは表示されませんでした。

    >hDevMode と hDevNames に有効な値を指定できないのであれば、NULL を指定すべきだという話も無視されてる

    >し...。
    >ちゃんと MSDN を読んだ上で戻したのであればいいんですがね。

    説明不足で申し訳御座いませんでした。実は、上記のレスの前にhDevMode と hDevNames を NULLに致しまして、実行致して居りました。結果は、HRESULTの戻り値がゼロでプリントダイアログは表示されませんでした。

    何卒、宜敷く御願い申し上げます。

    2011年10月3日 5:51
  • 新しいプロジェクトで印刷機能だけを付けて、またコピー & ペーストで実行してみました。さすがにブレーキポイント発生云々のエラーは出なかったのですが、HRESULTの戻り値はゼロでプリントダイアログは表示されませんでした。


    Flags に PD_RETURNDEFAULT が設定されているのなら分かりますが、PrintDlgEx が 0(S_OK) を返すのにダイアログが表示されないというのは、ちょっと分かりません。すみません。
    ちなみに、この場合は dwResultAction には何が入っているのでしょうか?
    2011年10月3日 9:57
  • totojo様、初心者の私に御付き合い下さいまして、誠に有り難う御座います。

    >Flags に PD_RETURNDEFAULT が設定されているのなら分かりますが、PrintDlgEx が 0(S_OK) を返すのにダイ>アログが表示されないというのは、ちょっと分かりません。すみません。
    >ちなみに、この場合は dwResultAction には何が入っているのでしょうか?

    ほとんどコピー & ペーストで下記のコードで確認致しましたところ、hResult はゼロで dwResultAction は、E_FAILが返ってきているみたいです。

    何卒、宜敷く御願い申し上げます。

    HRESULT DisplayPrintPropertySheet(HWND hWnd)
    {
        HRESULT hResult;
        PRINTDLGEX pdx = {0};
        LPPRINTPAGERANGE pPageRanges = NULL;
    
        // Allocate an array of PRINTPAGERANGE structures.
        pPageRanges = (LPPRINTPAGERANGE) GlobalAlloc(GPTR, 10 * sizeof(PRINTPAGERANGE));
        if (!pPageRanges)
            return E_OUTOFMEMORY;
    
        //  Initialize the PRINTDLGEX structure.
        pdx.lStructSize = sizeof(PRINTDLGEX);
        pdx.hwndOwner = hWnd;
        pdx.hDevMode = NULL;
        pdx.hDevNames = NULL;
        pdx.hDC = NULL;
        pdx.Flags = PD_RETURNDC | PD_COLLATE;
        pdx.Flags2 = 0;
        pdx.ExclusionFlags = 0;
        pdx.nPageRanges = 0;
        pdx.nMaxPageRanges = 10;
        pdx.lpPageRanges = pPageRanges;
        pdx.nMinPage = 1;
        pdx.nMaxPage = 1000;
        pdx.nCopies = 1;
        pdx.hInstance = 0;
        pdx.lpPrintTemplateName = NULL;
        pdx.lpCallback = NULL;
        pdx.nPropertyPages = 0;
        pdx.lphPropertyPages = NULL;
        pdx.nStartPage = START_PAGE_GENERAL;
        pdx.dwResultAction = 0;
        
        //  Invoke the Print property sheet.
        
        hResult = PrintDlgEx(&pdx);
    
        if ((hResult == S_OK) && pdx.dwResultAction == PD_RESULT_PRINT) 
        {
            // User clicked the Print button, so use the DC and other information returned in the 
            // PRINTDLGEX structure to print the document.
        }
    
    	else if (hResult == E_OUTOFMEMORY)
    		{
    			::MessageBox(NULL, _T("メモリが不足しています。"), _T("DS"), MB_OK);
    	    }
    
    	else if (hResult == E_INVALIDARG)
    		{
    			::MessageBox(NULL, _T("1 つ以上の引数が無効です。"), _T("DS"), MB_OK);
    	    }
    
    	else if (hResult == E_POINTER)
    		{
    			::MessageBox(NULL, _T("無効なポインタです。"), _T("DS"), MB_OK);
    	    }
    
    	else if (hResult == E_HANDLE)
    		{
    			::MessageBox(NULL, _T("無効なハンドルです。"), _T("DS"), MB_OK);
    	    }
    
    	else if (hResult == E_FAIL)
    		{
    		::MessageBox(NULL, _T("定義されていないエラーが発生しました。"), _T("DS"), MB_OK);
    	    }
    
        if (pdx.hDevMode != NULL) 
            GlobalFree(pdx.hDevMode); 
        if (pdx.hDevNames != NULL) 
            GlobalFree(pdx.hDevNames); 
        if (pdx.lpPageRanges != NULL)
            GlobalFree(pPageRanges);
    
        if (pdx.hDC != NULL) 
            DeleteDC(pdx.hDC);
    
        return hResult;
    }
    

    2011年10月3日 12:20
  •     if ((hResult == S_OK) && pdx.dwResultAction == PD_RESULT_PRINT) 
    
    ここのところで hResult が 0(S_OK) に、pdx.dwResultAction が 0x80004005(E_FAIL) になっているということでしょうか。
    PrintDlgEx 関数の仕様からすると、hResult が S_OK の場合には 
    pdx.dwResultAction の値は 0 ~ 2 になるはずらしいのですが。 
    2011年10月3日 16:07
  • totojo様、御世話に成ります。

    >ここのところで hResult が 0(S_OK) に、pdx.dwResultAction が 0x80004005(E_FAIL) になっているということ

    >でしょうか。

    >PrintDlgEx 関数の仕様からすると、hResult が S_OK の場合には pdx.dwResultAction の値は 0 ~ 2 になるは

    >ずらしいのですが。

    申し訳御座いません。書き間違いでした。hResult は S_OK  pdx.dwResultAction は 0です。 (ブレーキポイントを貼って確認)http://msdn.microsoft.com/ja-jp/library/cc410959.aspx それで、なぜか、ダイアログが表示されません。hResult = PrintDlgEx(&pdx);が実行し終えると、メッセージボックスは、E_FAILを表示致します。後、時々なのですが、メッセージボタンの OK を押した後アクセス違反が発生する時も御座います。状況と致しましては、この様な感じです。何卒、宜敷く御願い申し上げます。

    2011年10月3日 22:10
  • ちょっとよく分からないのですが、"定義されていないエラーが発生しました。" というメッセージ メッセージボックスが表示されたのであれば、hResult は S_OK でなくて E_FAIL なんではないでしょうか。
    ブレーク ポイントを置く位置が良くないように思います。PrintDlgEx 関数を呼び出した後の行にブレーク ポイントを置いていますか?

    PrintDlgEx が E_FAIL を返しているとすると、今までの話とは全然違う話になってしまいます。
    メッセージ ボックスを閉じるとアクセス違反が発生するということは、そもそも元のウィンドウも正しく作れているかどうかも怪しくなってきます。
    2011年10月4日 1:30
  • totojo様、御世話に成ります。
    >ちょっとよく分からないのですが、"定義されていないエラーが発生しました。" というメッセージ メッセージボックスが表示さ
    >れたのであれば、hResult は S_OK でなくて E_FAIL なんではないでしょうか。
    ウォッチで覗きますと、hResult も pdx.dwResultAction も 0 が入って居ります。
    >ブレーク ポイントを置く位置が良くないように思います。PrintDlgEx 関数を呼び出した後の行にブレーク ポイントを置い
    >ていますか?
    if ((hResult == S_OK) && pdx.dwResultAction == PD_RESULT_PRINT)
        {
            // User clicked the Print button, so use the DC and other information returned in the
            // PRINTDLGEX structure to print the document.
        }

    /*ここにブレークポイントを貼ってあります。*/else if (hResult == E_OUTOFMEMORY)
                  
                        /////--以下、省略---//////
    >PrintDlgEx が E_FAIL を返しているとすると、今までの話とは全然違う話になってしまいます。
    何故か、メッセージボックスは、E_FAIL を表示致します。
    >メッセージ ボックスを閉じるとアクセス違反が発生するということは、そもそも元のウィンドウも正しく作れているかどう
    >かも怪しくなってきます。
    今のところ、他の機能及びウインドウの表示等は、私の意図した通りに動作致して居りますが、もう一度よく見てみたいと思います。怪しいところと言えば、リッチエディットをサブクラス化しているところかな と 思います。
    何卒、宜敷く御願い申し上げます。
    2011年10月4日 4:35
  • ブレーク ポイントからトレースしていくと、どういう動きになるのでしょうか?
    「定義されていないエラーが発生しました。」のメッセージ ボックスを出すためには、「else if (hResult == E_FAIL)」の条件が真でなければならないはずですが、この条件判定をする時点で hResult の値はどうなっていますか?
    2011年10月5日 3:22
  • totojo様、御世話に成ります。

    >ブレーク ポイントからトレースしていくと、どういう動きになるのでしょうか?
    >「定義されていないエラーが発生しました。」のメッセージ ボックスを出すためには、「else if (hResult == E_FAIL)」の>条件が真でなければならないはずですが、この条件判定をする時点で hResult の値はどうなっていますか?

    誠に申し訳御座いませんが、何度動も作確認しようと致しましたが、毎回

    「'System.Runtime.InteropServices.SEHException' のハンドルされていない例外が DS.exe で発生しました。

    追加情報: 外部コンポーネントが例外をスローしました。」

    というメッセージが hResult = PrintDlgEx(&pdx); の所で 表示されまして、確認が取れませんでした。これは、新しくプロジェクトを作成致しまして、コピー & ペーストで貼り付けただけでも発生してしまいます。もしかしましたら、 VS2010そのものが不安定になっているのかもしれませんので、再インストールからやり直してみたいと思います。ただ、前回の動作では、hResult も  E_FAIL も 0(ゼロ)を示していたと記憶致して居ります。それでいて、"定義されていないエラーが発生しました。" というメッセージボックスが表示されてしまいまして、混乱してしまった次第です。因みに、hResult = PrintDlgEx(&pdx); の所で発生するエラー時の hResult の値は 0 が入って居りました。もし、これが成功して次に行けば他の数値が格納されるのかもしれません。

    以上の様な状況です。何卒、宜敷く御願い申し上げます。

    2011年10月5日 8:15
  • # 今さらで恐縮なんですが...。

    そもそも C++/CLI なんですか?(Windows フォーム アプリケーションとか)
    あと、Vista は 64 ビットだったりしますか?

    2011年10月5日 8:32
  • totojo様、御世話に成ります。

    >そもそも C++/CLI なんですか?(Windows フォーム アプリケーションとか)
    >あと、Vista は 64 ビットだったりしますか?

    VC++ で SDK のみです。.NET Frameworkは、使用致して居りません。

    共通言語基盤(CLI)は、なし です。

    VISTA は 32 ビットです。(ULTIMATE) SP2

    宜敷く御願い申し上げます。

    2011年10月5日 9:56
  • 不思議ですねぇ。
    'System.Runtime.InteropServices.SEHException' 例外は .NET Framework のランタイムが出しているように見えるのですけれども。
    その割には、発生しているのは DS.exe (おそらく Dominico Savio さんが作成されているアプリケーションの名前と思われる) だし。
    2011年10月5日 10:15
  • totojo様、御世話に成ります。

    <不思議ですねぇ。

    私も、不思議でなりません。

    試しに、他のマシンでもコピー & ペーストで貼り付けただけで、コードを実行してみました。そうしましたら、

    「この操作の実行中にエラーが発生しました。」 というダイアログが現れまして、その後に、「定義されていないエラーが発生しました。」 というメッセージボックスが現れる様な状況でした。この時の HRESULT と dwResultAction の値をウォッチで覗きますと、値は両方とも 0 でした。今現在は、この様な状況です。何かの参考に成りますでしょうか。何卒、宜敷く御願い申し上げます。

    2011年10月5日 10:35
  • 参考までに私がやってみたこと。

    1. Visual C++ 2010 Express で新規プロジェクトを作成する。(テンプレートは [Win32 プロジェクト])
    2. [Win32 アプリケーション ウィザード] の [アプリケーション設定] で [アプリケーションの種類] を [Windows アプリケーション] にして [完了] する。
    3. ここまでで一旦 [ビルド] して [デバッグ開始] する。

    [ファイル] と [ヘルプ] メニューだけがある白いウィンドウが起動します。起動したことを確認したら、アプリケーションを終了します。

    4. stdafx.h を開き、「#define WIN32_LEAN_AND_MEAN」という行をコメントアウトする。(commdlg.h をインクルードさせるため)
    5. http://msdn.microsoft.com/en-us/library/ms646829(VS.85).aspx をブラウザーで開き、サンプル コードの DisplayPrintPropertySheet 関数をごっそりコピーする。
    6. _tWinMain 関数があるソース コードを開き、コピーしたコードを _tWinMain 関数の直前にコピーする。(プロトタイプ宣言を書くのが面倒だったので...)
    7. WndProc 関数内の「case IDM_ABOUT:」の次にある「DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);」をコメントアウトする。
    8. コメントアウトした行と「break;」の間に「DisplayPrintPropertySheet(hWnd);」を入れる。

    これでアプリケーションの [ヘルプ] - [バージョン情報] を選択すると、印刷ダイアログが表示されるようになるはずです。
    [ヘルプ] - [バージョン情報] を利用したののは、なるべく余計なコードが入る隙を排除したいからです。

    [ビルド] して [デバッグ開始] します。同じく [ファイル] と [ヘルプ] メニューだけがある白いウィンドウが起動するはずです。
    [ヘルプ] - [バージョン情報] を選択します。すると、印刷ダイアログが表示されました。

    残念ながら手元には Vista がないので、Windows 7 と XP とでしか確認できていません。
    時間と実行環境が見つかれば、Vista でも試してみても良いですが、いつになるかは分かりません。
    2011年10月5日 11:16
  • totojo様、御世話に成ります。私の方も確認できました。やはり、私の書いたコードのどこかに悪い個所があるのだと思います。もう一度、全体的にコードを見直してみたいと思います。この件は、これでクローズさせて頂きたいと存じます。長々と、御付き合い下さいまして、誠に申し訳御座いませんでした。そして、本当に有り難うございました。
    2011年10月5日 12:55