FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour Sample to make a drop into btnbmp
Posts: 7317
Joined: Thu Oct 18, 2012 07:17 PM
Sample to make a drop into btnbmp
Posted: Tue May 05, 2026 01:03 PM

I Wish a test sample to make drag and drop from a btnbmp to another

I made / @ nTop, nLeft BTNBMP oBtn ...

oBtn:bDragBegin := { |nRow, nCol, nFlags| SetDropInfo( oBtn ) }

And for the btnbmp receive

::oBtn:bDropOver := { |uDropInfo, nRow, nCol, nFlags| ::HandleDrop( uDropInfo ) }

But not run ok

Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Sample to make a drop into btnbmp
Posted: Tue May 05, 2026 01:09 PM

Dear Silvio,

// Drag & Drop between two BtnBmp controls  

#include "FiveWin.ch"  
  

function Main()  
  

   local oWnd, oCursor, oBtn1, oBtn2  
  

   // You MUST define a drag cursor  

   DEFINE CURSOR oCursor HAND  
  

   DEFINE WINDOW oWnd TITLE "BtnBmp Drag & Drop Test"  
  

   // Catch drops that miss the target  

   oWnd:bDropOver = { || MsgAlert( "Dropped outside target!" ) }  
  

   // Source button  

   @ 3, 3 BTNBMP oBtn1 OF oWnd ;  

      PROMPT "Drag Me" ;  

      SIZE 100, 40  
  

   oBtn1:oDragCursor = oCursor                          // <-- Required!  

   oBtn1:bDragBegin  = { | nRow, nCol, nFlags | ;  

                         SetDropInfo( "Hello from Btn1" ) }  
  

   // Target button  

   @ 3, 20 BTNBMP oBtn2 OF oWnd ;  

      PROMPT "Drop Here" ;  

      SIZE 100, 40  
  

   oBtn2:bDropOver = { | uDropInfo, nRow, nCol, nFlags | ;  

                       MsgInfo( "Received: " + uDropInfo ) }  
  

   ACTIVATE WINDOW oWnd  
  

return nil
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 7317
Joined: Thu Oct 18, 2012 07:17 PM
Re: Sample to make a drop into btnbmp
Posted: Wed May 06, 2026 09:28 PM

Antonio,
I must make a cursor on line from btnbmp how I can make I try with

oCur := TCursor():NewBmp( oBtn:hBitmap1, Int(nSize/2), Int(nSize/2) )

but not run

// Drag & Drop between two BtnBmp controls
#include "FiveWin.ch"

function Main()

   local oWnd, oCursor, oBtn1, oBtn2

   // You MUST define a drag cursor
   DEFINE CURSOR oCursor HAND

   DEFINE WINDOW oWnd TITLE "BtnBmp Drag & Drop Test"

   // Catch drops that miss the target
   oWnd:bDropOver = { || MsgAlert( "Dropped outside target!" ) }

   // Source button
   @ 3, 3 BTNBMP oBtn1 OF oWnd ;
      PROMPT "Drag Me" ;
      SIZE 100, 40
   oBtn1:bClrGrad := { |lIn| If(!lIn, {{0.5, CLR_WHITE, CLR_RED}}, {{0.5, CLR_HGRAY, CLR_GREEN}})}
   *oBtn1:oDragCursor = oCursor
   oBtn1:oDragCursor := CreaCursorfromButton( oBtn1, 100 )
   oBtn1:bDragBegin  = { | nRow, nCol, nFlags | ;
                         SetDropInfo( "Hello from Btn1" ) }

   // Target button
   @ 3, 400 BTNBMP oBtn2 OF oWnd ;
      PROMPT "Drop Here" ;
      SIZE 100, 40

   oBtn2:bDropOver = { | uDropInfo, nRow, nCol, nFlags | ;
                       MsgInfo( "Received: " + uDropInfo ) }

   ACTIVATE WINDOW oWnd

   return nil


 FUNCTION CreaCursorfromButton( oBtn, nSize )
   LOCAL oCur
   oCur := TCursor():NewBmp( oBtn:hBitmap1, Int(nSize/2), Int(nSize/2) )
RETURN oCur

now the cursor is allways 🚫 why ?

