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
Author: Mike K
Date: Tue, 17 Jun 2008 12:14
Date: Tue, 17 Jun 2008 12:14
46 lines
2245 bytes
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
Author: Eliot Frank
Date: Tue, 17 Jun 2008 13:13
Date: Tue, 17 Jun 2008 13:13
19 lines
1695 bytes
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
Author: Eliot Frank
Date: Tue, 17 Jun 2008 13:17
Date: Tue, 17 Jun 2008 13:17
10 lines
1342 bytes
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
Author: Mike K
Date: Tue, 17 Jun 2008 13:48
Date: Tue, 17 Jun 2008 13:48
23 lines
2139 bytes
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
Author: Remy Lebeau (TeamB)
Date: Tue, 17 Jun 2008 16:27
Date: Tue, 17 Jun 2008 16:27
89 lines
3202 bytes
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