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)
-
Raven.txt (6.59K)
Number of downloads: 1262