I tried to make

 FUNCTION CreaCursorfromButton( aGrad, nSize )

   LOCAL oBmp
   LOCAL oCur

   DEFINE BITMAP oBmp SIZE nSize, nSize

   GradientFill(  oBmp:hDC, ;
      0, 0, ;
      nSize, nSize, ;
      aGrad )

   oCur := TCursor():New()

   oCur:NewBmp( ;
      oBmp, ;
      Int( nSize / 2 ), ;
      Int( nSize / 2 ) )

RETURN oCur

because the method of tcursor class NewBmp want hpalette or hbimap but I on btnbmp not have bitmap but gradient

Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Sample to make a drop into btnbmp
Posted: Thu May 07, 2026 02:24 AM

Dear Silvio,

The problem is clear from looking at the TCursor:NewBmp() method: 0-cite-0

When you pass oBtn (a TBtnBmp), it reads oBtn:hBitmap1. But since your button uses only a gradient (bClrGrad) and has no bitmap file, hBitmap1 is 0. The condition if hBitMap != 0 fails, so no cursor is created and hCursor stays at 0 โ€” which makes Windows show the 🚫 (no-drop) cursor.

The fix: You need to first render the gradient into a bitmap, then pass that bitmap handle (as a numeric) to NewBmp(). Here's a working approach based on the GradientBmp pattern used in FiveWin's own brush.prg: 0-cite-1

Code (harbour): Select all Collapse
FUNCTION CreaCursorfromButton( oBtn, nSize )

   LOCAL oCur
   LOCAL hDC, hDC2, hBmp, hBmpOld
   LOCAL aGrad

   // Get the gradient colors from the button
   aGrad := Eval( oBtn:bClrGrad, .F. )  // .F. = not pressed/mouse-over state

   // Create a compatible bitmap and paint the gradient into it
   hDC      := GetDC( 0 )
   hDC2     := CreateCompatibleDC( hDC )
   hBmp     := CreateCompatibleBitMap( hDC, nSize, nSize )
   hBmpOld  := SelectObject( hDC2, hBmp )

   GradientFill( hDC2, 0, 0, nSize, nSize, aGrad )

   SelectObject( hDC2, hBmpOld )
   DeleteDC( hDC2 )
   ReleaseDC( 0, hDC )

   // Now create the cursor passing the bitmap HANDLE (numeric)
   oCur := TCursor():NewBmp( hBmp, Int( nSize / 2 ), Int( nSize / 2 ) )

   // Clean up the bitmap after cursor is created
   DeleteObject( hBmp )

RETURN oCur

Key points:

  1. NewBmp() accepts a numeric value (bitmap handle) directly โ€” see line 136-137 of cursor.prg: elseif ValType( oBitmap ) == "N" โ†’ hBitMap := oBitmap. So you can pass the raw hBmp handle. 0-cite-2

  2. GradientFill() in FiveWin accepts the same array format that bClrGrad returns (e.g. {{0.5, CLR_WHITE, CLR_RED}}). 0-cite-3

  3. You must create a real bitmap in memory, paint the gradient onto it, then pass its handle. The CreateBmpCursor() C function reads the pixel data from the bitmap to build the AND/XOR cursor masks. 0-cite-4

If you also want the button's text drawn on the cursor, you could additionally call DrawText() on hDC2 before deselecting the bitmap.

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 7317
Joined: Thu Oct 18, 2012 07:17 PM
Re: Sample to make a drop into btnbmp
Posted: Thu May 07, 2026 07:28 AM

Dear Antonio,
In my tests I also tried your same solution but it didn't work for me. I tried your function and it doesn't work in fact when I drag from button A to button B the cursor becomes a red circle with a slash 🚫

Please try this test

// Drag & Drop between two BtnBmp controls
#include "FiveWin.ch"  
  

