Page 1 of 1

Drag and Drop Files Demo in C. Rate Topic: ***** 1 Votes

#1 snoopy11  Icon User is online

  • Engineering ● Software
  • member icon

Reputation: 802
  • View blog
  • Posts: 2,363
  • Joined: 20-March 10

Posted 28 September 2012 - 07:39 PM

Drag and Drop.

In this simple Demo I would like to discuss
how to drag and drop files into your application.

As usual I will post the entire code first then explain it bit by bit.

#include <Windows.h>
#include <ShellAPI.h>
#include <string.h>
#include <stdio.h>
#define SIZE 500

#define IDC_EDIT 1
#define IDC_LIST 2

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

char *szAppName = "Drag and Drop";




int WINAPI WinMain (HINSTANCE hThisInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpszArgument,
	int nCmdShow)
{

	HWND hwnd;               /* This is the handle for our window */
	MSG messages;            /* Here messages to the application are saved */
	WNDCLASSEX wincl;        /* Data structure for the windowclass */

	/* The Window structure */
	wincl.hInstance = hThisInstance;
	wincl.lpszClassName = szAppName;
	wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
	wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
	wincl.cbSize = sizeof (WNDCLASSEX);

	/* Use default icon and mouse-pointer */
	wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
	wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
	wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
	wincl.lpszMenuName = "APP_MENU";                 /*menu */
	wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
	wincl.cbWndExtra = 0;                      /* structure or the window instance */
	/* Use Windows's default colour as the background of the window */
	wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

	/* Register the window class, and if it fails quit the program */
	if (!RegisterClassEx (&wincl))
		return 0;

	/* The class is registered, let's create the program*/
	hwnd = CreateWindowEx (
		0,                   /* Extended possibilites for variation */
		szAppName,         /* Classname */
		szAppName,       /* Title Text */
		WS_OVERLAPPEDWINDOW|WS_EX_ACCEPTFILES, /* default window */
		CW_USEDEFAULT,       /* Windows decides the position */
		CW_USEDEFAULT,       /* where the window ends up on the screen */
		600,                 /* The programs width */
		600,                 /* and height in pixels */
		HWND_DESKTOP,        /* The window is a child-window to desktop */
		NULL,                /*use class menu */
		hThisInstance,       /* Program Instance handler */
		NULL                 /* No Window Creation data */
		);

	/* Make the window visible on the screen */
	ShowWindow (hwnd, nCmdShow);

	/* Run the message loop. It will run until GetMessage() returns 0 */
	while (GetMessage (&messages, NULL, 0, 0))
	{
		/* Translate virtual-key messages into character messages */
		TranslateMessage(&messages);
		/* Send message to WindowProcedure */
		DispatchMessage(&messages);
	}

	/* The program return-value is 0 - The value that PostQuitMessage() gave */
	return messages.wParam;
}


LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

	static HWND EditBox;
	static HWND ListBox;
	char *buffer;
	char* outText;
	HDROP hDropInfo = NULL;
	UINT buffsize= SIZE;
	char buf[SIZE];




	switch (message)                  /* handle the messages */
	{
	case WM_CREATE:

		ListBox = CreateWindowEx(0,"LISTBOX",TEXT(""),WS_VISIBLE|WS_CHILD|WS_VSCROLL|WS_HSCROLL|LBS_HASSTRINGS,10,10,500,300,hwnd,(HMENU)IDC_LIST,((LPCREATESTRUCT) lParam) -> hInstance,(LPVOID)NULL);
		EditBox = CreateWindowEx(0,"EDIT",TEXT(""),WS_VISIBLE|WS_CHILD|WS_VSCROLL|WS_HSCROLL|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_LEFT|ES_WANTRETURN,10,310,500,240,hwnd,(HMENU)IDC_EDIT,((LPCREATESTRUCT) lParam) -> hInstance,(LPVOID)NULL);
		DragAcceptFiles(ListBox,TRUE);
		return 0;

	case WM_DROPFILES:
		{
			hDropInfo = (HDROP) wParam;

			DragQueryFile (hDropInfo, 0, buf, buffsize);





			FILE *pFile;
			char* pch = strstr(buf,".txt");
			if(pch != NULL)
			{
				pFile =  fopen (buf,"r");
				if (pFile !=NULL)
				{



					// obtain file size:
					fseek (pFile , 0 , SEEK_END);
					long lSize = ftell (pFile);
					rewind (pFile);
					// allocate memory to contain the buffers:
					buffer = (char*) malloc (sizeof(char)*lSize);
					outText = (char*) malloc (sizeof(char)*lSize*2);
					ZeroMemory(buffer,lSize);
					ZeroMemory(outText,lSize);
					char *returnchar = "\r";
					// copy the file into the buffers:
					while(fgets (buffer,lSize,pFile) != NULL)
					{
						strcat(outText, buffer);
						strcat(outText, returnchar);

					}

					SendMessage(ListBox,LB_ADDSTRING, 0, (LPARAM)buf);
					HFONT hFont=CreateFont(16,0,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS,
						CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY, VARIABLE_PITCH,TEXT("Arial Bold"));

					SendMessage(EditBox,             // Handle of edit control
						WM_SETFONT,         // Message to change the font
						(WPARAM) hFont,     // handle of the font
						MAKELPARAM(TRUE, 0) // Redraw text
						);
					SendMessage(EditBox,WM_SETTEXT,0,(LPARAM)outText);
					free(buffer);
					free(outText);

				}
				fclose(pFile);
			}
			else
				MessageBox(hwnd,"Not a Text File", "Drop Error", MB_OK);








			break;
		}
	case WM_DESTROY:
		free(hDropInfo);
		PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
		break;




	default:                      /* for messages that we don't deal with */
		return DefWindowProc (hwnd, message, wParam, lParam);

	}
	return 0;
}



