Announcement

Collapse
No announcement yet.

drag image of text

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • drag image of text

    I am trying (so far without much luck) to create a drag image from text. ListViews and Treeviews have a command to create the image from an item. I would like to replicate that behavior from a hard-coded text.

    This is what I have so far after a few days of working on and off this project:

    Code:
    #PBFORMS CREATED V1.51
    #COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #IF NOT %DEF(%COMMCTRL_INC)
        #INCLUDE "COMMCTRL.INC"
    #ENDIF
    GLOBAL SwitchtoHand AS LONG
    
    #PBFORMS END INCLUDES
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN CONSTANTS
    %IDD_DIALOG1 =  101
    %IDC_BUTTON1 = 1001
    #PBFORMS END CONSTANTS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
      STATIC fDrag, hfont, hfont2, hbmp AS LONG
      LOCAL  retval AS LONG
      LOCAL  rc AS RECT
      STATIC  pt AS POINTAPI
      STATIC himg AS LONG
    ''  STATIC himg2 AS LONG
      STATIC ptIcon AS POINTAPI
      STATIC cx AS LONG
      STATIC cy AS LONG
      STATIC hdc AS DWORD
      LOCAL  ps  AS PAINTSTRUCT
      LOCAL  szText AS ASCIIZ * 50
      STATIC memDC, memBMP AS LONG
      LOCAL oldBMP AS LONG
      LOCAL dtVal AS LONG
      LOCAL hBrush AS LONG
      STATIC imageNumToLoad AS LONG
    
        SELECT CASE AS LONG CBMSG
            CASE %wm_initdialog
                imageNumToLoad = 0
    
                hBrush = CreateSolidBrush(%WHITE)
    
                'himg = ImageList_Create(100, 16, %ILC_COLOR   , 1, 1)
                himg = ImageList_Create( 64, 64, %ILC_COLOR        , 1, 1 )
    
                ImageList_SetBKColor hImg, %CLR_NONE
    
                memDC = CreateCompatibleDC(GetDC(CBHNDL))
                memBMP = CreateBitmap(64, 64,1,1,BYVAL 0&)
                SetBKMode memDC, %TRANSPARENT
                oldBMP = SelectObject(memDC, memBMP)
                PatBlt memDC, 0, 0, 64, 64, %WHITENESS
                rc.nLeft = 0: rc.nTop = 0: rc.nRight = 64: rc.nBottom = 64
    
                szText = "Hello"
                        'this is using drawtext
                        'rc.nleft = 0
                        'rc.nTop = 0
                        'rc.nBottom = 64
                        'rc.nRight = 64
                        'dtVal = DrawText(memDC, szText, len(szText),rc, %DT_CENTER)
                TextOut memDC, 1, 1, szText, LEN(szText)
    
                retval =  ImageList_Add(himg, memBmp, 0)
    
                'other ways to add this bitmap--none seem to work
                'retval =  ImageList_AddMasked(himg2, memBmp, hBrush)
                'retval = ImageList_AddMasked( hImg, memBMP, GetSysColor(%COLOR_WINDOW))
    
                'Add the hand icon for testing
                retval  = LoadCursor( %NULL, BYVAL %IDC_HAND )
                ImageList_AddIcon himg, retval
                'clean up (commented out for now)
                'IF SelectObject(memDC, oldBMP) THEN
                '  DeleteObject hBmp
                'END IF
    
            CASE %wm_paint
                 'use this to get the image out of the ImageList for debugging
                  'retval = ImageList_Draw(himg, 0, memDC,0,0, %ILD_TRANSPARENT     )
    
              'show the image
              hDC = BeginPaint(CBHNDL, ps)
    
              BitBlt hDC, 10, 100, 64, 64, memDC, 0, 0, %SRCCOPY
    
              EndPaint CBHNDL, ps
    
              FUNCTION = 0
              EXIT FUNCTION
    
    
            CASE %wm_destroy
                ReleaseDC CBHNDL, hDC
    
            CASE %wm_ncactivate
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CBWPARAM THEN
                    ' Save control focus
                    hWndSaveFocus = GetFocus()
                ELSEIF hWndSaveFocus THEN
                    ' Restore control focus
                    SetFocus(hWndSaveFocus)
                    hWndSaveFocus = 0
                END IF
    
             CASE %wm_lbuttonup
                '// release the mouse
                    CALL ReleaseCapture()
                    ImageList_EndDrag()
    
             CASE %wm_lbuttondown
    
                '// determine the current mouse position
                pt.x = LOWRD( CBLPARAM)
                pt.y = HIWRD( CBLPARAM)
    
                '// determine the icon rectangle
                rc.nleft   = ptIcon.x
                rc.ntop    = ptIcon.y
                rc.nright  = ptIcon.x + 64
                rc.nbottom = ptIcon.y + 64
    
                '// evaluate if we clicked on the icon
                IF  PtInRect( rc, pt.x,pt.y ) = %TRUE THEN
    
                    '// calculate the offset from the upper left corner
                    cx = pt.x - ptIcon.x
                    cy = pt.y - ptIcon.y
    
                    '// get the imagelist handle
    '                himg = GetWindowLong( hwnd, %GWL_USERDATA)
    
                    '// convert the cursor position in screen coordinates
                    CALL ClientToScreen( CBHNDL, pt)
    
                    '// define the icon attributes
                    CALL ImageList_BeginDrag( himg, imageNumToLoad, cx, cy)
    
                    '// enter dragging mode
                    CALL ImageList_DragEnter( %NULL, pt.x, pt.y)
    
                    '// set the drag flag to TRUE
                    fDrag = 1
    
                    '// capture the mouse to drag the icon everywhere on the screen
                    CALL SetCapture( CBHNDL)
               END IF
    
    
            CASE %wm_mousemove
    
                '// skip if we are not dragging the icon
                IF fDrag = 1 THEN
    
                    pt.x = LOWRD(CBLPARAM)
                    pt.y = HIWRD(CBLPARAM)
    
                    '// convert the cursor position in screen coordinates
                    CALL ClientToScreen( CBHNDL, pt)
    
                    '// drag the icon
                    CALL ImageList_DragMove( pt.x, pt.y)
    
                END IF
    
            CASE %wm_command
                ' Process control notifications
                SELECT CASE AS LONG CBCTL
                    CASE %IDC_BUTTON1
                        IF CBCTLMSG = %bn_clicked OR CBCTLMSG = 1 THEN
                            IF switchtoHand = 0 THEN
                                CONTROL SET TEXT CBHNDL, %idc_button1, "switch to text"
                                switchtoHand = 1
                                imageNumToLoad = 1
                            ELSE
                                CONTROL SET TEXT CBHNDL, %idc_button1, "switch to hand"
                                switchtoHand = 0
                                imageNumToLoad = 0
                            END IF
                        END IF
    
                END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "Dialog1", 239, 270, 200, 120, %ws_popup OR _
            %ws_border OR %ws_dlgframe OR %ws_sysmenu OR %ws_clipsiblings OR _
            %ws_visible OR %ds_modalframe OR %ds_3dlook OR %ds_nofailcreate OR _
            %ds_setfont, %ws_ex_controlparent OR %ws_ex_left OR _
            %ws_ex_ltrreading OR %ws_ex_rightscrollbar, TO hDlg
        CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Switch to hand", 50, 55, 75, 55
    #PBFORMS END DIALOG
    
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    The user should be able to drag an image from the top left corner. This image is displayed on the right-hand side of the dialog. If you click the button, then the drag image will switch to be a hand icon. The purpose of the hand icon is to show that an image can get there--just not the text image. The purpose of the "hello" image on the right is to show that the image is indeed being drawn to the DC. The problem is that the image always shows up black. If I change:
    Code:
    himg = ImageList_Create( 64, 64, %ILC_COLOR            , 1, 1 )
    to
    Code:
    himg = ImageList_Create( 64, 64, %ILC_MASK, 1, 1 )
    then it will display the transparency I am looking for, but still no text.

    Any thought, advice, or prayers would be appreciated. InThanksAdvance!
    Bill Scharf

  • #2
    I suspect that this is not quite what you are seeking, but a method of dragging text, complete with compileable example, is shown in Chris Boss's post here: http://www.powerbasic.com/support/pb...light=dragging

    Comment


    • #3
      Thanks Chris! I have indeed looked at that example many times. It does not use drag images, but instead drags a child dialog. I was really looking to use drag images and take advantage of the transparency. The goal is to eventually have a cell-to-cell drag and drop for listviews. I have posted about that before with no luck. Now I am trying to do it without a listview at all.
      Bill Scharf

      Comment


      • #4
        If you have not totally given up on the listview control, the LVM_CREATEDRAGIMAGE message sure looks like it's worth a look.

        That 'appears' to only work with column zero, but... I don't see a reason you could not have a second listview control, invisible, and when you want to do your thing, copy the desired text from the source item/subitem (row, column) to Row 0, column 0 of your invisible helper listview control, the use LVM_CREATEDRAGIMAGE against that.

        Only thing which kind of scares me about this is... what kind of "image" is created if the text is not currently visible?

        Only one way to find out, I guess....
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          OK Bill, I think the problem is that you don't select the bmp out of the DC after you have drawn the text on the DC. I made a couple of changes - can remember quite what I changed, but the crux of it was:

          Code:
          retval =  ImageList_Add(himg, memBmp, 0)
          to
          Code:
          oldBMP = SelectObject(memDC, oldBMP)
          
          retval =  ImageList_Addmasked(himg, OldBmp, &H00c0c0c0)
          If you do this then it should spring to life - except that you have just restored the original (blank) bitmap, so your dummy image is not redisplayed by the WM_PAINT handler..

          BTW when you get an image or icon handle then put the image/icon into a list, you should (or so they say) use deleteobject to release the handle.
          Last edited by Chris Holbrook; 23 Jan 2009, 03:40 PM.

          Comment


          • #6
            Thank you Chris and MM!

            Chris,

            I tried your suggestion. I get a solid black drag image. The text may be drawing in black--but I cannot see it.hmmm...I bet I am just missing something dumb, but I don't see it. You are correct about the deleteObject. I was going to work on cleaning up, naming variables better, reducing static/globals, etc. when I coudl get something to work. I appreciate your help, but I may have a work-around (see below).


            MM,

            I had considered that, but I thought that might be too much of a hack. I doubted that it would work and didn't try. But, if you are suggesting it, it is worth a try! I thought of trying it with a hidden listView and then a listview of size 0,0. This is the result--click and drag from the top-right corner. It traps the click, sets the listview to the time (just something easy that was dynamic), and creates a drag image!!!! WHOOHOO!
            Code:
            #COMPILE EXE
            #DIM ALL
            '------------------------------------------------------------------------------
            '   ** Includes **
            '------------------------------------------------------------------------------
            #IF NOT %DEF(%WINAPI)
                #INCLUDE "WIN32API.INC"
            #ENDIF
            #IF NOT %DEF(%COMMCTRL_INC)
                #INCLUDE "COMMCTRL.INC"
            #ENDIF
            GLOBAL SwitchtoHand AS LONG
            GLOBAL hlvtime      AS LONG
            '------------------------------------------------------------------------------
            '------------------------------------------------------------------------------
            '   ** Constants **
            '------------------------------------------------------------------------------
            %IDD_DIALOG1 =  101
            %IDC_LVTIME  = 1002
            '------------------------------------------------------------------------------
            '------------------------------------------------------------------------------
            '   ** Declarations **
            '------------------------------------------------------------------------------
            DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
            DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
            '------------------------------------------------------------------------------
            '------------------------------------------------------------------------------
            '   ** Main Application Entry Point **
            '------------------------------------------------------------------------------
            FUNCTION PBMAIN()
                ShowDIALOG1 %HWND_DESKTOP
            END FUNCTION
            '------------------------------------------------------------------------------
            '------------------------------------------------------------------------------
            '   ** CallBacks **
            '------------------------------------------------------------------------------
            CALLBACK FUNCTION ShowDIALOG1Proc()
              STATIC fDrag, hfont, hfont2, hbmp AS LONG
              LOCAL  retval AS LONG
              LOCAL  rc AS RECT
              STATIC  pt AS POINTAPI
              STATIC himg AS LONG
            ''  STATIC himg2 AS LONG
              STATIC ptIcon AS POINTAPI
              STATIC cx AS LONG
              STATIC cy AS LONG
              STATIC hdc AS DWORD
              LOCAL  ps  AS PAINTSTRUCT
              LOCAL  szText AS ASCIIZ * 50
              STATIC memDC, memBMP AS LONG
              LOCAL oldBMP AS LONG
              LOCAL dtVal AS LONG
              LOCAL hBrush AS LONG
              STATIC imageNumToLoad AS LONG
              DIM PA              AS POINTAPI
            
                SELECT CASE AS LONG CBMSG
                    CASE %wm_initdialog
                        imageNumToLoad = 0
            
                        hBrush = CreateSolidBrush(%WHITE)
            
            
            himg = ImageList_Create( 0, 0, %ILC_COLORDDB, 0, 0 )
            'I don't know if this is needed, but it does not appear to be needed?
            'retval = ListView_SetImageList(hlvtime,himg, %LVSIL_NORMAL    )
                        memDC = CreateCompatibleDC(GetDC(CBHNDL))
                        memBMP = CreateBitmap(64, 64,1,1,BYVAL 0&)
                        SetBKMode memDC, %TRANSPARENT
                        oldBMP = SelectObject(memDC, memBMP)
                        PatBlt memDC, 0, 0, 64, 64, %whiteness
                        rc.nLeft = 0: rc.nTop = 0: rc.nRight = 64: rc.nBottom = 64
            
                        szText = "Hello"
            
                        TextOut memDC, 1, 1, szText, LEN(szText)
            
            himg =  ListView_CreateDragImage(hlvtime, 0,BYVAL VARPTR( PA )  )   'last parameter not needed...yet?
            
                        'clean up (commented out for now)
                        'IF SelectObject(memDC, oldBMP) THEN
                        '  DeleteObject hBmp
                        'END IF
            
                    CASE %wm_paint
                      'show the image
                      hDC = BeginPaint(CBHNDL, ps)
            
                      BitBlt hDC, 10, 100, 64, 64, memDC, 0, 0, %SRCCOPY
            
                      EndPaint CBHNDL, ps
            
                      FUNCTION = 0
                      EXIT FUNCTION
            
            
                    CASE %wm_destroy
                        ReleaseDC CBHNDL, hDC
            
                    CASE %wm_ncactivate
                        STATIC hWndSaveFocus AS DWORD
                        IF ISFALSE CBWPARAM THEN
                            ' Save control focus
                            hWndSaveFocus = GetFocus()
                        ELSEIF hWndSaveFocus THEN
                            ' Restore control focus
                            SetFocus(hWndSaveFocus)
                            hWndSaveFocus = 0
                        END IF
            
                     CASE %wm_lbuttonup
                        '// release the mouse
                            CALL ReleaseCapture()
                            ImageList_EndDrag()
            
                     CASE %wm_lbuttondown
            ListView_SetItemText(hLVtime, 0, 0, TIME$)
            himg =  ListView_CreateDragImage(hlvtime, 0,BYVAL VARPTR( PA )  )   'last parameter not needed...yet?
                        '// determine the current mouse position
                        pt.x = LOWRD( CBLPARAM)
                        pt.y = HIWRD( CBLPARAM)
            
                        '// determine the icon rectangle
                        rc.nleft   = ptIcon.x
                        rc.ntop    = ptIcon.y
                        rc.nright  = ptIcon.x + 64
                        rc.nbottom = ptIcon.y + 64
            
                        '// evaluate if we clicked on the icon
                        IF  PtInRect( rc, pt.x,pt.y ) = %TRUE THEN
            
                            '// calculate the offset from the upper left corner
                            cx = pt.x - ptIcon.x
                            cy = pt.y - ptIcon.y
            
                            '// get the imagelist handle
            '                himg = GetWindowLong( hwnd, %GWL_USERDATA)
            
                            '// convert the cursor position in screen coordinates
                            CALL ClientToScreen( CBHNDL, pt)
            
                            '// define the icon attributes
                            CALL ImageList_BeginDrag( himg, 0, cx, cy)
            
                            '// enter dragging mode
                            CALL ImageList_DragEnter( %NULL, pt.x, pt.y)
            
                            '// set the drag flag to TRUE
                            fDrag = 1
            
                            '// capture the mouse to drag the icon everywhere on the screen
                            CALL SetCapture( CBHNDL)
                       END IF
            
            
                    CASE %wm_mousemove
            
                        '// skip if we are not dragging the icon
                        IF fDrag = 1 THEN
            
                            pt.x = LOWRD(CBLPARAM)
                            pt.y = HIWRD(CBLPARAM)
            
                            '// convert the cursor position in screen coordinates
                            CALL ClientToScreen( CBHNDL, pt)
            
                            '// drag the icon
                            CALL ImageList_DragMove( pt.x, pt.y)
            
                        END IF
            
                    CASE %wm_command
                        ' Process control notifications
                        SELECT CASE AS LONG CBCTL
                        END SELECT
                END SELECT
            END FUNCTION
            '------------------------------------------------------------------------------
            
            '------------------------------------------------------------------------------
            '   ** Dialogs **
            '------------------------------------------------------------------------------
            FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                LOCAL lRslt, lstyle, x AS LONG
                LOCAL tLVC AS LV_COLUMN
                LOCAL tLVI   AS LV_ITEM
                LOCAL szBuf  AS ASCIIZ * 32
                LOCAL hDlg  AS DWORD
            
                DIALOG NEW hParent, "Dialog1", 239, 270, 300, 300, %ws_popup OR _
                    %ws_border OR %ws_dlgframe OR %ws_sysmenu OR %ws_clipsiblings OR _
                    %ws_visible OR %ds_modalframe OR %ds_3dlook OR %ds_nofailcreate OR _
                    %ds_setfont, %ws_ex_controlparent OR %ws_ex_left OR _
                    %ws_ex_ltrreading OR %ws_ex_rightscrollbar, TO hDlg
            'Add ListView
                 CONTROL ADD "SysListView32", hDlg, %IDC_LVTIME, "SysListView32_2", _
                    150, 150, 50, 45, %WS_CHILD OR %WS_VISIBLE  OR _
                    %LVS_REPORT OR %LVS_SHOWSELALWAYS OR %LVS_SINGLESEL, %WS_EX_CLIENTEDGE OR _
                    %WS_EX_LEFT OR %WS_EX_RIGHTSCROLLBAR
                 CONTROL HANDLE hDlg, %IDC_LVTIME TO hlvtime
                lStyle = ListView_GetExtendedListViewStyle(hlvtime)
                ListView_SetExtendedListViewStyle(hlvtime, lStyle OR %LVS_EX_GRIDLINES)
                ' Load column headers.
                tLVC.mask    = %LVCF_FMT OR %LVCF_TEXT OR %LVCF_SUBITEM
                tLVC.fmt     = %LVCFMT_LEFT
                tLVC.pszText = VARPTR(szBuf)
                szBuf       = "data"
                tLVC.iOrder = 0
                x=ListView_InsertColumn(hlvtime, 0, tLVC)
                ListView_SetColumnWidth(hlvtime, 0, 55)
                'add item to listview (to change the text latter)
                    tLVI.stateMask = %LVIS_FOCUSED
                    tLVI.pszText   = VARPTR(szBuf)
                    tLVI.iItem     = 0: tLVI.iSubItem = 0 : tLVI.lParam   = 0
                    szBuf = "hello"
                    tLVI.mask = %LVIF_TEXT OR %LVIF_PARAM OR %LVIF_STATE
                    ListView_InsertItem(hlvtime, tLVI)
                CONTROL SHOW STATE hdlg, %IDC_LVtime,  %SW_HIDE
            'end of Adding listview
                DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                FUNCTION = lRslt
            END FUNCTION
            This is not cleaned up and is pretty bad style. I hope to refine it and will post more when time allows. It appears that the drag image will work as long as the listview column is wide enough. So, for this to be very dymanic, I may have to dynamically adjust the size of the column. This works in Vista Business--now I have to go check Win 9x and up! I will report back as time allows!!! THANK YOU BOTH SO MUCH!
            Bill Scharf

            Comment


            • #7
              funny, it worked for me - must have changed something else.
              Here's "my" code
              Code:
              #compile exe
              #dim all
                  #include "WIN32API.INC"
                  #include "COMMCTRL.INC"
              global SwitchtoHand as long
              '------------------------------------------------------------------------------
              %IDD_DIALOG1 =  101
              %IDC_BUTTON1 = 1001
              '------------------------------------------------------------------------------
              declare callback function ShowDIALOG1Proc()
              declare function ShowDIALOG1(byval hParent as dword) as long
              #pbforms DECLARATIONS
              '------------------------------------------------------------------------------
              function pbmain()
                  ShowDIALOG1 %HWND_DESKTOP
              end function
              '------------------------------------------------------------------------------
              callback function ShowDIALOG1Proc()
                static fDrag, hfont, hfont2, hbmp as long
                local  retval as long
                local  rc as RECT
                static  pt as POINTAPI
                static himg as long
                static ptIcon as POINTAPI
                static cx as long
                static cy as long
                static hdc as dword
                local  ps  as PAINTSTRUCT
                local  szText as asciiz * 50
                static memDC, memBMP as long
                local oldBMP as long
                local dtVal as long
                local hBrush as long
                static imageNumToLoad as long
              
                  select case as long cbmsg
                      case %wm_initdialog
                          imageNumToLoad = 0
              
                          hBrush = CreateSolidBrush(%white)
                          himg = ImageList_Create( 64, 64, %ILC_MASK or %ILC_COLOR, 4, 0 )
              
                          ImageList_SetBKColor hImg, %CLR_NONE
              
                          memDC = CreateCompatibleDC(GetDC(cbhndl))
                          memBMP = CreateBitmap(64, 64, 1, 16,byval 0&)
                          SetBKMode memDC, %TRANSPARENT
                          oldBMP = SelectObject(memDC, memBMP)
                          PatBlt memDC, 0, 0, 64, 64, %WHITENESS
              
                          szText = "Oh yes it"
                          TextOut memDC, 0, 0, szText, len(szText)
                          sztext = "does!"
                          TextOut memDC, 0, 18, szText, len(szText)
                          oldBMP = SelectObject(memDC, oldBMP)
              
                          retval =  ImageList_Addmasked(himg, OldBmp, &H00c0c0c0)
              
                          deleteobject retval '? str$(retval)
                          'Add the hand icon for testing
                          retval  = LoadCursor( %NULL, byval %IDC_HAND )
                          dialog send cbhndl, %Wm_SETICON, %ICON_SMALL, retval
                          ImageList_AddIcon himg, retval
                          deleteobject retval
                          'clean up (commented out for now)
              
                      case %wm_paint
                           'use this to get the image out of the ImageList for debugging
                            'retval = ImageList_Draw(himg, 0, memDC,0,0, %ILD_TRANSPARENT     )
              
                        'show the image
                        hDC = BeginPaint(cbhndl, ps)
              
                        BitBlt hDC, 10, 100, 64, 64, memDC, 0, 0, %SRCCOPY' draw the text image at 10, 100
              
                        EndPaint cbhndl, ps
              
                        function = 0
                        exit function
              
              
                      case %wm_destroy
                          ReleaseDC cbhndl, hDC
              
                      case %WM_DROPFILES
                         beep
              
                       case %wm_lbuttonup
                          '// release the mouse
                              call ReleaseCapture()
                              ImageList_EndDrag()
              
                       case %wm_lbuttondown
              
                          '// determine the current mouse position
                          pt.x = lowrd( cblparam)
                          pt.y = hiwrd( cblparam)
              
                          '// determine the icon rectangle
                          rc.nleft   = ptIcon.x
                          rc.ntop    = ptIcon.y
                          rc.nright  = ptIcon.x + 64
                          rc.nbottom = ptIcon.y + 64
              
                          '// evaluate if we clicked on the icon
                          if  PtInRect( rc, pt.x,pt.y ) = %TRUE then
              
                              '// calculate the offset from the upper left corner
                              cx = pt.x - ptIcon.x
                              cy = pt.y - ptIcon.y
              
                              '// get the imagelist handle
              '                himg = GetWindowLong( hwnd, %GWL_USERDATA)
              
                              '// convert the cursor position in screen coordinates
                              call ClientToScreen( cbhndl, pt)
              
                              '// define the icon attributes
              '                call ImageList_BeginDrag( himg, imageNumToLoad, cx, cy)
                              call ImageList_BeginDrag( himg, imagenumtoload, cx, cy)
              
                              '// enter dragging mode
                              call ImageList_DragEnter( 0, pt.x, pt.y)
              
                              '// set the drag flag to TRUE
                              fDrag = 1
              
                              '// capture the mouse to drag the icon everywhere on the screen
                              call SetCapture( cbhndl)
                         end if
              
              
                      case %wm_mousemove
              
                          '// skip if we are not dragging the icon
                          if fDrag = 1 then
              
                              pt.x = lowrd(cblparam)
                              pt.y = hiwrd(cblparam)
              
                              '// convert the cursor position in screen coordinates
                              call ClientToScreen( cbhndl, pt)
              
                              '// drag the icon
                              call ImageList_DragMove( pt.x, pt.y)
              
                          end if
              
                      case %wm_command
                          ' Process control notifications
                          select case as long cbctl
                              case %IDC_BUTTON1
                                  if cbctlmsg = %bn_clicked or cbctlmsg = 1 then
                                      if switchtoHand = 0 then
                                          control set text cbhndl, %idc_button1, "switch to text"
                                          switchtoHand = 1
                                          imageNumToLoad = 1
                                      else
                                          control set text cbhndl, %idc_button1, "switch to hand"
                                          switchtoHand = 0
                                          imageNumToLoad = 0
                                      end if
                                  end if
              
                          end select
                  end select
              end function
              '------------------------------------------------------------------------------
              function ShowDIALOG1(byval hParent as dword) as long
                  local lRslt as long
                  local hDlg  as dword
              
                  dialog new hParent, "Chris's version", 239, 270, 200, 120, %ws_popup or _
                      %ws_border or %ws_dlgframe or %ws_sysmenu or %ws_clipsiblings or _
                      %ws_visible or %ds_modalframe or %ds_3dlook or %ds_nofailcreate or _
                      %ds_setfont, %ws_ex_controlparent or %ws_ex_left or _
                      %ws_ex_ltrreading or %ws_ex_rightscrollbar, to hDlg
                  control add button, hDlg, %IDC_BUTTON1, "drag text fr RH corner", 50, 55, 75, 55
              
                  dialog show modal hDlg, call ShowDIALOG1Proc to lRslt
              
                  function = lRslt
              end function

              Comment


              • #8
                I had considered that, but I thought that might be too much of a hack. I doubted that it
                would work and didn't try. But, if you are suggesting it, it is worth a try! I thought of
                trying it with a hidden listView and then a listview of size 0,0. This is the result--click
                and drag from the top-right corner. It traps the click, sets the listview to the time
                (just something easy that was dynamic), and creates a drag image!!!! WHOOHOO!
                Please, don't use that technique or post it in the source code forum. Enough said.

                Chris, there are problems with your code such as a resource leak and the destruction of the original image by ImageList_AddMasked.

                Bill, the following is a modified version of your code.
                Code:
                #PBFORMS CREATED V1.51
                #COMPILE EXE
                #DIM ALL
                
                '------------------------------------------------------------------------------
                '   ** Includes **
                '------------------------------------------------------------------------------
                #PBFORMS BEGIN INCLUDES
                #IF NOT %DEF(%WINAPI)
                    #INCLUDE "WIN32API.INC"
                #ENDIF
                #IF NOT %DEF(%COMMCTRL_INC)
                    #INCLUDE "COMMCTRL.INC"
                #ENDIF
                GLOBAL SwitchtoHand AS LONG
                
                #PBFORMS END INCLUDES
                '------------------------------------------------------------------------------
                
                '------------------------------------------------------------------------------
                '   ** Constants **
                '------------------------------------------------------------------------------
                #PBFORMS BEGIN CONSTANTS
                %IDD_DIALOG1 =  101
                %IDC_BUTTON1 = 1001
                #PBFORMS END CONSTANTS
                '------------------------------------------------------------------------------
                
                '------------------------------------------------------------------------------
                '   ** Declarations **
                '------------------------------------------------------------------------------
                DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
                DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                #PBFORMS DECLARATIONS
                '------------------------------------------------------------------------------
                
                '------------------------------------------------------------------------------
                '   ** Main Application Entry Point **
                '------------------------------------------------------------------------------
                FUNCTION PBMAIN()
                    ShowDIALOG1 %HWND_DESKTOP
                END FUNCTION
                '------------------------------------------------------------------------------
                
                '------------------------------------------------------------------------------
                '   ** CallBacks **
                '------------------------------------------------------------------------------
                CALLBACK FUNCTION ShowDIALOG1Proc()
                
                  STATIC  rcIcon          AS RECT
                  STATIC  hBmp            AS DWORD
                  STATIC  himg            AS DWORD
                  STATIC  imageNumToLoad  AS LONG
                  STATIC  fDrag           AS LONG
                
                  LOCAL   szText          AS ASCIIZ * 50
                  LOCAL   ps              AS PAINTSTRUCT  
                  LOCAL   pt              AS POINTAPI
                  LOCAL   hDC             AS DWORD
                  LOCAL   hMemDC          AS DWORD
                  LOCAL   hOldBmp         AS DWORD
                  LOCAL   hOldBrush       AS DWORD
                  LOCAL   hBmpCopy        AS DWORD
                  LOCAL   lOldBkMode      AS LONG
                  LOCAL   cxIcon          AS LONG
                  LOCAL   cyIcon          AS LONG
                  LOCAL   dx              AS LONG
                  LOCAL   dy              AS LONG
                  LOCAL   hCursor         AS DWORD
                  LOCAL   iImage          AS LONG
                
                    SELECT CASE AS LONG CBMSG
                        CASE %WM_INITDIALOG
                            imageNumToLoad = 0
                            ' Bounding rectangle of image on dialog
                            ' -------------------------------------
                            rcIcon.nLeft   = 10
                            rcIcon.nTop    = 100
                            rcIcon.nRight  = rcIcon.nLeft + 64
                            rcIcon.nBottom = rcIcon.nTop + 64
                            ' ------------------------------------- End Bounding rectangle
                
                            ' Create the drag image
                            ' ---------------------
                            cxIcon = rcIcon.nRight - rcIcon.nLeft
                            cyIcon = rcIcon.nBottom - rcIcon.nTop
                
                            hDC = GetDC(CBHNDL)
                            hMemDC = CreateCompatibleDC(hDC)
                            hBmp = CreateCompatibleBitmap(hDC, cxIcon, cyIcon)
                            ReleaseDC CBHNDL, hDC
                            hOldBmp = SelectObject(hMemDC, hBmp)
                            lOldBkMode = SetBkMode(hMemDC, %TRANSPARENT)
                            hOldBrush = SelectObject(hMemDC, CreateSolidBrush(%WHITE))
                            PatBlt hMemDC, 0, 0, cxIcon, cyIcon, %PATCOPY
                            DeleteObject SelectObject(hMemDC, hOldBrush)
                
                            SetTextColor hMemDC, GetSysColor(%COLOR_WINDOWTEXT)
                            szText = "Hello"
                            TextOut hMemDC, 1, 1, szText, LEN(szText)
                
                            SetBkMode hMemDC, lOldBkMode
                            SelectObject hMemDC, hOldBmp
                            DeleteDC hMemDC
                
                            himg = ImageList_Create(cxIcon, cyIcon, %ILC_COLOR32 OR %ILC_MASK, 2, 1)
                            ImageList_SetBkColor himg, %CLR_NONE
                            
                            ' ImageList_AddMasked modifies the original bitmap, therefore, a
                            ' copy of the bitmap is added since the original is used for the
                            ' image on the dialog.
                            hBmpCopy = CopyImage(hBmp, %IMAGE_BITMAP, 0, 0, %LR_COPYRETURNORG)
                            iImage = ImageList_AddMasked(himg, hBmpCopy, %WHITE)
                            DeleteObject hBmpCopy
                            ' -------------------------- End Create drag image
                
                            'Add the hand icon for testing
                            hCursor  = LoadCursor( %NULL, BYVAL %IDC_HAND )
                            iImage = ImageList_AddIcon(himg, hCursor)
                
                        CASE %WM_PAINT
                          'show the image
                          hDC = BeginPaint(CBHNDL, ps)
                
                          hMemDC = CreateCompatibleDC(hDC)
                          hOldBmp = SelectObject(hMemDC, hBmp)
                
                          cxIcon = rcIcon.nRight - rcIcon.nLeft
                          cyIcon = rcIcon.nBottom - rcIcon.nTop
                          BitBlt hDC, rcIcon.nLeft, rcIcon.nTop, cxIcon, cyIcon, hMemDC, 0, 0, %SRCCOPY
                
                          SelectObject hMemDC, hOldBmp
                          DeleteDC hMemDC
                
                          EndPaint CBHNDL, ps
                
                          FUNCTION = 0
                          EXIT FUNCTION
                
                
                        CASE %WM_DESTROY
                          IF hBmp THEN DeleteObject hBmp
                          IF himg THEN ImageList_Destroy himg
                
                        CASE %WM_NCACTIVATE
                            STATIC hWndSaveFocus AS DWORD
                            IF ISFALSE CBWPARAM THEN
                                ' Save control focus
                                hWndSaveFocus = GetFocus()
                            ELSEIF hWndSaveFocus THEN
                                ' Restore control focus
                                SetFocus(hWndSaveFocus)
                                hWndSaveFocus = 0
                            END IF
                
                         CASE %WM_LBUTTONUP
                            '// release the mouse
                                CALL ReleaseCapture()
                                ImageList_EndDrag()
                
                         CASE %WM_LBUTTONDOWN
                
                            '// determine the current mouse position
                            pt.x = LOWRD( CBLPARAM)
                            pt.y = HIWRD( CBLPARAM)
                
                            '// evaluate if we clicked on the icon
                            IF  PtInRect( rcIcon, pt.x,pt.y ) = %TRUE THEN
                                '// calculate the offset from the upper left corner
                                dx = pt.x - rcIcon.nLeft
                                dy = pt.y - rcIcon.nTop
                
                                '// convert the cursor position in screen coordinates
                                CALL ClientToScreen( CBHNDL, pt)
                
                                '// define the icon attributes
                                CALL ImageList_BeginDrag( himg, imageNumToLoad, dx, dy)
                
                                '// enter dragging mode
                                CALL ImageList_DragEnter( %NULL, pt.x, pt.y)
                
                                '// set the drag flag to TRUE
                                fDrag = 1
                
                                '// capture the mouse to drag the icon everywhere on the screen
                                CALL SetCapture( CBHNDL)
                           END IF
                
                
                        CASE %WM_MOUSEMOVE
                
                            '// skip if we are not dragging the icon
                            IF fDrag = 1 THEN
                
                                pt.x = LOWRD(CBLPARAM)
                                pt.y = HIWRD(CBLPARAM)
                
                                '// convert the cursor position in screen coordinates
                                CALL ClientToScreen( CBHNDL, pt)
                
                                '// drag the icon
                                CALL ImageList_DragMove( pt.x, pt.y)
                
                            END IF
                
                        CASE %WM_COMMAND
                            ' Process control notifications
                            SELECT CASE AS LONG CBCTL
                                CASE %IDC_BUTTON1
                                    IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                        IF switchtoHand = 0 THEN
                                            CONTROL SET TEXT CBHNDL, %IDC_BUTTON1, "switch to text"
                                            switchtoHand = 1
                                            imageNumToLoad = 1
                                        ELSE
                                            CONTROL SET TEXT CBHNDL, %IDC_BUTTON1, "switch to hand"
                                            switchtoHand = 0
                                            imageNumToLoad = 0
                                        END IF
                                    END IF
                
                            END SELECT
                    END SELECT
                END FUNCTION
                '------------------------------------------------------------------------------
                
                '------------------------------------------------------------------------------
                '   ** Dialogs **
                '------------------------------------------------------------------------------
                FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                    LOCAL lRslt AS LONG
                
                #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
                    LOCAL hDlg  AS DWORD
                
                    DIALOG NEW hParent, "Dialog1", 239, 270, 200, 120, %WS_POPUP OR _
                        %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR _
                        %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                        %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
                        %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                    CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Switch to hand", 50, 55, 75, 55
                #PBFORMS END DIALOG
                
                    DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                
                #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
                #PBFORMS END CLEANUP
                
                    FUNCTION = lRslt
                END FUNCTION
                Dominic Mitchell
                Phoenix Visual Designer
                http://www.phnxthunder.com

                Comment


                • #9
                  Question for Dominic - what is the advantage of creating the memDC in the WM_paint handler?

                  Comment


                  • #10
                    what is the advantage of creating the memDC in the WM_paint handler?
                    None in this case.
                    I did it that way to make it easier to see the connection between ImageList_AddMasked and the
                    bitmap in the memory device context.

                    Also, all those static variables need to go. Even this one
                    Code:
                    STATIC hWndSaveFocus AS DWORD
                    which is associated with code that is setting the focus where it really should not be set.

                    The code as is can never be used if multiple instances of the dialog can be created simultaneously in the same process.
                    Dominic Mitchell
                    Phoenix Visual Designer
                    http://www.phnxthunder.com

                    Comment


                    • #11
                      I think below code
                      Code:
                       
                              CASE %WM_MOUSEMOVE
                                  '// skip if we are not dragging the icon
                                  IF fDrag = 1 THEN
                                      pt.x = LoWRD(CbLParam)
                                      pt.y = HiWRD(CbLParam)
                      should be
                      Code:
                       
                              CASE %WM_MOUSEMOVE
                                  '// skip if we are not dragging the icon
                                  IF fDrag = 1 THEN
                                      pt.x = LoInt(CbLParam)
                                      pt.y = HiInt(CbLParam)
                      otherwise when mouse is above or left to the window (negative values of mouse position), image is not on screen.

                      Eros
                      Last edited by Eros Olmi; 24 Jan 2009, 07:49 AM.
                      thinBasic programming language
                      Win10 64bit - 8GB Ram - i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB

                      Comment


                      • #12
                        Originally posted by Dominic Mitchell View Post
                        None in this case.
                        I did it that way to make it easier to see the connection between ImageList_AddMasked and the bitmap in the memory device context.
                        Ah.

                        Originally posted by Dominic Mitchell View Post
                        Code:
                        STATIC hWndSaveFocus AS DWORD
                        which is associated with code that is setting the focus where it really should not be set.
                        Yes, that one comes for free with every PBFORMS, which is where Bill started from.

                        Originally posted by Dominic Mitchell View Post
                        [The code as is can never be used if multiple instances of the dialog can be created simultaneously in the same process.
                        That would be a good discipline for us lazy programmers.

                        Comment


                        • #13
                          thank you!!!

                          After a long day of my 20-month old injuring himself and us rushing him over the mountain to the doctor this is a great relief!!! My son is going to be ok and this code works very, very well! I cannot thank you guys enough, specially Dominic!

                          I had a basic misunderstanding of masking bitmaps along with a bunch of coding errors. Thank you for your patience as I learn.
                          Bill Scharf

                          Comment

                          Working...
                          X