(Win32) Drag&Drop onto individual gadgets

BlitzMax Forums/BlitzMax Module Tweaks/(Win32) Drag&Drop onto individual gadgets

taxlerendiosk(Posted 2005) [#1]
I worked out how to do this because I wanted several text fields in one window that you can drag and drop files on and they would be set to the file path (as an alternative to a button you click next to the text field which opens a file requester). This one's a bit more involved than others, you have to do a couple of things, so I'd suggest you only bother to do this if you're sure of yourself and really want it for something specific...

OK, first thing you need to do is get the following text from the wndProc method at the bottom of brl.mod\win32maxgui.mod\win32gui\win32window.cpp (or, er, the codebox itself):
	case  WM_DROPFILES:
		HDROP		drop;
		POINT		pt;
		BBString	*path;
		char		buffer[MAX_PATH];
		int			i,n,l;
		drop=(HDROP)wp;
		DragQueryPoint(drop,&pt);
		n=DragQueryFile(drop,0xffffffff,0,0);
		for (i=0;i<n;i++)
		{
			l=DragQueryFile(drop,i,buffer,MAX_PATH);
			path=bbStringFromBytes(buffer,l);
			emit( BBEVENT_WINDOWACCEPT,0,0,pt.x,pt.y,(BBObject*)path );
		}		
		DragFinish(drop);
		break;

Next, open the relevant .cpp file for the gadget that you want to set "drag-droppable" in that same directory. E.g. to do text fields it was brl.mod\win32maxgui.mod\win32gui\win32textfield.cpp. Paste the code above into the corresponding place in that gadget's wndProc method (i.e. inside the switch block, between existing cases.) Now open win32window.cpp again and copy this line from the instantiation method at the top:
	if (style&128) DragAcceptFiles( hwnd,true );

Paste it into the instantiation method of your chosen gadget (i.e. for text fields the Win32TextField::Win32TextField method, should be right at the top), after the hwnd variable has been set, e.g. here:
	HWND hwnd=CreateWindowEx( xstyle,"EDIT","",wstyle,0,0,0,0,parent,0,GetModuleHandle(0),0 );

	if (style&128) DragAcceptFiles( hwnd,true ); // HERE!!!

	_gadget.setHwnd( hwnd );
	_gadget.setWndProc( this );

Now you should be done! You should be able to set the flag WINDOW_ACCEPTFILES to the gadget as you create it, and catch EVENT_WINDOWACCEPT events for it. Here's a small demo:
Local window:TGadget=CreateWindow("My Window",30,20,320,200)

Local textfield1:TGadget=CreateTextField(4,4,120,22,window,WINDOW_ACCEPTFILES)
Local textfield2:TGadget=CreateTextField(4,30,120,22,window,WINDOW_ACCEPTFILES)

SetGadgetText( textfield1,"Drag files onto me!" )
SetGadgetText( textfield2,"No, me!" )

While WaitEvent()
	Select EventID()
		Case EVENT_WINDOWACCEPT
			Select EventSource()
				Case textfield1
					SetGadgetText textfield1,String(EventExtra())
				Case textfield2
					SetGadgetText textfield2,String(EventExtra())
			End Select
	Case EVENT_WINDOWCLOSE
		End
	End Select
Wend



Jason W.(Posted 2006) [#2]
I have not used this yet. I prefer to see this added to the MAXGUI module.

skid or mark,

Can you comment on this?

Jason


Brucey(Posted 2006) [#3]
For that, you would need implementations of it across platforms.