I have decided to make this demo in C to make the program
as cross compiler compatible as possible.

It will build and compile in all the Major IDE/Compiler suites

I have built this in

Microsoft Visual C++ 2010
Pelles C
Code::Blocks with MinGW installation
Eclipse with MinGW installation
which means it should run under DEV C++ as well

you will need to link to

kernel32
shell32
user32
gdi32


in Microsoft Visual Studio it will produce warnings about using the microsoft specific versions of fopen and strcat.

You can either ignore these warnings or add the _CRT_SECURE_NO_WARNINGS flag to Pre-processor Defintions.

If you are using MS Visual Studio please remember this is not a unicode build so
change the character set to Use Multi-Byte Character Set.


The Explanation Bit

We set up some defines first.

We call our windows callback procedure WindowProcedure
.


We make our usual window.


LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

	static HWND EditBox;
	static HWND ListBox;
	char *buffer;
	char* outText;
	HDROP hDropInfo = NULL;
	UINT buffsize= SIZE;
	char buf[SIZE];




This is the start of WindowProcedure
I set up some HWND's EditBox and a ListBox.
set up some char buffers for use later on in dragging and dropping

set up a HDROP variable
declare another buffer in buf.

Moving on swiftly...

case WM_CREATE:

		ListBox = CreateWindowEx(0,"LISTBOX",TEXT(""),WS_VISIBLE|WS_CHILD|WS_VSCROLL|WS_HSCROLL|LBS_HASSTRINGS,10,10,500,300,hwnd,(HMENU)IDC_LIST,((LPCREATESTRUCT) lParam) -> hInstance,(LPVOID)NULL);
		EditBox = CreateWindowEx(0,"EDIT",TEXT(""),WS_VISIBLE|WS_CHILD|WS_VSCROLL|WS_HSCROLL|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_LEFT|ES_WANTRETURN,10,310,500,240,hwnd,(HMENU)IDC_EDIT,((LPCREATESTRUCT) lParam) -> hInstance,(LPVOID)NULL);
		DragAcceptFiles(ListBox,TRUE);
		return 0;


We create a ListBox and an Edit box..

case WM_DROPFILES:
		{
			hDropInfo = (HDROP) wParam;

			DragQueryFile (hDropInfo, 0, buf, buffsize);





			FILE *pFile;
			char* pch = strstr(buf,".txt");
			if(pch != NULL)
			{
				pFile =  fopen (buf,"r");
				if (pFile !=NULL)
				{



					// obtain file size:
					fseek (pFile , 0 , SEEK_END);
					long lSize = ftell (pFile);
					rewind (pFile);
					// allocate memory to contain the buffers:
					buffer = (char*) malloc (sizeof(char)*lSize);
					outText = (char*) malloc (sizeof(char)*lSize*2);
					ZeroMemory(buffer,lSize);
					ZeroMemory(outText,lSize);
					char *returnchar = "\r";
					// copy the file into the buffers:
					while(fgets (buffer,lSize,pFile) != NULL)
					{
						strcat(outText, buffer);
						strcat(outText, returnchar);

					}

					SendMessage(ListBox,LB_ADDSTRING, 0, (LPARAM)buf);
					HFONT hFont=CreateFont(16,0,0,0,FW_DONTCARE,FALSE,FALSE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS,
						CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY, VARIABLE_PITCH,TEXT("Arial Bold"));

					SendMessage(EditBox,             // Handle of edit control
						WM_SETFONT,         // Message to change the font
						(WPARAM) hFont,     // handle of the font
						MAKELPARAM(TRUE, 0) // Redraw text
						);
					SendMessage(EditBox,WM_SETTEXT,0,(LPARAM)outText);
					free(buffer);
					free(outText);

				}
				fclose(pFile);
			}
			else
				MessageBox(hwnd,"Not a Text File", "Drop Error", MB_OK);








			break;
		}


This is where the drag and drop magic happens.

I get the HDROP from wParam

use DragQueryFile to retrieve the path information.

declare a FILE structure for loading the text file.

use strstr to make sure we only allow .txt files you caan change this to any
extension you please but in this example its text files being dropped.

we obtain a file size
dynamically create some buffers to hold the text file.

I copy the .txt file into the buffers
set up a while loop to read the textfile with carriage returns line by line.

I send a message to the listbox and create a font for use in the editbox
I set the font for the edit box with SendMessage.

I then finally write the contents of outText to the EditBox with SendMessage.

Finally I Free the memory allocated by the buffers

And that is it basically... quite easy.

I have included a suitably long .txt file it is Edgar Allan Poe's The Raven
it is attached as Raven.txt

Best Wishes

Snoopy.

Attached File(s)

  • Attached File  Raven.txt (6.59K)
    Number of downloads: 605


Is This A Good Question/Topic? 4
  • +

Replies To: Drag and Drop Files Demo in C.

#2 Senor Pablos  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 15-July 14

Posted 15 July 2014 - 03:53 PM

Incredibly detailed tutorial focusing on the minimums. I like it. Registered only for express this.

[Also nice that should support other IDEs.]

[I so far am not sure how to make the Window indicate that it will accept a drop file, moving a file over it I get a red circle with an X in it, however I am sure I will figure this out ..]
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1