Click here to Skip to main content
6,595,444 members and growing! (19,696 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » WTL » General     Intermediate

Dropping Files Into a WTL Window (The Easy Way)

By Pablo Aliskevicius

A mix-in class to help dropping files into WTL windows.
VC6, Windows, WTL, Dev
Posted:22 Feb 2004
Updated:20 Apr 2004
Views:28,100
Bookmarked:15 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
12 votes for this article.
Popularity: 4.51 Rating: 4.18 out of 5

1

2
1 vote, 8.3%
3
3 votes, 25.0%
4
8 votes, 66.7%
5

Sample Image (Dialog version)

Introduction

Every day, many of us drop files on windows in order to get them to 'do' something: an editor (text or graphics), a word processor, an electronic worksheet, a media player, and even Visual Studio usually opens the file: a shortcut is created when dropping the file on top of the 'Start' button; some utilities add a shortcut to a toolbar, when dropping the file on that toolbar.

The API way to do it, is to add WS_EX_ACCEPTFILES to the extended style of your dialog, view or child window, and handle WM_DROPFILES.

Since most of the WM_DROPFILES handlers are quite similar, the WTL way to do it is to make a mixin class which handles the boring parts of the job, inherit from it, and add just your own logic.

After that, you can add WM_DROPFILES handling to your windows with about a dozen lines of code.

Background:

The WM_DROPFILES handler usually does the following actions:

  • Tests to see that the drop happened inside the client area of the relevant window.
  • Tests to see that the application is ready to handle dropped files.
  • Checks how many files were dropped.
  • In a loop (since multiple files can be dropped at once): A. Gets the name (a fully qualified path is given) of each dropped file. B. Does some application-specific handling.
  • Releases memory and resources used to manage the drag & drop operation.
  • Does application-specific resource cleanup, if needed.

As you see, most of the functionality is boilerplate: only the actions marked in bold are application-specific. Those are the only ones you'll have to write, if you decide to use CDropFilesHandler.

Using the code:

There are basically two kinds of windows which will handle dropped files: dialogs and frame windows.

Using CDropFilesHandler<CMyDialog> (with dialogs):

  • In the resource editor, mark the checkbox "Accept Files" in the tab "Extended Styles" (see image below), otherwise the WM_DROPFILES message will never arrive.

The sample dialog's properties

  • #include <DropFilesHandler.h> (which should be in your WTL\Include\CustomExtensions folder).
  • Inherit your class (from now on, CMyDialog) from CDropFilesHandler<CMyDialog>.
  • Forward messages, by adding CHAIN_MSG_MAP(CDropFilesHandler<CMyDialog>) to your message map.
  • Implement three functions: BOOL IsReadyForDrop(void) - Called once for each drop operation, before entering the dropped files loop. Return TRUE if your dialog is ready to accept dropped files, FALSE otherwise. BOOL HandleDroppedFile(LPCTSTR szBuff) - This is the function called inside the loop, once per dropped file, and it should return FALSE to break the loop. This one might implement the real 'handling' of the drop (e.g., by pasting the file's name in an edit box, or, in a SDI/MDI/Multi SDI application, by opening the file). void EndDropFiles(void) - This function is called once, after exiting the loop. You can leave this as an empty inline, but if your file handling is not trivial, and you want to handle several files at once, putting all their names in a container during the loop (std::list<WTL::CString> comes to mind) and starting a worker thread here to really handle them all can be an option.

This is the dialog class in the dialog sample project (relevant parts in bold):

// maindlg.h : interface of the CMainDlg class

//

/////////////////////////////////////////////////////////////////////


#include "DropFileHandler.h" // Include the relevant file...


class CMainDlg : public CDialogImpl<CMainDlg>,
              // Add CDropFilesHandler to your inheritance list...

                 public CDropFilesHandler<CMainDlg> 
{
public:
    enum { IDD = IDD_MAINDLG };

    BEGIN_MSG_MAP(CMainDlg)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
        COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
        COMMAND_ID_HANDLER(IDOK, OnOK)
        COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
        // Send WM_DROPFILES to its handler...

        CHAIN_MSG_MAP(CDropFilesHandler<CMainDlg>)
    END_MSG_MAP()
    

    LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, 
      LPARAM /*lParam*/, BOOL& /*bHandled*/)
    {
        // center the dialog on the screen

        CenterWindow();

        // set icons

        HICON hIcon = (HICON)::LoadImage(
          _Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
            IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), 
           ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
        SetIcon(hIcon, TRUE);
        HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), 
            MAKEINTRESOURCE(IDR_MAINFRAME), 
            IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), 
           ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
        SetIcon(hIconSmall, FALSE);
        // The sample dialog application just adds all

        // dropped files to a listbox.

        m_ListBox.Attach(GetDlgItem(IDC_LISTFILES));
        return TRUE;
    }
    // These were left as the wizard created them...

    LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, 
         HWND /*hWndCtl*/, BOOL& /*bHandled*/);
    LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID,
         HWND /*hWndCtl*/, BOOL& /*bHandled*/);
    LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, 
         HWND /*hWndCtl*/, BOOL& /*bHandled*/);
    
    /////////////////////////////////////////////////////////////////////

    //////////////////////// CDropFilesHandler requirements' implementation.

    // In this particular example, we'll put all dropped files in a listbox.

    CListBox m_ListBox;

    BOOL IsReadyForDrop(void)     { m_ListBox.ResetContent(); return TRUE; }
    BOOL HandleDroppedFile(LPCTSTR szBuff)
    {
        ATLTRACE("%s\n", szBuff);
        // In this particular example, we'll do the VERY LEAST possible.

        m_ListBox.AddString(szBuff);

        // Return TRUE unless you're done handling files (e.g., if you want 

        // to handle only the first relevant file, 

        // and you have already found it).

        return TRUE;
    }
    void EndDropFiles(void)
    {
        // Sometimes, if your file handling is not trivial,  

        // you might want to add all

        // file names to some container (std::list<CString> comes to mind), 

        // and do the 

        // handling afterwards, in a worker thread. 

        // If so, use this function to create your worker thread.



        // In this example, we'll display the total number of files dropped.

        CWindow wnd;
        wnd.Attach(GetDlgItem(IDC_COUNT));
        char fmt[] = "Count of files in the last drop: %d";
        char buff[sizeof(fmt) + 30];
        wsprintf(buff, fmt, m_ListBox.GetCount());
        wnd.SetWindowText(buff);
    }
};

