Страница 1 из 1
Путь противоположной панели
Добавлено: Пн июл 02, 2012 12:54
Maximus
Знает ли кто способы получения пути в противоположной панели TC из WFX-плагина?
Естественно напрашивается вывод использовать EnumChildWindows с поиском контрола по имени TPathPanel, текст которого не содержит в начале три черты \\\.
Но может есть способ поровнее?
Добавлено: Пн июл 02, 2012 23:57
MVV
Код: Выделить всё
25.11.11 Release Total Commander 8.0 public beta 10 (32/64)
25.11.11 Added: Send WM_COPYDATA with dwData='G'+256*'W': Same as with 'G'+256*'A', but data is returned as UTF-16 Unicode. dwData of return is 'R'+256*'W' (32/64)
25.11.11 Added: Send WM_COPYDATA with dwData='G'+256*'A' and lpData pointing to command to get back WM_COPYDATA with various info. Supported commands A: Active side (returns L or R), or two byte command: first byte: L=left, R=right, S=source, T=target. Second byte: P=current path, C=list count, I=caret index, N=name of file under caret. dwData of return is 'R'+256*'A' (32/64)
Как вариант. Естественно, не работает в более старых версиях.
А вообще, во время вызова какой конкретно функции это нужно? В силу пассивности WFX-плагинов не вижу необходимости узнавать путь вне вызовов тоталом функций плагина.
Добавлено: Вт июл 03, 2012 01:16
Maximus
MVV
Я так и знал, что ты мне поможешь :)
Похоже на то, что нужно. Даже нашёл твой пример на офсайте.
А что за выражение такое?
dwData='G'+256*'A'
Зачем было писать так интересно?
В твоём примере всё просто
cds.dwData='AG';
А вообще, во время вызова какой конкретно функции это нужно? В силу пассивности WFX-плагинов не вижу необходимости узнавать путь вне вызовов тоталом функций плагина.
Телефонная книга. Хочу завести псевдофайл при запуске которого будет выполняться экспорт всех контактов в один файл. Будет открываться диалог сохранения, куда и буду подставлять путь противоположной панели, если он окажется корректным.
Собственно я уже научился делать это описанным мною выше способом, а теперь хочу сделать то же, но правильно :)
Добавлено: Вт июл 03, 2012 10:44
MVV
Maximus писал(а):А что за выражение такое?
dwData='G'+256*'A'
Зачем было писать так интересно?
В твоём примере всё просто
cds.dwData='AG';
Ну, то писал Гислер, можно было записать как
'G'+('A'<<8). А я знаю, что можно писать многосимвольные константы, заключая их в одиночные кавычки и инвертируя порядок, потому пишу просто 'AG'

