none
サブクラス化したリストビューの項目を選択・変更した場合のメッセージを取得するには? RRS feed

  • 質問

  • こんにちは。
    Windows XP Pro SP3 + VC++ 2008で開発を行っています。

    リストビュー(複数選択不可)をサブクラス化し、そのリスト内のアイテムを選択(またはカーソルキーで変更)した場合に、選択されているカラムの情報を取得して処理をしたいと思っています。
    リストビューに対してドラッグ&ドロップをさせるためにサブクラス化して、以下のようなソースにしているのですが・・・

    LRESULT CALLBACK LVProc(HWND hList, UINT msg, WPARAM wParam, LPARAM lParam)
    {
     HDROP l_hDrop;             //ドラッグされたファイル情報のハンドル
     UINT l_FileNum;             //ドラッグされたファイル数
     WCHAR *l_FilePath = NULL;          //ドラッグされたファイルのパス
     UINT l_FilePathSize;           //↑のサイズ
     int l_nLoop;             //ループ用変数
     int l_nItem;             //アイテムをリストの最後にに追加するための変数
     LV_ITEM l_lvitem;            //リストビューに登録するアイテム
     LPNMHEADER l_pnmhdr;
     

     switch(msg)
     {
      //ファイルがドラッグされた場合
      case WM_DROPFILES:
       l_hDrop = (HDROP)wParam;
       l_FileNum = DragQueryFile(l_hDrop, 0xFFFFFFFF, NULL, 0);
       memset(&l_lvitem, 0, sizeof(LV_ITEM));
       l_nItem = ListView_GetItemCount(hList);
       for(l_nLoop = 0; l_nLoop < (int)l_FileNum; l_nLoop++)
       {
        l_FilePathSize = DragQueryFile(l_hDrop, l_nLoop, NULL, 0) + 1;
        l_FilePath = new WCHAR[l_FilePathSize];
        if(l_FilePath == NULL)
        {
         MessageBox(hList, L"バッファ不足のため、ファイルパスを取得できませんでした。", L"", MB_OK);
        }
        else
        {
         //バッファを取得したら、ファイルパスを格納
         DragQueryFile(l_hDrop, l_nLoop, l_FilePath, l_FilePathSize);
         
         //格納したら、リストビューに表示
         l_lvitem.mask = LVIF_TEXT;
         l_lvitem.pszText = l_FilePath;
         l_lvitem.iItem = l_nItem;
         l_lvitem.iSubItem = 0;
         l_nItem = ListView_InsertItem(hList, &l_lvitem);
         l_nItem++;
        }
        //使い終わったバッファを開放
        if(l_FilePath != NULL)
        {
         delete[] l_FilePath;
         l_FilePath = NULL;
        }

       }
       break;
      //マウスが左クリックされた場合
      case WM_NOTIFY:
       l_pnmhdr = (LPNMHEADER)lParam;
       switch(l_pnmhdr->hdr.code)
       {
        case NM_CLICK:
         MessageBox(hList, L"左クリック", L"デバッグ", MB_OK);
         break;
       }
       break;
      
     }

     return CallWindowProc(g_LVProc, hList, msg, wParam, lParam);

    }


    WM_NOTIFYメッセージまでは受けているようなのですが、NM_CLICKを受け取っていないようなのです。
    試しに、ここをカラムの部分をクリックされたときのメッセージに変更(NM_CLICK→HDN_ITEMCLICK)してみたところ、普通にメッセージを受け取り、メッセージボックスが表示されました。

    リストビューの1行が選択された事をメッセージとして受け取ることはできるのでしょうか?
    (また、上記ソースだとマウスのクリックだけですが、キーボードの上下などで選択行が変更されたときのメッセージもあわせて受け取るようにするには、どうすれば良いのでしょうか?)

    お手数をおかけしてたいへん申し訳ありませんが、ご教授のほどよろしくお願いいたします。

    2010年6月22日 8:58

回答

  • >プログラム自体はWin32 API(非MFC) で作成しています。
    WM_LBUTTONUP 時のマウス位置と、
    リストヘッダーの高さ、1行の高さ、スクロール位置などから
    算定するしかないと思います。

    • 回答としてマーク どらちん 2010年6月28日 2:06
    • 回答としてマークされていない どらちん 2010年6月28日 2:06
    • 回答としてマーク どらちん 2010年6月28日 2:06
    2010年6月28日 1:55

すべての返信

  • 念のため。
    WM_NOTIFY はコントロールの親ウィンドウに送付されるものですが、それを考慮してサブクラス化を行っているのでしょうか?
    (親ウィンドウへの通知を横取りしている?)

    参考
    http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200706/07060051.txt


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年6月22日 14:09
    モデレータ
  • Azuleanさん、ご返答ありがとうございます。

    サブクラス化した大元の理由は、ダイアログベースのプログラム上の、コントロールごとにファイルのドラッグ&ドロップを受け付けるようにしたかったため、サブクラス化しています。

    実は、その後本件の動作に関して四苦八苦しはじめ、記載いただいているURLに行き着き、WM_NOTIFYから、選択/変更/左クリックなどのメッセージを受けられるのかな?と思いガチャガチャやってみたのが、最初の書き込みで記載したソースなんです。

    やろうとしていることは
    ・リストビューににドラッグされたファイルのパスをリストに表示
         →サブクラス化することで実現

    ・このリストビュー(複数選択不可)のどれかを選択したときに、選択されたファイルの情報を別のコントロールに表示

    という事をしたいと思っているんです。
    (基本的には、jpegファイルのみをドラッグできるようにし、リストで選択されたファイルをPicture Controlに表示させるような動きをさせたいと思っています)

    2010年6月23日 3:48
  • え~と
    MyListView:public CListView{};なクラスにドロップを受け付けさせるだけなら
    MyListView::OnDragEnter()
    MyListView::OnDragLeave()
    MyListView::OnDragOver()
    MyListView::OnDrop()
    群をオーバーライドするだけのような気がしますが、その方法をとれなかった理由を
    聞かせてもらえるでしょうか。
    2010年6月23日 7:19
  • 中澤@失業者さん

    レスありがとうございます。

    すみません、最初の質問時に記載していませんでしたが・・・
    プログラム自体はWin32 API(非MFC) で作成しています。

    中澤@失業者さんが記載してくださったのはMFCですよね?
    (使ったことがないので・・・)

    なので、「理由」といわれると、「Win32 APIで作成しているから」になります(「なぜMFCを使わないのか?」と追加で質問されると「使ったことがないから(VC++をはじめた頃からSDKで開発をしていて、MFCがあまり好きではないから使わないようにしているため)」と言うことになっちゃいます・・・)

    2010年6月24日 8:13
  • >プログラム自体はWin32 API(非MFC) で作成しています。
    WM_LBUTTONUP 時のマウス位置と、
    リストヘッダーの高さ、1行の高さ、スクロール位置などから
    算定するしかないと思います。

    • 回答としてマーク どらちん 2010年6月28日 2:06
    • 回答としてマークされていない どらちん 2010年6月28日 2:06
    • 回答としてマーク どらちん 2010年6月28日 2:06
    2010年6月28日 1:55
  • 中澤@失業者 さん

    ご返答ありがとうございます。

    > WM_LBUTTONUP 時のマウス位置と、
    > リストヘッダーの高さ、1行の高さ、スクロール位置などから
    > 算定するしかないと思います。

    むむむ・・・やはりそれしかないんですね。
    了解しました!!

    頑張ってみます。

    2010年6月28日 2:07
  • LVM_SUBITEMHITTEST?
    jzkey
    2010年6月28日 11:27