🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.nativeapi
5 messages
5 total messages Started by Mike K Tue, 17 Jun 2008 12:14
Drag-and-drop 101
#151
Author: Mike K
Date: Tue, 17 Jun 2008 12:14
46 lines
2245 bytes
I would like to drag files (just file names) from windows explorer into a Borland control.  Here is the implementation from the Developers Guide:

1) in the main form constructor, add:
	DragAcceptFiles(Handle,true);

2) set up a message map in the mainform class:
	.
	.
	private:
	   void virtual __fastcall WMDropFiles(TWMDropFiles &message);

	public:
 	   BEGIN_MESSAGE_MAP
	   MESSAGE_HANDLER(WM_DROPFILES,TWMDropFiles,WMDropFiles)
	   END_MESSAGE_MAP

3) write the handler:
	void __fastcall WMDropFiles(TWMDropFiles &message)
	{
		String filename;
		int count;
   		count = DragQueryFile((HDROP)message.Drop,0xFFFFFFFF,NULL,MAX_PATH);

   		for(int i=1;i<count; i++)
   		{
      			filename.SetLength(DragQueryFile((HDROP)message.Drop,i,fname.c_str(),MAX_PATH));
      			FileListBox1->Items->Add(filename);
   		}
   		DragFinish((HDROP)message.Drop);
	}

Seems easy enough. But when I compile and run this code, the app crashes into the CPU window, and the call stack shows pages of calls to TForm1::Dispatch().  I commented all the code out of the handler, and put breakpoints in the message map and in the call to DragAcceptFiles().  I never hit a breakpoint, and crash every time.  

Am I missing something very basic?  

Using BCB5. Also, what would I use the TFileListBox's OnDragDrop method for?  Drag/drop within the application?


Thanks for any help...


Mike



	
Re: Drag-and-drop 101
#152
Author: Eliot Frank
Date: Tue, 17 Jun 2008 13:13
19 lines
1695 bytes
Mike K wrote:
> 
> filename.SetLength(DragQueryFile((HDROP)message.Drop,i,fname.c_str(),MAX_PATH)); 

This is very very wrong.  What's "fname"?  Is fname initialized to be 
long enough to accept up to MAX_PATH bytes?  Since you don't show the 
initialization code, I guess the answer is no.  If fname is an 
uninitialized String (aka AnsiString), c_str() returns NULL (bad bad 
craziness there).  Also you are passing a char const * (the result of 
c_str()) to a function that expects a char * (I don't see why that 
should even compile).

Just use the simple,

	char name[MAX_PATH];
	DragQueryFile((HDROP)message.Drop,i,name,MAX_PATH);
	filename = name;

-Eliot
Re: Drag-and-drop 101
#153
Author: Eliot Frank
Date: Tue, 17 Jun 2008 13:17
10 lines
1342 bytes
Mike K wrote:
>     private:
>        void virtual __fastcall WMDropFiles(TWMDropFiles &message);
> 

Also I wanted to say when I've done this, I have the dispatch function 
in a protected area not a private area.  I know I've had trouble with 
private WMDropFiles dispatch functions, but I don't remember why.

-Eliot
Re: Drag-and-drop 101
#154
Author: Mike K
Date: Tue, 17 Jun 2008 13:48
23 lines
2139 bytes
Eliot Frank wrote:
> Mike K wrote:
>>
>> filename.SetLength(DragQueryFile((HDROP)message.Drop,i,fname.c_str(),MAX_PATH)); 
> 
> 
> This is very very wrong.  What's "fname"?  Is fname initialized to be 
> long enough to accept up to MAX_PATH bytes?  Since you don't show the 
> initialization code, I guess the answer is no.  If fname is an 
> uninitialized String (aka AnsiString), c_str() returns NULL (bad bad 
> craziness there).  Also you are passing a char const * (the result of 
> c_str()) to a function that expects a char * (I don't see why that 
> should even compile).
> 
> Just use the simple,
> 
>     char name[MAX_PATH];
>     DragQueryFile((HDROP)message.Drop,i,name,MAX_PATH);
>     filename = name;
> 
> -Eliot

Sorry, these are transcription typos.  I left out 'filename.SetLength(MAX_PATH)' and spelled 'filename' as 'fname'.  The code is right out of the Developers Guide.  Doesn't matter anyway, since the handler code is commented out.  The only way the app runs without crashing is by commenting out the message mapping macros. 
Re: Drag-and-drop 101
#155
Author: Remy Lebeau (TeamB)
Date: Tue, 17 Jun 2008 16:27
89 lines
3202 bytes
"Mike K" <nospam@nospam.net> wrote in message
news:4857aabb$1@newsgroups.borland.com...

> I would like to drag files (just file names) from windows explorer
> into a Borland control.

There are two ways to do that:

1) subclass the control to intercept the WM_DROPFILES message (obsolete, 
provided for backwards compatibility)

2) implement the IDropTarget interface (recommended)

>    END_MESSAGE_MAP

That has a required parameter:

    END_MESSAGE_MAP(TForm)

> void __fastcall WMDropFiles(TWMDropFiles &message)

That needs to be a member of the class:

    void __fastcall TForm1::WMDropFiles(TWMDropFiles &message)

>  for(int i=1;i<count; i++)

Your loop needs to start at 0, not 1.

> filename.SetLength(DragQueryFile((HDROP)message.Drop,i,fname.c_str(),MAX_PATH));

On the first iteration of the loop, fname is empty, so you are telling 
DragQueryFile() to write to a NULL buffer.  You need to allocate memory 
before passing it around.  In this situation, I would suggest using a 
static-length character array instead.

Try this code:

    private:
        MESSAGE void __fastcall WMDropFiles(TWMDropFiles &message);

    protected:
        virtual void __fastcall CreateWnd();
        virtual void __fastcall DestroyWnd();

    public:
        BEGIN_MESSAGE_MAP
            VCL_MESSAGE_HANDLER(WM_DROPFILES, TWMDropFiles, WMDropFiles)
        END_MESSAGE_MAP(TForm)


    void __fastcall TForm1::CreateWnd()
    {
        TForm::CreateWnd();
        DragAcceptFiles(Handle, TRUE);
    }

    void __fastcall TForm1::DestroyWnd()
    {
        DragAcceptFiles(Handle, FALSE);

        TForm::DestroyWnd();
    }

    void __fastcall TForm1::WMDropFiles(TWMDropFiles &message)
    {
        TCHAR filename[MAX_PATH+1];

        UINT count = DragQueryFile((HDROP)message.Drop, 0xFFFFFFFF, NULL, 
0);

        for(int i = 0; i < count; ++i)
        {
            memset(filename, 0, sizeof(filename));
            DragQueryFile((HDROP)message.Drop, i, filename, MAX_PATH);
            FileListBox1->Items->Add(filename);
        }

        DragFinish((HDROP)message.Drop);
    }

> Also, what would I use the TFileListBox's OnDragDrop method for?
> Drag/drop within the application?

Yes.


Gambit
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads