Путь противоположной панели
Select messages from
# through # FAQ
[/[Print]\]

Total Commander -> Написание плагинов для Total Commander

#1: Путь противоположной панели Author: MaximusLocation: Украина, Кировоградская обл., г. Знаменка PostPosted: Mon Jul 02, 2012 12:54
    —
Знает ли кто способы получения пути в противоположной панели TC из WFX-плагина?
Естественно напрашивается вывод использовать EnumChildWindows с поиском контрола по имени TPathPanel, текст которого не содержит в начале три черты \\\.
Но может есть способ поровнее?


Last edited by Maximus on Tue Jul 03, 2012 01:17; edited 1 time in total

#2:  Author: MVVLocation: Ростов-Дон PostPosted: Mon Jul 02, 2012 23:57
    —
Code:
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-плагинов не вижу необходимости узнавать путь вне вызовов тоталом функций плагина.

#3:  Author: MaximusLocation: Украина, Кировоградская обл., г. Знаменка PostPosted: Tue Jul 03, 2012 01:16
    —
MVV
Я так и знал, что ты мне поможешь :)
Похоже на то, что нужно. Даже нашёл твой пример на офсайте.

А что за выражение такое?
Quote:
dwData='G'+256*'A'

Зачем было писать так интересно?
В твоём примере всё просто
Quote:
cds.dwData='AG';


Quote:
А вообще, во время вызова какой конкретно функции это нужно? В силу пассивности WFX-плагинов не вижу необходимости узнавать путь вне вызовов тоталом функций плагина.

Телефонная книга. Хочу завести псевдофайл при запуске которого будет выполняться экспорт всех контактов в один файл. Будет открываться диалог сохранения, куда и буду подставлять путь противоположной панели, если он окажется корректным.

Собственно я уже научился делать это описанным мною выше способом, а теперь хочу сделать то же, но правильно :)

#4:  Author: MVVLocation: Ростов-Дон PostPosted: Tue Jul 03, 2012 10:44
    —
Maximus wrote:
А что за выражение такое?
Quote:
dwData='G'+256*'A'

Зачем было писать так интересно?
В твоём примере всё просто
Quote:
cds.dwData='AG';

Ну, то писал Гислер, можно было записать как 'G'+('A'<<8). А я знаю, что можно писать многосимвольные константы, заключая их в одиночные кавычки и инвертируя порядок, потому пишу просто 'AG' Smile Кстати, некоторые компиляторы (гнутый, например) выдают ахтунг на такую запись, хотя и компилируют правильно.
Цель достигается и так и так - получить в данном примере в 4 байтах памяти этой переменной строку "GA" - понять бы, что означает буква 'G' ('A' означает ANSI). Для смены каталога надо получить там строку "CD" (для чего я использую запись 'DC'). У себя для Virtual Panel я использую 'PV' (строка "VP"), а для юникода - 'P\0V' (строка L"VP" без терминатора).

Ну да, в принципе, в FsExecuteFile путь неактивной панели никак не получить прямым способом. А может для экспорта лучше использовать копирование какого-нибудь псевдофайла в неактивную панель? По-моему, вполне логично для экспорта использовать копирование. Тогда юзер сам выберет путь прямо в тотальном диалоге, и тотал укажет его тебе, вызвав функцию FsGetFile.


Last edited by MVV on Tue Jul 03, 2012 11:15; edited 2 times in total

#5:  Author: MaximusLocation: Украина, Кировоградская обл., г. Знаменка PostPosted: Tue Jul 03, 2012 10:55
    —
MVV wrote:
А может для экспорта лучше использовать копирование какого-нибудь псевдофайла в неактивную панель? По-моему, вполне логично для экспорта использовать копирование. Тогда юзер сам выберет путь прямо в тотальном диалоге, и тотал укажет его тебе, вызвав функцию FsGetFile.

Будет и то и другое. Просто для пользователя понятнее будет запуск псевдофайла с именем "Экспорт всего на свете", чем копирование файла contacts.vcf. Поэтому функционал будет продублирован - для запуска этого элемента и для его копирования.

#6:  Author: MVVLocation: Ростов-Дон PostPosted: Tue Jul 03, 2012 11:17
    —
Ну в принципе да, можно и продублировать. Но окошки искать, конечно, занятие не из приятных. Особенно с учетом того, что в разных версиях иерархия слегка различается. Не говоря уже о 64-битной версии, где почти все дочерние окна имеют имя класса Window.

#7:  Author: MaximusLocation: Украина, Кировоградская обл., г. Знаменка PostPosted: Tue Jul 03, 2012 11:35
    —
MVV wrote:
Но окошки искать, конечно, занятие не из приятных. Особенно с учетом того, что в разных версиях иерархия слегка различается. Не говоря уже о 64-битной версии, где почти все дочерние окна имеют имя класса Window.

Вот потому и хотелось сделать всё не костылями, а как положено.

#8:  Author: MaximusLocation: Украина, Кировоградская обл., г. Знаменка PostPosted: Wed Jul 04, 2012 22:05
    —
MVV
Чтото не идет у меня WM_COPYDATA. TC ничего не отвечает. Не сталкивался ли ты с подобным во время отладки?

Добавлено спустя 1 час 22 минуты:

SendMessage возвращает false.
Пытаюсь послать сообщение в своё же приложение - результат тот же.

Добавлено спустя 28 минут:

Внезапно всё заработало. Причины неработы непонятны. Вероятно, что файервол-антивирус. Такое вообще возможно? Заработало через некоторое время после отключения. Но сейчас работает и при включенном.

А можно ли сообщение WM_COPYDATA каким-то образом обработать не в оконной процедуре, а в самой DLL?

#9:  Author: MVVLocation: Ростов-Дон PostPosted: Thu Jul 05, 2012 10:00
    —
Пардон, что значит "не в оконной процедуре, а в самой DLL"? Если у тебя оконная процедура твоего окна в DLL, то можно и нужно.

#10:  Author: MaximusLocation: Украина, Кировоградская обл., г. Знаменка PostPosted: Thu Jul 05, 2012 10:21
    —
Я имел в виду, если DLL не создает никаких окон.

#11:  Author: MVVLocation: Ростов-Дон PostPosted: Thu Jul 05, 2012 11:25
    —
А тебе просто необходимо окно, чтобы получить ответ, иначе никак. Подцепляться к оконной процедуре тотала в данной ситуации - абсолютно некорректно.

Code:
//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 должна содержать адрес и размер буфера, куда будет возвращена строка от тотала, и размер данных при возвращении будет установлен в тот, что вернёт тотал.

#12:  Author: MaximusLocation: Украина, Кировоградская обл., г. Знаменка PostPosted: Thu Jul 05, 2012 11:53
    —
MVV
Спасибо. Как то про динамическое создание окна не подумалось.
Пригодится. А то вскоре за AppLoader браться, а там получение текущего пути на костылях :)

#13:  Author: MaximusLocation: Украина, Кировоградская обл., г. Знаменка PostPosted: Sun Jul 22, 2012 14:52
    —
Взялся за AppLoader...
Опробовал приведённый выше пример.
Code:
      if (!~GetMessage(&msg, hWnd, 0, 0)) return 0;

1. ~ - опечатка?
2. Пока не поставил NULL вместо hWnd висло при втором входе в GetMessage. Чем объяснить?



Total Commander -> Написание плагинов для Total Commander


output generated using printer-friendly topic mod. All times are GMT + 4 Hours

Page 1 of 1

Powered by phpBB © 2001, 2005 phpBB Group