Кстати, некоторые компиляторы (гнутый, например) выдают ахтунг на такую запись, хотя и компилируют правильно.
Цель достигается и так и так - получить в данном примере в 4 байтах памяти этой переменной строку "GA" - понять бы, что означает буква 'G' ('A' означает ANSI). Для смены каталога надо получить там строку "CD" (для чего я использую запись 'DC'). У себя для Virtual Panel я использую 'PV' (строка "VP"), а для юникода - 'P\0V' (строка L"VP" без терминатора).
Ну да, в принципе, в
FsExecuteFile путь неактивной панели никак не получить прямым способом. А может для экспорта лучше использовать копирование какого-нибудь псевдофайла в неактивную панель? По-моему, вполне логично для экспорта использовать копирование. Тогда юзер сам выберет путь прямо в тотальном диалоге, и тотал укажет его тебе, вызвав функцию
FsGetFile.
Добавлено: Вт июл 03, 2012 10:55
Maximus
MVV писал(а):А может для экспорта лучше использовать копирование какого-нибудь псевдофайла в неактивную панель? По-моему, вполне логично для экспорта использовать копирование. Тогда юзер сам выберет путь прямо в тотальном диалоге, и тотал укажет его тебе, вызвав функцию FsGetFile.
Будет и то и другое. Просто для пользователя понятнее будет запуск псевдофайла с именем "Экспорт всего на свете", чем копирование файла contacts.vcf. Поэтому функционал будет продублирован - для запуска этого элемента и для его копирования.
Добавлено: Вт июл 03, 2012 11:17
MVV
Ну в принципе да, можно и продублировать. Но окошки искать, конечно, занятие не из приятных. Особенно с учетом того, что в разных версиях иерархия слегка различается. Не говоря уже о 64-битной версии, где почти все дочерние окна имеют имя класса Window.
Добавлено: Вт июл 03, 2012 11:35
Maximus
MVV писал(а):Но окошки искать, конечно, занятие не из приятных. Особенно с учетом того, что в разных версиях иерархия слегка различается. Не говоря уже о 64-битной версии, где почти все дочерние окна имеют имя класса Window.
Вот потому и хотелось сделать всё не костылями, а как положено.
Добавлено: Ср июл 04, 2012 23:54
Maximus
MVV
Чтото не идет у меня WM_COPYDATA. TC ничего не отвечает. Не сталкивался ли ты с подобным во время отладки?
Добавлено спустя 1 час 22 минуты:
SendMessage возвращает false.
Пытаюсь послать сообщение в своё же приложение - результат тот же.
Добавлено спустя 28 минут:
Внезапно всё заработало. Причины неработы непонятны. Вероятно, что файервол-антивирус. Такое вообще возможно? Заработало через некоторое время после отключения. Но сейчас работает и при включенном.
А можно ли сообщение WM_COPYDATA каким-то образом обработать не в оконной процедуре, а в самой DLL?
Добавлено: Чт июл 05, 2012 10:00
MVV
Пардон, что значит "не в оконной процедуре, а в самой DLL"? Если у тебя оконная процедура твоего окна в DLL, то можно и нужно.
Добавлено: Чт июл 05, 2012 10:21
Maximus
Я имел в виду, если DLL не создает никаких окон.
Добавлено: Чт июл 05, 2012 11:25
MVV
А тебе просто необходимо окно, чтобы получить ответ, иначе никак. Подцепляться к оконной процедуре тотала в данной ситуации - абсолютно некорректно.
Код: Выделить всё
//25.11.11 Added:
// Send WM_COPYDATA with dwData='G'+256*'W': Same as with 'G'+256*'A', but data is returned as UTF-16 Unicode. dwData of return is 'R'+256*'W' (32/64)
//25.11.11 Added:
// Send WM_COPYDATA with dwData='G'+256*'A' and lpData pointing to command to get back WM_COPYDATA with various info.
// Supported commands
// A: Active side (returns L or R), or two byte command: first byte: L=left, R=right, S=source, T=target.
// Second byte: P=current path, C=list count, I=caret index, N=name of file under caret. dwData of return is 'R'+256*'A' (32/64)
struct SendCopyData_t {
const COPYDATASTRUCT* cds_in;
COPYDATASTRUCT* cds_out;
};
LRESULT __stdcall SendCopyDataProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg==WM_CREATE) {
CREATESTRUCT& cs=*(CREATESTRUCT*)lParam;
SendCopyData_t& scd=*(SendCopyData_t*)cs.lpCreateParams;
HWND htcwnd=FindWindow(L"TTOTAL_CMD", 0);
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM)&scd);
scd.cds_out->dwData=0;
int r=SendMessage(htcwnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)scd.cds_in);
PostQuitMessage(r ? 0 : 1);
}
else if (uMsg==WM_COPYDATA) {
SendCopyData_t& scd=*(SendCopyData_t*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
COPYDATASTRUCT& cds=*(COPYDATASTRUCT*)lParam;
scd.cds_out->dwData=cds.dwData;
scd.cds_out->cbData=cds.cbData;
memcpy(scd.cds_out->lpData, cds.lpData, cds.cbData);
return 1;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
bool SendCopyData(const COPYDATASTRUCT* cds_in, COPYDATASTRUCT* cds_out) {
SendCopyData_t scd={cds_in, cds_out};
const WNDCLASS wc={0, SendCopyDataProc, 0, 0, GetModuleHandle(0), 0, 0, 0, 0, L"SendCopyDataWnd"};
HWND hWnd=CreateWindow((LPWSTR)RegisterClass(&wc), wc.lpszClassName, 0, 0, 0, 0, 0, 0, 0, wc.hInstance, &scd);
if (!hWnd) return 0;
while (1) {
MSG msg;
if (!~GetMessage(&msg, hWnd, 0, 0)) return 0;
if (msg.message==WM_QUIT) return msg.wParam!=0;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Так можно создать временное окно и послать нужное сообщение. Структура
cds_in заполняется как обычно, а структура
cds_out должна содержать адрес и размер буфера, куда будет возвращена строка от тотала, и размер данных при возвращении будет установлен в тот, что вернёт тотал.
Добавлено: Чт июл 05, 2012 11:53
Maximus
MVV
Спасибо. Как то про динамическое создание окна не подумалось.
Пригодится. А то вскоре за AppLoader браться, а там получение текущего пути на костылях :)
Добавлено: Вс июл 22, 2012 14:52
Maximus
Взялся за AppLoader...
Опробовал приведённый выше пример.
Код: Выделить всё
if (!~GetMessage(&msg, hWnd, 0, 0)) return 0;
1. ~ - опечатка?
2. Пока не поставил NULL вместо hWnd висло при втором входе в GetMessage. Чем объяснить?