none
CComboBox AddStringに失敗する原因 RRS feed

  • 質問

  • いつも大変お世話になっています。

    VS2008 C++ Win7 で開発しています。

    このフォーラムで質問させていただく内容ではないかもしれませんが、

    あるユーザーさんのWin7のノートパソコンに限り、納品したソフトで不具合が発生しています。

    (EPSON製でダメで、lenovo製の全く新しい環境でもダメだったそうです)

    現象は、コンボボックスでリストが表示されない、というものです(Typeにかかわらず)。

        err=((CComboBox*)GetDlgItem(IDC_ID_POS))->AddString((LPCTSTR)pDoc->stt[i].ctitle);

    この例では、コンボボックス作成時に、あらかじめ1件だけ、”(設定なし)”という文字列がセットされています。

    そこに、AddString()すると、"err"に”0”が返ります(ソートモードではありません)。

    err=0といことは、1行目のセットに成功した、という意味になりますよね?

    正しく動作しているPCでは、err=1が返り、その後順次戻り値は加算されていきますが、不具合PCでは、ずっとerr=0のままです。

    pos=((CComboBox*)GetDlgItem(IDC_ID_POS))->GetCount();
    ((CComboBox*)GetDlgItem(IDC_ID_POS))->GetLBText(pos-1,str);

    デバッグとして、上記値を取得したところ、常に

    pos=1

    str="(設定なし)"

    となります。

    このアプリにいくつかあるコンボボックスすべてで失敗しています(空のコンボボックスに追加していくパターンでも)。

    ただし、1つだけ、CComboBoxの派生クラスでのAddString()は成功しています。

    AddString()の前にResetContent()を必ず実行しなければならない、ということはないですよね?

    何か思い当たることがおありの方がおられましたら、ご教授よろしくお願いいたします。


    2014年3月18日 8:03

回答

  • 最初に確認しますが、MFCで良いですね。
    次に、DDXを使用していないようですが、どういった理由なのでしょう(質問)。

    さて、CWnd::GetDlgItem()はWin32SDKの同名関数のラッパー+αにすぎません、
    CComboBox::AddString()もSendMessage()しているだけです。
    戻り値が0以上である場合は、AddString()に成功しています。
    従って、次のように整理できます。

    1.AddString()に成功しているが、追加されないように見える。
     しかも先頭に追加されているという戻り値になっている。
    2.初期設定の”(設定なし)”だけが残されているように見える。
    3.CComboBoxの派生クラスではAddString()に成功する。
    4.上記例外を除き、全てのコンボボックスで同様の症状に見える。
    5.この症状は、特定の「ユーザー」で起きる。

    ということでよろしいでしょうか。

    まず、pDoc->stt[ i].ctitleが"(設定なし)"でないことを確認します。
    次に、

    A.コンボに追加した文字列は、どこかで削除されている可能性がある。
     "(設定なし)"だけが削除されていないのは、2つの可能性があり、
     A.1 全て削除されてから、あらためて"(設定なし)"が追加されているかも。
     A.2 インデックスの1ないし、それ以降のみが削除されているかも。

    という点について調べなければなりません。
    WM_NOTFYに応答して、何かしているところがないか調べてみてはどうでしょう。
    特に DeleteItem()、DeleteString()、ResetContent()などをしているところで
    ブレークして、AddString()時にそこを通過しないことを確認します。

    それらを全てパスした場合は、ウインドウクラス"ComboBox"が
    スーパークラス化されている可能性を考えなくてはなりませんが、
    割愛します。

    2014年3月18日 9:03

すべての返信

  • 可能であれば再現できる環境を借り受けて、リモートデバッグすることが解決の早道だと考えています。

    ところで、「(設定なし)」はコード上から追加されているのでしょうか?
    もし、そうであるなら、コード上からの追加は成功する事例と失敗する事例が存在することになります。その場合に考えられるのは、追加した後に誤って初期化するルートを通っていないかどうかでしょうか。(追加 → 初期化 → 追加 → 初期化を繰り返してしまうようなもの。開発環境ではなかったメッセージの流れ、ハンドラの呼ばれ方に起因?)

    2014年3月18日 8:57
    モデレータ
  • 最初に確認しますが、MFCで良いですね。
    次に、DDXを使用していないようですが、どういった理由なのでしょう(質問)。

    さて、CWnd::GetDlgItem()はWin32SDKの同名関数のラッパー+αにすぎません、
    CComboBox::AddString()もSendMessage()しているだけです。
    戻り値が0以上である場合は、AddString()に成功しています。
    従って、次のように整理できます。

    1.AddString()に成功しているが、追加されないように見える。
     しかも先頭に追加されているという戻り値になっている。
    2.初期設定の”(設定なし)”だけが残されているように見える。
    3.CComboBoxの派生クラスではAddString()に成功する。
    4.上記例外を除き、全てのコンボボックスで同様の症状に見える。
    5.この症状は、特定の「ユーザー」で起きる。

    ということでよろしいでしょうか。

    まず、pDoc->stt[ i].ctitleが"(設定なし)"でないことを確認します。
    次に、

    A.コンボに追加した文字列は、どこかで削除されている可能性がある。
     "(設定なし)"だけが削除されていないのは、2つの可能性があり、
     A.1 全て削除されてから、あらためて"(設定なし)"が追加されているかも。
     A.2 インデックスの1ないし、それ以降のみが削除されているかも。

    という点について調べなければなりません。
    WM_NOTFYに応答して、何かしているところがないか調べてみてはどうでしょう。
    特に DeleteItem()、DeleteString()、ResetContent()などをしているところで
    ブレークして、AddString()時にそこを通過しないことを確認します。

    それらを全てパスした場合は、ウインドウクラス"ComboBox"が
    スーパークラス化されている可能性を考えなくてはなりませんが、
    割愛します。

    2014年3月18日 9:03
  • ご回答、ありがとうございます。

    明日、半日程度環境をお借りすることになりました。

    「(設定なし)」は、あらかじめダイアログエディタでセットしています。コード上ではありません。

    最初は、1つのパソコンだけで発生する現象かと思っていたのですが、2台目でも起こったので・・・

    ただ担当の方のプライベートPCでは正常に動作しているようです。

    2014年3月18日 11:21
  • ご回答ありがとうございます。

    MFCを使用しています。

    2000年ごろに、クラスの知識もおぼつかないまま、作成したソフトですので

    何かとスマートではない組み方になっています。

    現象は、整理していただいた通りです。

    環境をお借りできることになったので、

    ・他のソフトではどうか?

    ・ResetContent()を追加したらどうなるか?

    ・ご指導いただいた追跡調査

    などを行ってみたい思います。

    2014年3月18日 11:30
  • ご指導、ありがとうございました。

    ユーザーさんのノートパソコンを送っていただいたのですが、こちらでは不具合が再現しませんでした。

    その後、ユーザーさんで使用されているマウスを使ったときのみ、起こる現象であることがわかりました。

    問題のマウスをお借りし、調査をする予定です。

    お時間を取っていただき、申し訳ありませんでした。

    今後とも、よろしくお願いいたします。

    2014年3月24日 2:01