Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling drag and drop files in a running Windows console application

First, to clarify, I am not asking how to drag-and-drop a file onto an exe's icon. I want to know how to handle drag and drop onto an already running win32 console application. I'm also not asking how to handle drag and drop inside of WinMain based applications through the Windows message pump. I want to do this inside of a program with the entry point int main() that doesn't have a WndProc (yet) or anything.

That said, I'm wondering if my goal is achievable (and hoping that it is).

I have a server application that is running within a console window. Due to a large codebase and a lot of weird coupling, it is an 'output only' console for all intensive purposes. Within it though, I can still handle things like key presses, as I have an update loop ticking. I'd like to be able to drag and drop files full of commands (which use a custom syntax) onto my running application and have it process them.

Is this possible to do? I was thinking that potentially I could get a pointer to the HWND of the console (which hopefully is a thing?), and then maybe subclass that window to use a custom WndProc to listen for the WM_DROPFILES message.

I've never really tried to set up handling of windows messages in an int main() program instead of a WinMain program, but I'm hoping it's somehow possible.

Any help would be greatly appreciated! Weird solutions are fine.

like image 222
Robert Kelly Avatar asked Jan 25 '14 01:01

Robert Kelly


2 Answers

AFAIK, a console window does not support drag&drop by default. You can always create your own separate popup window with its own message loop so the user has something to drag items onto.

To use drag&drop on the console window itself, try using GetConsoleWindow() to get the console HWND, then either:

  1. subclass the HWND using SetWindowLong/Ptr() or SetWindowSubClass(), then register the HWND using DragAcceptFiles() to start receiving WM_DROPFILES messages. Be sure to call DragAcceptFiles() again to stop receiving the messages and then unhook your subclass before exiting the app.

  2. implement the IDropTarget interface and then register the HWND using RegisterDragDrop() to start receiving notifications. Be sure to call RevokeDragDrop() before exiting the app.

WM_DROPFILES is easier to code for, but IDropTarget is more flexible as it handles virtual items as well as physical files.

like image 146
Remy Lebeau Avatar answered Sep 27 '22 21:09

Remy Lebeau


#include <vector>
#include <string>
#include <iostream>
#include <conio.h>

int main()
{
    std::cout << "Please drop files and press [Enter] when done ...\n";

    std::vector< std::string > files;

    for( int ch = _getch(); ch != '\r'; ch = _getch() ) {

        std::string file_name;

        if( ch == '\"' ) {  // path containing spaces. read til next '"' ...

            while( ( ch = _getch() ) != '\"' )
                file_name += ch;

        } else { // path not containing spaces. read as long as chars are coming rapidly.

            file_name += ch;

            while( _kbhit() )
                file_name += _getch();
        }

        files.push_back( file_name );
    }

    std::cout << "You dropped these files:\n";

    for( auto & i : files )
        std::cout << i << '\n';
}
like image 40
Swordfish Avatar answered Sep 27 '22 23:09

Swordfish