none
ユニコードライブラリを使った場合のCreateDragImageの異常 RRS feed

  • 質問

  • .NET2005/VISTAです。

     

    2つのリストビュー間で、複数の列がある1行を、そっくりドラッグ&ドロップをする場合に、ユニコードにしてTCHAR型を使うと、文字列のイメージをうまく取得できません。

     

    マウスポインタをドラッグしている時に、1列目の文字列しかついてきません。

    しかも文字列の部分の背景色が半透明のグレイになってしまいます。

     

    たとえぱ、1行が3列で、入っている文字列が、aaa    bbb  ccc の行をドラッグしようとすると、マウスポインタに aaa  しかついてきません。

     

    アプリを新たに作るとき、アプリケーションウイザードで、「ユニコードライブラリを使用する」のチェックを外し、char型をつかうと、3列の文字列とも、きれいについてくるので、文字型の問題だと思うのです。

     

    コードは下記です。

    アドバイスをお願いいたします。

     

    リストビュー m_list1 から m_list2 にドラッグ&ドロップさせるコードで、m_list1をサブクラス化(CmyListCtrl)しています。


    CImageList* m_pDragImage;
    BOOL m_bDrag; 
    HTREEITEM m_hitemDrag;
    int iRow, nLen, nIndex;
    CPoint nPo, pPo;

    として

    void CmyListCtrl:SurprisenLButtonDown(UINT nFlags, CPoint point)
    {
        iRow = HitTest(point); 
        nLen = point.x;

        CListCtrl:SurprisenLButtonDown(nFlags, point);
    }

    void CmyListCtrl:SurprisenMouseMove(UINT nFlags, CPoint point)
    {
        POINT pt;
        if (m_bDrag) { 
            pt.x = point.x-nLen; pt.y = point.y;
            ClientToScreen( &pt );
            CImageList:Big SmileragMove(pt); 
        }

        CListCtrl:SurprisenMouseMove(nFlags, point);
    }

    void CmyListCtrl:SurprisenLvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
    {
        LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

        if( !(m_pDragImage = CreateDragImage(iRow, &pPo)) ) {return; }
        m_bDrag = TRUE;
        m_pDragImage->BeginDrag(0, CPoint(0, 0));
        ClientToScreen( &pPo );
        m_pDragImage->DragEnter(NULL, pPo);
        SetCapture();

        *pResult = 0;
    }

    2007年4月23日 1:19