Using CDropFilesHandler<CMyView> (with frame windows):

It is almost the same, except that you don't usually have access to your view through the resource editor. You have (at least) three options: adding the style when the mainframe creates the view (this was done in the sample application), calling RegisterDropHandler() on creation from the view itself (more self-contained), if the view handles WM_CREATE, or even calling ModifyStyleEx(0, WS_EX_ACCEPTFILES) either depending on an initialization parameter or on a menu option, thus letting the user enable/disable file dropping.

Points of Interest

This class might save you writing a couple of dozen lines of code per window, which is not much, but it also centralizes maintenance, which is a desirable thing, and enables a programmer to handle dropped files without learning the API related to WM_DROPFILES, which is a (maybe mixed) blessing. If any of you finds this code helpful or inspiring (as I have found so many CodeProject samples), this article has filled its purpose.

History

  • 2004: February - Created.
  • 2004: April - Added the protected member m_nFiles, which holds, during drop operations, the total number of dropped files, and can be used to display a progress bar. Fixed a bug: EndDropFiles() was called for each file, instead of once per drop.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Pablo Aliskevicius


Member
Pablo writes code for a living, in the good ol' days in COBOL, now in C#, C++, and also SQL (both MS' T-SQL and Oracle's PL).

To make all that work easier, he uses some C++ libraries: STL (can't live without it), ATL & WTL (to write Windows applications), and code generation (you'll find almost everything you need in SQL Server's view SYS.OBJECTS).

Pablo was born in 1963, got married in 1998, and is the happy father of two girls.

His favorite quote is: "Accident: An inevitable occurrence due to the action of immutable natural laws." (Ambrose Bierce, "The Devil's Dictionary", published in several newspapers between 1881 and 1906).
Occupation: Team Leader
Location: Israel Israel

Other popular WTL articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 2 of 2 (Total in Forum: 2) (Refresh)FirstPrevNext
GeneralI like the mixin style [modified] Pinmemberflyingxu19:41 1 Feb '09  
GeneralThank you! PinmemberJohnnyMalaria15:01 25 Jan '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 20 Apr 2004
Editor: Nishant Sivakumar
Copyright 2004 by Pablo Aliskevicius
Everything else Copyright © CodeProject, 1999-2009
Web10 | Advertise on the Code Project