No announcement yet.


  • Filter
  • Time
  • Show
Clear All
new posts

  • LVM_CREATEDRAGIMAGE for single cell

    First off I thank all those posts that demonstrate how to use the message LVM_CREATEDRAGIMAGE. I am trying to create a listview in which an item can be dragged from line X column Y to line X column Z. If anybody has an example of this, I would love to see it.

    It seems that this is possible as the %LVN_BEGINDRAG message is fired when dragging begins. I can get the initial coordinates from %WM_LBUTTONDOWN using %LVM_SUBITEMHITTEST. Then a hook can be put in the callback function to process the messages until %WM_LBUTTONUP. Am I wrong?

    My latest issue is trying to create a drag image for this process. It appears that the message of LVM_CREATEDRAGIMAGE only works for the entire row (the list view item). I am looking for just the cell (the sub-item). Is this possible? If so how? Any thoughts, ideas, etc are appreciated!
    Bill Scharf

  • #2
    Does it create the image for the entire row? Or just for column (subitem) zero?

    If it's just for subitem zero, maybe you could temporarily change the contents of that subitem, then change it back when the drag-drop operation completes?
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]


    • #3

      It creates an image of the entire row. I am using code mostly from Kev Peel's example:
      DIM PA              AS POINTAPI
      nStartId = SendMessage( hListView, %LVM_GETNEXTITEM, -1, MAKLNG( %LVNI_SELECTED, 0 ) ) 
      hImageList = SendMessage( hListView, %LVM_CREATEDRAGIMAGE, nStartId, BYVAL VARPTR( PA )
      There can be many columns and up to 96 rows. The idea is to drag and drop to anywhere visible from anywhere visible.
      Bill Scharf


      • #4
        I know there is a way to create an image from text. I just don't know what call it is (graphics is not my strnong suit)

        It would kind of be related to the way the Pb/Windows GRAPHICS functions allow you to create a blank bitmap, draw some text in it, then 'save as' a BMP file.

        Someone here will know how to do this, returning the needed handle to the image.

        Maybe (CreateBitmap + SelectObject + DrawText) ??

        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]


        • #5
          I thank you for your help. After hours of trying another way, I gave up and am trying this as a custom bitmap. I have tried various things for many, many hours and am stumped. I apologize that I am very ignorant of graphics in PB. If there were a PB graphics for dummies book, then I would buy it!
          this is my code--it seems to do nothing morethan draw a blank box at the cursor that can then be dragged around:

                 CASE %LVN_BEGINDRAG
                      '// Prepare an unique windows message to communicate with the parent dialog.
                      IF WM_LISTVIEW_ENDDRAG = 0 THEN WM_LISTVIEW_ENDDRAG = RegisterWindowMessage( "LISTVIEW_ENDDRAG" )
                      '// Fetch the selected item id.
                      nStartId = SendMessage( @pNMH.hdr.hWndFrom, %LVM_GETNEXTITEM, -1, MAKLNG( %LVNI_SELECTED, 0 ) )
                      IF nStartId < 0 THEN EXIT SELECT
                      '// A temporary hook is used on the control.
                      IF pPrevProc = 0 THEN
                          pPrevProc = SetWindowLong( @pNMH.hdr.hWndFrom, %GWL_WNDPROC, CODEPTR( LISTVIEW_HandleDrag ) )
                      END IF
                      '// No imagelist present, let's create one for a brief moment.
                      IF SendMessage( @pNMH.hdr.hWndFrom, %LVM_GETIMAGELIST, %LVSIL_NORMAL, BYVAL 0& ) = 0 THEN
                          hTempImgList = ImageList_Create( 0, 0, %ILC_COLORDDB, 0, 0 )
                          SendMessage @pNMH.hdr.hWndFrom, %LVM_SETIMAGELIST, %LVSIL_NORMAL, BYVAL hTempImgList
                      END IF
                      '// Create a drag image.
                     hImageList = SendMessage( @pNMH.hdr.hWndFrom, %LVM_CREATEDRAGIMAGE, nStartId, BYVAL VARPTR( PA ) )
             LOCAL hdc, hmemdc AS LONG
             LOCAL w&, h&, hBrush&
             LOCAL hbitmap, holdmemdcbitmap AS LONG
             LOCAL green AS DWORD
             LOCAL hwndclient AS LONG
             LOCAL trect AS rect
             hwndclient = @pNMH.hdr.hWndFrom
             ' Create bitmap in memory DC
             hDC = GetDC(hWndClient)
             hMemDC = CreateCompatibleDC(hDC)
             w& = 150'this will be the length of the column
             h& = 15 'this will be the height of the row
             hBitMap = CreateCompatibleBitMap(hDC, w&-1, h&)   'why the -1 is needed I just don't get?
             hOldMemDCBitMap= SelectObject(hMemDC, hBitMap)
             ' Use green as mask color
             Green = RGB(10, 255, 10)
             hBrush& = CreateSolidBrush(Green)
             SelectObject hmemDC, hBrush&
             tRect.nBottom = 15'tRect.nBottom - tRect.nTop
             tRect.nTop = 5
             tRect.nright = 25
             tRect.nleft = 5
             FillRect hmemDC, tRect, hBrush&
             DeleteObject hBrush&
              ImageList_Draw hImageList, 0, hMemDC, 5, 5, %ILD_MASK
              LOCAL zCap          AS ASCIIZ * 50
              zcap = "test"
           DrawText hDC, zCap, LEN(zCap), tRect, %DT_SINGLELINE OR %DT_CENTER
           'textout hMemDC, 300,300, zcap, len(zcap)
          SelectObject hMemDC, hOldMemDCBitMap
             ' Create the imagelist with the merged drag images
             hImageList = ImageList_Create(w&, h&, %ILC_COLOR OR %ILC_MASK, 0, 1)
             'mask it
             ImageList_AddMasked hImageList, hBitMap, Green
                 ' Clean up...
             ReleaseDC hWndClient, hDC
             DeleteDC hMemDC
             DeleteObject hBitMap
                      '// Destroy an evt. temp imagelist.
                      IF hTempImgList THEN
                          SendMessage @pNMH.hdr.hWndFrom, %LVM_SETIMAGELIST, %LVSIL_NORMAL, BYVAL 0&
                          ImageList_Destroy hTempImgList
                      END IF
                      '// Initiate dragging + make sure the image is positioned well.
          '            SendMessage @pNMH.hdr.hWndFrom, %LVM_GETITEMRECT, nStartId, BYVAL VARPTR( RItem )
          '            ImageList_BeginDrag hImageList, 0, @pNMH.ptAction.x, ( RItem.nBottom - RItem.nTop ) / 2
                      ImageList_BeginDrag hImageList, 0, -10, -5
                      '// Route all mousemessages to this control.
                      SetCapture @pNMH.hdr.hWndFrom
                      FUNCTION = 1
                  END SELECT
          This is based on many examples from this forum--I claim none of this as original and thank those who have come before me.

          I am sure I have many, many errors in this, but I just don't see them. If anybody has any thoughts or suggestions, I would appreciate it. I thought surely I was not the first person in history to want to drag and drop individual cells in a PB listview...maybe I am
          Last edited by Bill Scharf; 13 Mar 2008, 08:11 PM. Reason: code tags off
          Bill Scharf


          • #6
            I had a similar problem but with another twist - the listbox cell could contain several lines of text and I wanted to see them all before committing to the drag/drop. The solution, acheived with lots of help from Chris Boss, is described here. The example can be compiled. I hope it's some use to you.