すべての返信

  • 提示されているコードだけでは、ちょっと分かりませんが、
    以下のような文字列を取得するようなAPIを呼び出す場合に、
    文字数ではなくバイト数を呼び出したりしていませんか?


    BOOL GetHoge(LPCTSTR szHoge, int nLength);

    #if 0 // バイト数
    TCHAR szHoge[16] = { 0 };
    BOOL br = ::GetHoge(szHoge, sizeof(zHoge));
    #else // 文字数
    TCHAR szHoge[16] = { 0 };
    BOOL br = ::GetHoge(szHoge, (sizeof(zHoge) / sizeof(TCHAR)));
    #endif

    2007年4月23日 5:18
  • 社本 ワック さん、、ありがとうございます。

     

    BOOL GetHoge(LPCTSTR szHoge, int nLength); というような関数は作っていません。

     

    以前ネットで見つけたコードをもとにしているのですが、ユニコードを使わなければ、

     

    CreateDragImage(iRow, &pPo)) だけで、1行分の文字列がイメージに入るようです。

     

    掲載していないのは、OnLButtonUp(UINT nFlags, CPoint point) だけで、これはドロップの部分なので、

    関係ないと思います。

     

    あくまでイメージの問題だけで、ドロップは正しく行われています。


     


     

    2007年4月23日 7:55
  • リストのデータ表示はどうしています?もしかして、コールバック(LVN_GETDISPINFO)を使ってませんか?

    だとすると、そっち側の問題の可能性があります。

    LVN_GETDISPINFO/TVN_GETDISPINFO は結構ドキュメントがわかりづらいので、使い方を間違っている可能性があります(うちの中にもあって、別件で追ってて気がついて修正したことがある)。

     

    そうではないとすると、ちょっと思い当たる節はありません。

    2007年4月23日 12:14
  • とっちゃんさん、ありがとうございます。

     

    > コールバック(LVN_GETDISPINFO)を使ってませんか?

     

    使っていません。

    コードとしては、このほか、OnLButtonUpと、

    ***View.cppファイルに値の定義と、リストビューの描画のコードがあるだけです。

    「こういうものだ」という認識だったのですが。。。。。

     

    試しにOnLButtonUp関数の中身を全部コメントアウトしてみましたが、解決しません。

     

    ユニコードを使わない場合は、問題は起こりません。

     

     

    2007年4月23日 20:00
  •  ごえもん さんからの引用

    使っていません。

    コードとしては、このほか、OnLButtonUpと、

    ***View.cppファイルに値の定義と、リストビューの描画のコードがあるだけです。

    リストビューの描画のコードというのが気になります。

    とはいえ、UNICODE じゃなければ問題ないとすると、あんまり影響のある部分ではないのかもしれません。

    が、正直どこがどう影響するかなんてわかりませんので、疑わしきはすべて疑うの精神で、自分のコードを調査していく必要はあると思います。

     

    あとは、それと並行して、KB にそれらしいものがないかを探るなどですね。

    2007年4月24日 7:15
  • とっちゃんさん、ありがとうございます。

     

    。。。なかなかメッセージの文字サイズがうまくいきません。

     

    リストの描画のコードは下記です。

    というか、アプリのコードがこれで全部です。

     

    OnLButtonUpの中身は全部コメントアウトしました。

     

    試しに、TCHARでなく、wchar_tに置き換えてみましたが、やはりダメでした。

    どこか、おかしいでしょうか。

     

    wchar_t mych1[30];

    LVCOLUMN myColumn; myColumn.mask = LVCF_TEXT|LVCF_WIDTH;

    myColumn.cx = 90;

    myColumn.pszText = L"0列目"; m_list1.InsertColumn(0,&myColumn);

    myColumn.cx = 90;

    myColumn.pszText = L"1列目";

    m_list1.InsertColumn(1,&myColumn);

    myColumn.cx = 90;

    myColumn.pszText = L"2列目";

    m_list1.InsertColumn(2,&myColumn);

    static LVITEM myITEM;

    for (int i=0; i<=9; i++) { 

        myITEM.mask = LVIF_TEXT; myITEM.iItem = i; myITEM.iSubItem = 0;

        wcscpy_s( mych1, L"テスト0" ); myITEM.pszText = mych1;

        m_list1.InsertItem(&myITEM);

        myITEM.iItem = i; myITEM.iSubItem = 1;

        wcscpy_s( mych1, L"テスト1" ); myITEM.pszText = mych1; 

        m_list1.SetItem(&myITEM);

        myITEM.iItem = i; myITEM.iSubItem = 2;

        wcscpy_s( mych1, L"テスト2" ); myITEM.pszText = mych1;

        m_list1.SetItem(&myITEM); 
      }

    m_list1.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_TWOCLICKACTIVATE | LVS_EX_GRIDLINES);

    long state; state = ::GetWindowLong(m_list1.GetSafeHwnd(),GWL_STYLE);

    :Tongue TiedetWindowLong(m_list1.GetSafeHwnd(),GWL_STYLE,(state & ~LVS_TYPEMASK)|LVS_REPORT);

     

    2007年4月27日 0:50
  • 文字列セットの後で、

    myITEM.cchTextMax = 4;

    を追加してみては?

     

    あと、SetItem する場合の iItem は、InsertItem の戻り値にした方がいいですよ。

     

    なんで、スタイル設定だけAPIなのかも気になりますけど...それはたぶん影響ないでしょう。

     

    2007年4月27日 7:27
  • とっちゃんさん、ありがとうございます。

     

    myITEM.cchTextMax = 4;

     

    を置く位置はどこでしょうか。

     

    MSDNを見て、

     

    myITEM.pszText = mych1;

     

    の次かと思ったのですが、それだけでなく、順列組み合わせ算的に、あちこちに移動させてみましたが、

    うまくいきませんでした。

     

    2007年4月28日 22:50
  • myITEM.pszText = mych1; の次の行です。

    けど、駄目だったみたいですね。

     

    だとすると、リストビューコントロールそのものが抱えている不具合かもしれません。

     

    そうなると、方法としては、コードで望む画像を作り上げるということになります。それがいいか悪いかはともかくとして。

    あとは、文字列をあらかじめ渡すのではなく、コールバックで渡すようにするという方法もあります。面倒ではありますけど、こちらならうまくいく可能性もあるかも知れません。

     

    2007年5月1日 5:40