function Main()
  

   local oWnd, oCursor, oBtn1, oBtn2  

   local aGradRosso := ;
      { { 0.5, CLR_WHITE, CLR_RED } }

   // You MUST define a drag cursor
   DEFINE CURSOR oCursor HAND  
  

   DEFINE WINDOW oWnd TITLE "BtnBmp Drag & Drop Test"  
  

   // Catch drops that miss the target  

   oWnd:bDropOver = { || MsgAlert( "Dropped outside target!" ) }  
  

   // Source button  

   @ 3, 3 BTNBMP oBtn1 OF oWnd ;  

      PROMPT "Drag Me" ;  

      SIZE 40, 40


 oBtn1:bClrGrad := ;
      { |lIn| ;
         If( ! lIn, ;
            aGradRosso, ;
            { { 0.5, CLR_HGRAY, CLR_WHITE } } ) }
  

   //oBtn1:oDragCursor = oCursor                          // <-- Required!

  oBtn1:oDragCursor = CreaCursorfromButton( oBtn1, 40 )

   oBtn1:bDragBegin  = { | nRow, nCol, nFlags | ;
                         SetDropInfo( "Hello from Btn1" ) }  

   // Target button
   @ 3, 220 BTNBMP oBtn2 OF oWnd ;  

      PROMPT "Drop Here" ;  

      SIZE 100, 40
  

   oBtn2:bDropOver = { | uDropInfo, nRow, nCol, nFlags | ;  

                       MsgInfo( "Received: " + uDropInfo ) }

   ACTIVATE WINDOW oWnd  

return nil
//--------------------------------------------------------------------//
FUNCTION CreaCursorfromButton( oBtn, nSize )

   LOCAL oCur
   LOCAL hDC, hDC2, hBmp, hBmpOld
   LOCAL aGrad

   // Get the gradient colors from the button
   aGrad := Eval( oBtn:bClrGrad, .F. )  // .F. = not pressed/mouse-over state

   // Create a compatible bitmap and paint the gradient into it
   hDC      := GetDC( 0 )
   hDC2     := CreateCompatibleDC( hDC )
   hBmp     := CreateCompatibleBitMap( hDC, nSize, nSize )
   hBmpOld  := SelectObject( hDC2, hBmp )

   GradientFill( hDC2, 0, 0, nSize, nSize, aGrad )

   SelectObject( hDC2, hBmpOld )
   DeleteDC( hDC2 )
   ReleaseDC( 0, hDC )

   // Now create the cursor passing the bitmap HANDLE (numeric)
   oCur := TCursor():NewBmp( hBmp, Int( nSize / 2 ), Int( nSize / 2 ) )

   // Clean up the bitmap after cursor is created
   DeleteObject( hBmp )

RETURN oCu
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 7317
Joined: Thu Oct 18, 2012 07:17 PM
Re: Sample to make a drop into btnbmp
Posted: Thu May 07, 2026 10:55 AM

Antonio,

If I have a bmp sample dragcursor.bmp How I can insert it as cursor ?

i TRIED THIS BUT NOT RUN

#include "FiveWin.ch"

function Main()
   local oWnd, oBtn1, oBtn2  

   local aGradRosso := { { 0.5, CLR_WHITE, CLR_RED } }

   DEFINE WINDOW oWnd TITLE "BtnBmp Drag & Drop Test"

   @ 3, 3 BTNBMP oBtn1 OF oWnd PROMPT "Drag Me" SIZE 40, 40

   oBtn1:bClrGrad := { |lIn| If( ! lIn, aGradRosso, { { 0.5, CLR_HGRAY, CLR_WHITE } } ) }

   

   oBtn1:oDragCursor = CreaCursorfromButton( oBtn1, 40 )


   oBtn1:bDragBegin = { | nRow, nCol, nFlags | SetDropInfo( "Hello from Btn1" ) }

   @ 3, 220 BTNBMP oBtn2 OF oWnd PROMPT "Drop Here" SIZE 100, 40
   oBtn2:bDropOver = { | uDropInfo | MsgInfo( "Received: " + uDropInfo ) }

   ACTIVATE WINDOW oWnd

return nil

//--------------------------------------------------------------------//

//--------------------------------------------------------------------//
FUNCTION CreaCursorfromButton( oBtn, nSize )
   LOCAL oCur
   LOCAL hBmpCustom
   LOCAL cBmpFile := "dragcursor.bmp"
   LOCAL aGrad, aColors

 
   IF oBtn:bClrGrad != NIL
      aGrad := Eval( oBtn:bClrGrad, .F. )
      aColors := { aGrad[1][2], aGrad[1][3] }
   ELSE
      aColors := { CLR_WHITE, CLR_BLUE }
   ENDIF

   

   hBmpCustom := FW_MakeYourBitmap( nSize, nSize, {|hDC,w,h| ;
                    FW_Box( hDC, { 0,0,h,w }, CLR_BLACK, aColors[2] ) } )

  

   FW_SaveImage( hBmpCustom, cBmpFile )
   


   DeleteObject( hBmpCustom )

  

   oCur := TCursor():NewBmp( cBmpFile, nSize/2, nSize/2 )

