2014-01-25 17 views
5

Во-первых, чтобы уточнить, я не не, спрашивая, как перетащить файл на значок exe. Я хочу знать, как обращаться с перетаскиванием на уже запущенное приложение win32. Я также не спрашивает, как обращаться с перетаскиванием внутри приложений на основе WinMain через насос сообщений Windows. Я хочу сделать это внутри программы с точкой входа int main(), у которой нет WndProc (пока) или что-то еще.Обращение с файлами перетаскивания в запущенном консольном приложении Windows

Сказали, что мне интересно, возможна ли моя цель (и надеется, что это так).

У меня есть серверное приложение, которое работает в окне консоли. Из-за большой кодовой базы и множества странных связей она является консолью «только для вывода» для всех интенсивных целей. Внутри этого, хотя я все еще могу обрабатывать такие вещи, как нажатия клавиш, поскольку у меня есть цикл обновления. Я хотел бы иметь возможность перетаскивать файлы, заполненные командами (которые используют специальный синтаксис), в мое запущенное приложение и обрабатывать их.

Это можно сделать? Я думал, что потенциально я мог бы получить указатель на HWND консоли (что, надеюсь, это вещь?), А затем, возможно, подкласс этого окна использовать пользовательский WndProc для прослушивания сообщения WM_DROPFILES.

Я никогда не пытался настроить обработку окон сообщений в Int основной() программы вместо программы WinMain, но я надеюсь, что это как-то возможно.

Любая помощь была бы принята с благодарностью! Странные решения в порядке.

ответ

6

AFAIK, консольное окно не поддерживает перетаскивание & по умолчанию. Вы всегда можете создать свое собственное отдельное всплывающее окно со своим собственным циклом сообщений, чтобы пользователь мог что-то перетаскивать.

Чтобы использовать перетащить & падение на само окно консоли, попробуйте использовать GetConsoleWindow(), чтобы получить консоль HWND, затем:

  1. подкласса HWND с помощью SetWindowLong/Ptr() или SetWindowSubClass(), а затем зарегистрировать HWND, используя DragAcceptFiles(), чтобы начать получение WM_DROPFILES сообщений. Не забудьте снова позвонить DragAcceptFiles(), чтобы прекратить получать сообщения, а затем отцепить ваш подкласс перед выходом из приложения.

  2. реализовать интерфейс IDropTarget, а затем зарегистрировать HWND с помощью RegisterDragDrop(), чтобы начать получать уведомления. Обязательно вызовите RevokeDragDrop() перед выходом из приложения.

WM_DROPFILES проще кодировать, но IDropTarget является более гибким, поскольку он обрабатывает виртуальные предметы, а также физические файлы.

+0

Очень интересно, спасибо! Я оставлю его открытым дольше, чтобы понять, существуют ли какие-то реальные странные решения, но это надежный ответ. Я не знал о различиях между WM_DROPFILES и IDropTarget.Сервер уже где-то использует MFC, поэтому это может быть жизнеспособным. –

+1

Хм, нет, консольное окно фактически не принадлежит консольной программе. Таким образом, подклассы - это полный тупик. Покрывается [этот вопрос] (http://stackoverflow.com/questions/14788134/trying-subclassing-on-console). –

+1

Если программа является первым процессом, запущенным в консоли, то он имеет собственное консольное окно ('GetWindowThreadProcessId()' возвращает те же идентификаторы, что и 'GetCurrentProcessId()' и 'GetCurrentThreadId()'), но нечетное подклассирование не работает ('SetWindowLong/Ptr() 'возвращает ошибку 5). Если программа не является первым процессом в консоли, она не будет владеть консольным окном, хотя она будет выполнять ввод-вывод с использованием существующего окна консоли. –

1
#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'; 
} 
+1

Добавьте описание, чтобы другой мог понять ваш код и ответить на этот вопрос. –

+0

Почему это работает? – Charlie

Смежные вопросы