mfc-ml

2005年08月

30

[mfc 51208] Re: get__NewEnumを実行した場合にCoUninitializeを実行するとAccessViolationが発生


社本@ワックです。

> tryブロックの中で変数を定義して、ブロックの外でCoUninitialize()を呼び
> だす方法で解決しました。

基本的に以下のタイミングでCOMの初期化と終了処理を呼び出すのが
いいと思いますよ。これなら、忘れないでしょうし。

  InitInstance : CoInitialize()
  ExitInstance : CoUninitialize()

ただし、マルチスレッドの場合には、そのスレッドごとにCOMの初期化と
終了処理が必要となります。


// 社本 明弘
// http://www.wac-jp.com/programmers/
// http://www.ailight.jp/blog/sha256/
// Microsoft MVP for VC++ (Oct 2003 - Oct 2005)
30

[mfc 51207] Re: cFileDialogでPLACESBARを消すには?


社本@ワックです。

> 1)CFileDialogのm_ofnの
>  lStructSizeに「OPENFILENAME_SIZE_VERSION_400」を定義する

手で設定しても間違いはないのですが、コンストラクタの
最後の引数(dwSize) に、OPENFILENAME_SIZE_VERSION_400を
指定することもできます。
CFileDialogのコンストラクタのコードを見ると、面白いですよ。

> 2)CFileDialogのm_ofnの
>  FlagsExに「OFN_EX_NOPLACESBAR」を定義する

このフラグは、プレースバーの対応していない過去のOSの場合、
恐らく定義されていないので、その場合には指定しないといった対応が、
必要だと思います。

まあ、きっと、大丈夫だとは思いますけどね。
でも、似たような事例で、WinNT4だとダメだった~とか、経験したことがあります。


// 社本 明弘
// http://www.wac-jp.com/programmers/
// http://www.ailight.jp/blog/sha256/
// Microsoft MVP for VC++ (Oct 2003 - Oct 2005)
30

[mfc 51206] Re: cFileDialogでPLACESBARを消すには?

中村です。
お世話になっております。

社本さま
>CFileDialogのコンストラクタを調べてみましょう。

調べに調べてやっとわかりました。(なんだか情けない…)
2つ方法が確認できて、どちらの方法でもうまくいきました。

1)CFileDialogのm_ofnの
 lStructSizeに「OPENFILENAME_SIZE_VERSION_400」を定義する

2)CFileDialogのm_ofnの
 FlagsExに「OFN_EX_NOPLACESBAR」を定義する

でした。

当初、1)を行った直後のコンパイル時にOPENFILENAME_SIZE_VERSION_400が
未定義と怒られましたが、WINVERその他が0x0400のままだったためと気づき
(脱力)
stdafx.hのWINVER、_WIN32_WINNT、ついでに_WIN32_IEを適正値に修正する
ことで正常にコンパイル出来ました。


MLアップ前にもかなり調べたつもりだったんですが、まだ努力が足りませんでした。
お騒がせしました。精進します…
30

[mfc 51205] Re: [mfc 51203] cFileDialogでPLACESBARを消すには?


社本@ワックです。

> このとき、左側に「デスクトップ」や「マイドキュメント」等のアイコンが
> 出てきますが(MLの過去ログによるとPLACESBARと呼ぶそうですが([mfc 
>  34462]))
> これを表示しないようにする方法はないでしょうか?

CFileDialogのコンストラクタを調べてみましょう。


// 社本 明弘
// http://www.wac-jp.com/programmers/
// http://www.ailight.jp/blog/sha256/
// Microsoft MVP for VC++ (Oct 2003 - Oct 2005)
30

[mfc 51204] Re: get__NewEnumを実行した場合にCoUninitializeを実行するとAccessViolationが発生

南波様、

お世話になります、質問元の今井です。

tryブロックの中で変数を定義して、ブロックの外でCoUninitialize()を呼び
だす方法で解決しました。

大変ありがとうございました。おかげでモヤモヤがスッキリしました。


On Tue, 30 Aug 2005 10:01:03 +0900
NANBA Toshiaki <n...@crest-cs.co.jp> wrote:

> 南波と申します。

> On 2005/08/29 23:11:53
> "[mfc 51201] get__NewEnumを実行した場合にCoUninitializeを実行するとAccessViolationが発生" Kenichi Imai wrote:

> >下記サンプルで、exit(0);コメントアウトし、
> >CoUninitialize()を1回だけコールするようにすると
> >AccessViolationが発生します。
> >CoUninitializeをコールしないようにするとAccessViolationは発生しません。

> 恐らく、インタフェースを参照したままの状態(COMを使用中の状態)で
> CoUninitialize()を呼んだからだと思います(そしてその後にCOMの機能
> を使おうとした)。

> #importを使っているのでスマートポインタを使ったプログラムになって
> いますが、この場合変数のスコープを抜けるときにインタフェースが開放
> されることになります。

> この場合で言えば、main関数から抜けるときにpIEnumの保持するインタフ
> ェースが開放されることになりますが、この段階では既にCoUninitialize()
> が呼び出された後になるので、その状態でCOMの機能を使うのはよろしく
> ないと思います。

> 解決方法としては、CoUninitialize()を呼び出す前に全てのインタフェー
> スポインタを開放してあげればよいはずです。一番手っ取り早いのは、try
> ブロックの中で変数を定義して、ブロックの外でCoUninitialize()を呼び
> 出せば良いと思います。

> -- 
> 南波 利明 <n...@crest-cs.co.jp>
記事検索
Amazon.co.jp
  • ライブドアブログ