RETURN oCur
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 7317
Joined: Thu Oct 18, 2012 07:17 PM
Re: Sample to make a drop into btnbmp
Posted: Thu May 07, 2026 11:30 AM

i NOT SEE THE CURSOR

i TRIED WITH DEFINE CURSOR oCursor FILE "dragcursor.BMP"

#include "FiveWin.ch"
  

function Main()
  

   local oWnd, oCursor, oBtn1, oBtn2

   // You MUST define a drag cursor  

   DEFINE CURSOR oCursor FILE "dragcursor.BMP" 

   DEFINE WINDOW oWnd TITLE "BtnBmp Drag & Drop Test"  
  

   // Catch drops that miss the target
   oWnd:bDropOver = { || MsgAlert( "Dropped outside target!" ) }  
  

   // Source button
   @ 3, 3 BTNBMP oBtn1 OF oWnd ;  

      PROMPT "Drag Me" ;  

      SIZE 100, 40

   oBtn1:oDragCursor = oCursor                          // <-- Required!
   oBtn1:bDragBegin  = { | nRow, nCol, nFlags | ;
                         SetDropInfo( "Hello from Btn1" ) }

   // Target button
   @ 3, 420 BTNBMP oBtn2 OF oWnd ;
      PROMPT "Drop Here" ;
      SIZE 100, 40

   oBtn2:bDropOver = { | uDropInfo, nRow, nCol, nFlags | ;
                       MsgInfo( "Received: " + uDropInfo ) }

   ACTIVATE WINDOW oWnd

return nil
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Sample to make a drop into btnbmp
Posted: Thu May 07, 2026 06:19 PM

Dear Silvio,

Cause: DEFINE CURSOR FILE in source/classes/cursor.prg:99-104 only loads .cur or .ico via LoadCursorFromFile. Other
extensions fall through to LoadCursor( GetResources(), ... ), which looks up a resource by name โ€” "dragcursor.BMP" is
not a resource โ†’ hCursor = 0 โ†’ no cursor shown.

.BMP is not a valid cursor format (no hotspot info).

3 fixes:

  1. Convert to .CUR (simplest)

    Online editor or ImageMagick: magick dragcursor.bmp dragcursor.cur. Then:
    DEFINE CURSOR oCursor FILE "dragcursor.CUR"

  2. Use NewBmp with explicit hotspot
    local oBmp, oCursor
    DEFINE BITMAP oBmp FILE "dragcursor.BMP"
    oCursor := TCursor():NewBmp( oBmp, 0, 0 ) // nHotRow=0, nHotCol=0
    oBtn1:oDragCursor := oCursor

  3. Built-in DRAG predef (no file needed)
    DEFINE CURSOR oCursor DRAG

    Built-in drag cursor via GetCursorDrag().

    Optional enhancement: patch cursor.prg to detect .BMP extension and route through CreateBmpCursor automatically with
    default hotspot (0,0). Want me to make that change ?

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 7317
Joined: Thu Oct 18, 2012 07:17 PM
Re: Sample to make a drop into btnbmp
Posted: Fri May 08, 2026 07:28 AM

Dear Antonio, Thank you for your feedback. I have already tried the NewBmp() method, but unfortunately, it doesn't work as expected in my specific scenario.

What I am doing:

I have 6 buttons btnbmp controls with different gradient-based backgrounds. When the user selects (drags) one of these buttons, I dynamically generate a BMP file on disk that matches the button's gradient style.

The goal:

The user should drag this generated BMP and drop it onto a group of 16 large bitmaps. Upon dropping, the target bitmap receives the color/gradient of the dragged source.

The issue:

DEFINE CURSOR FILE "filename.bmp" fails because, as you explained, it only supports .cur or .ico.

TCursor():NewBmp( oBmp, 0, 0 ) is often unstable or fails to show the cursor correctly depending on the BMP's color depth (24/32 bit) and the lack of a transparency mask.

Using a predefined DRAG cursor is not an option because I need the user to see the specific color/gradient they are dragging.

My request:

Yes, please! I would be very grateful if you could patch cursor.prg to detect the .BMP extension and automatically route it through CreateBmpCursor.

If the class could handle the BMP-to-Cursor conversion internally (generating the necessary mask for Windows), it would make this type of dynamic drag-and-drop UI much easier to implement in FiveWin.

Best regards, Silvio

Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com

Continue the discussion