Подмена "штатного" сетевого окружения при возврате с хоста
Select messages from
# through # FAQ
[/[Print]\]
Goto page Previous  1, 2, 3  Next  :| |:
Total Commander -> Написание плагинов для Total Commander

#16:  Author: VadiMGP PostPosted: Sun Apr 18, 2010 12:50
    —
MVV wrote:
В функции IsForbiddenLevelUp я беру текст из панели в строке состояния, текст в которой есть независимо от режима панели.

Тогда может быть другое ложное срабатывание - при выходе из виртуальной папки. Если, к примеру, ты в Control Panel, то текст панели будет "\\Control Panel\*.*".

#17:  Author: MVVLocation: Ростов-Дон PostPosted: Sun Apr 18, 2010 14:34
    —
VadiMGP wrote:
MVV wrote:
В функции IsForbiddenLevelUp я беру текст из панели в строке состояния, текст в которой есть независимо от режима панели.

Тогда может быть другое ложное срабатывание - при выходе из виртуальной папки. Если, к примеру, ты в Control Panel, то текст панели будет "\\Control Panel\*.*".

Вообще-то, конечно, "\\Панель управления>", но это детали. На этот счет я рекомендовал запоминать имя папки верхнего уровня и действовать только в том случае, если оно не изменилось - моя задача была раскрыть общую идею того, как работать с хуками.

#18:  Author: VadiMGP PostPosted: Sun Apr 18, 2010 14:55
    —
MVV wrote:
Вообще-то, конечно, "\\Панель управления>", но это детали.
Это, разумеется, детали, хотя у меня стоит имено "\\Control Panel\*.*". Smile
В любом случае, я вовсе не отвергаю идею, как таковую, я лишь указываю на некоторые подводные камни, об которые сам бился.

#19:  Author: MVVLocation: Ростов-Дон PostPosted: Sun Apr 18, 2010 21:48
    —
Тут проблема действительна для любой виртуальной папки вообще, так что панель управления - лишь пример.

А под деталями я имел в виду не то, что панель по-русски, а то, что в конце стоит знак больше, а не слэш и звездочка точка звездочка (я ведь беру текст из строки состояния, а не из панели пути).

#20:  Author: HankHank PostPosted: Mon Apr 19, 2010 10:02
    —
Привет, MVV.

Написанное тобой только слегка подрихтовал под Visual c 6.0: в функциях, содержащих L”…, перешёл с обнобайтовым строкам, и двухбайтовые char-типы соответственно заменил на char).
Небольшая описЬка в
Code:

bool IsForbiddenLevelUp()
{
   char buf[1024];
   GetWindowText(stpath, buf, TSIZE(buf));
   if (*(int*)buf!='\\\0\\' || buf[2]=='\\')


Заменена на
Code:

bool IsForbiddenLevelUp()
{
   char buf[1024];
   GetWindowText(stpath, buf, TSIZE(buf));
   if (!((buf[0]=='\\' && buf[1]=='\\') || buf[2]=='\\'))



и… всё заработало почти с пол-оборота. Отдаю должное профессиональной прозрачности написанного кода. И всё это – при вполне удовлетворительной скорости.

Поразмыслив о твоём предложении запрограммировать контроль, когда находимся “в среде моего плагина” – работает хук, вышли – хук сбросить, пришёл к выводу, который озвучивал ранее:
- возможны коллизии, когда в обеих панелях сетевая среда,
- моя “сетевая среда” была создана плагином, вышли из него, но вошли через командную строку, написав ту же магическую строчку cd \\< IP или имя>.
Поэтому решил оставить хук работающим после вызова плагина – хуже не будет.

Остались несколько мелких вопросов:
1. Поскольку имитируем ввод в командную строку “забивкой в клавиатуру” Коммандеру:
Code:

void DoMyAction()
{
   // focus to command line
   SendMessage(hMainWnd, WM_USER + 51, 4003, 0);
   // type of plugin
   SetWindowText(GetFocus(), "cd \\\\\\net");
   // ENTER-pressing
   keybd_event(VK_RETURN, 0, KEYEVENTF_EXTENDEDKEY, 0);
}
,
то в командной строчке успевает мелькнуть пресловутый вызов “cd \\\net”.

Нет ли другого способа “невидимого” вызова пллагина, чтобы “погасить” cd \\\net ?

2. При нахождении “в среде плагина” попытка ввести “cd \\< IP или имя>” не приводит к успеху – надо слегка подриххтовать логику. Ты, впрочем, об этом вскользь уже говорил.

3. До сего момента руки не доходили разобраться с вызовом плагина, как DLL-библиотеки. Поэтому был слегка озадачен, когда увидел, что вызов
Code:

BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)

происходит несколько раз (!) с параметрами ul_reason_for_call 1 и 2 – запуск самого процесса и первого его TREAD'а. Меня, собственно интересовал момент с условием
Code:

ul_reason_for_call==DLL_PROCESS_DETACH
, которого я так и не увидел.
Интересно, при каких условиях Гислер выдаёт такой параметр ? Или этот момент целиком на откупе у операционной системы ?

4. И последнее. Поскольку уже много лет, как профессионально не занимаюсь программированием, инструментарий у меня – дедовский – 6-я версия Visual’а.
Пробовал как-то из любопытства установить MS Visual 2005-ый из журнального диска – “Trial Express”, так был сильно разочарован. Внешне “верстак” выглядит красивее, чем в 6-ке, но в сущности – мЕньшая функциональность, ужасные объёмы базы MSDN. При том, что этот монстр ставится на комп довольно долго. И сносится также весьма небыстро. С месяц-два назад в Сети проходила инфо о выпуске Visual 2010- го.
Что говорят профи ? И, кстати, на чём работает Гислер ?

------------------------
Обновив страничку, увидел, что подключились ещё спецы с комментариями. За что участникам обсуждения – гран мерси.
Немного позже попробую внести соответствующие изменения.

С уважением.

#21:  Author: MVVLocation: Ростов-Дон PostPosted: Mon Apr 19, 2010 10:59
    —
Описек не было. Я писал для Юникод-версии, поэтому везде буквы L. А условие (*(int*)buf!='\\\0\\') эквивалентно тому, что первые два юникод-символа буфера равны слэшу (т.е., байты идут 5C 00 5C 00, что соответствует константе 0x005C005C, или '\\\0\\', хранящейся в первых 4 байтах буфера). Но согласен, твой вариант понятнее (признаю, есть у мя некая извратомания).

Скорость куды больше, чем в системном хуке от AHK. Very Happy


Менять путь, посылая сообщение установки текста полю пути - извращение и маразм. ТК поддерживает специальное оконное сообщение WM_COPYDATA, в котором можно послать путь для перехода. Но надо это делать в фоновом потоке (у меня из плагина не работало, если в основном).

Code:
DWORD __stdcall BackgroundSendData(void* Data) {
   auto_ptr<byte> ash((byte*)Data);
   SendMessage(hMainWnd, WM_COPYDATA, 0, (LPARAM)Data);
   return 0;
}

bool ChangeCurrentDir(const wchar_t* Path, bool NewTab) {
   int length=lstrlen(Path);
   auto_ptr<char> ash(new char[sizeof(COPYDATASTRUCT)+20+2*length]);
   COPYDATASTRUCT* cds=(COPYDATASTRUCT*)ash.get();
   char* data=ash.get()+sizeof(COPYDATASTRUCT);

   cds->dwData='DC';
   cds->lpData=data;
   char* p=data;
   if (Unicode) p+=wsprintfA(p, "\xEF\xBB\xBF");
   p+=WideCharToMultiByte(Unicode ? CP_UTF8 : CP_ACP, 0, Path, length, p, 2*length, 0, 0);
   p+=wsprintfA(p, "\r%cS%s", 0, NewTab ? "T" : "");
   cds->cbData=p-data+1;

   HANDLE thread=CreateThread(0, 0, &BackgroundSendData, ash.release(), 0, 0);
   if (!thread) return 0;

   CloseHandle(thread);
   return 1;
}

Первая функция посылает сообщение WM_COPYDATA, используя переданный ей указатель. Вторая формирует правильное сообщение и вызывает первую в фоновом потоке. То есть, в DoMyAction просто вызываешь ChangeCurrentDir, передав ей путь. Функция ChangeCurrentDir юникодная (опять же, выдрал из исходника VirtualPanel), при использовании юникода (у меня глобальная переменная Unicode при инициализации плагина ставится в 1, если вызывается FsInitW) посылает путь в UTF-8. Параметр NewTab тебе скорее всего не понадобится.


При первой подгрузке к процессу библиотеки функцией LoadLibrary система вызывает DllMain с fdwReason=DLL_PROCESS_ATTACH. Далее, при последующих вызовах LoadLibrary - с DLL_THREAD_ATTACH (заметил, что с таким значением вызывается неоднократно, так что лучше код туда не пихать). Значение DLL_PROCESS_DETACH передается в DllMain при выгрузке последней инстанции библиотеки из процесса - при закрытии ТК или при вызове команды cm_UnloadPlugins (частенько юзаю при отладке или для обновления плагина без перезапуска ТК). Это система делает при последнем вызове FreeLibrary (или же, по идее, при выгрузке процесса, загрузившего библиотечку - тут не знаю, вызовет ли, или молча убьет). К вызову DllMain Гислер отношения не имеет. Все, что ему нужно вызывать - LoadLibrary и FreeLibrary, а потом GetProcAddress для получения адресов экспортируемых функций плагина.


Мне лично больше нравятся 2005-2008 студии, чем 6, в них проблем с юникодом меньше (при установке свойств проекта или отладке, например - можно читать юникод-строки из Watch), лучше оптимизация (например, в реализации стандартной библиотеки "шестерки" дерево чистится путем удаления диапазона от начала до конца дерева - убиться веником, это ж тьма времени на поиск и удаление каждого элемента в отдельности, а в 2005 - умная функция рекурсивного удаления поддеревьев), приспособленность к новым системам. Очень люблю аддон VisualAssist (красит код, удобные функции, правда, триал на месяц, но есть RTKF). Express-версии студии, насколько я понимаю, не имеют PlatformSDK, т.е. могут не иметь нужных заголовочных файлов (не знаю, не ставил). Да, еще удобство в 2005 и выше - скрываемые боковые панели, очень экономит рабочее пространство. 2010 сам хочу попробовать, как будет возможность. Надеюсь, он не будет вешать мою семерку при отладке, как 2008-я (да, есть такое, причем наглухо и при пока непонятных обстоятельствах). Где можно, юзаю 2005-2008, где нельзя - 6 без установки, она справляется с компиляцией моего плагина (хотя Boost уже не тянет).


Гислер пишет ТК на второй дельфе. И я его понимаю. Чем выше версия дельфи, тем больше весит пустой проект (на шестой - в два раза больше, чем в третьей!) - и компоненты. А если не использовать эти извращения, то и второй вполне достаточно. Единственное что хороший компилятор бы ему не помешал наверняка (оптимизация и всё такое), но я не знаю, есть ли для дельфи хорошие компиляторы.

#22:  Author: HankHank PostPosted: Mon Apr 19, 2010 15:58
    —
MVV wrote:
Менять путь, посылая сообщение установки текста полю пути - извращение и маразм. ТК поддерживает специальное оконное сообщение WM_COPYDATA, в котором можно послать путь для перехода. Но надо это делать в фоновом потоке (у меня из плагина не работало, если в основном)...

Дык я тоже чувствую, что как-то уж очень топорно получается. Должен быть выход. Попробовал приладить код с вызовом фонового процесса, получилось так:
Code:

DWORD __stdcall BackgroundSendData(void* Data)
{
   SendMessage(hMainWnd, WM_COPYDATA, 0, (LPARAM) Data);
   return 0;
}

bool ChangeCurrentDir()
{
   COPYDATASTRUCT cds;
   char buffer[]="cd \\\\\\net";
   cds.dwData='DC';
   cds.lpData=&buffer;
   cds.cbData=sizeof(buffer);

   HANDLE thread=CreateThread(0, 0, &BackgroundSendData, &cds, 0, 0);
   if (!thread) return 0;

   CloseHandle(thread);
   return 1;
}

Компиллятор не взбрыкнул. Нужный процесс рождается. Код возврата thread ненулевой. Но эффекта - нет. Так и стоим на месте - на [..]. Подробнее пока не глядел.
Может, свежим взглядом косяк виден сразу ?

И ещё немного оффтопа.
1. Поскольку в основном эксплуатирую всякий софт, а не занимаюсь разработкой, то отстал от жизни. Не очень понимаю перспективы 64-битной судьбы Коммандера. В Сети встречал рассуждения, что, вроде бы для TC особой нужды нет в переходе на 64-ю платформу. Как 32-битное приложение TC вполне справляется со всеми практическими задачами. Мол, есть системные папки под Windows 7, которые напрямую сейчас не доступны, но к ним TC доступ обеспечивает, тем не менее.

2. Также интересен вопрос UNICODE под TC. Ещё в примере реализации FS-плагина TC я обратил внимание на функции API TC, содержащие буковку "w". Насколько учёт UNICODE оказывает практическое влияние на разработку плагинов под TC ? Так ли нельзя без него обойтись ?

#23:  Author: AvadaLocation: Россия, Саратов PostPosted: Mon Apr 19, 2010 16:33
    —
HankHank wrote:
И ещё немного оффтопа.

А вот этого не надо. Правила форума существуют для того, чтобы их соблюдали.
Ответ на первый вопрос — например, здесь. Или здесь. Второй вопрос имеет смысл прояснять в подфоруме по разработке плагинов, к "Общим вопросам" он никак не относится.

#24:  Author: MVVLocation: Ростов-Дон PostPosted: Mon Apr 19, 2010 18:04
    —
HankHank wrote:
Попробовал приладить код с вызовом фонового процесса, получилось так:
Code:

...

Компиллятор не взбрыкнул. Нужный процесс рождается. Код возврата thread ненулевой. Но эффекта - нет. Так и стоим на месте - на [..]. Подробнее пока не глядел.
Может, свежим взглядом косяк виден сразу ?

Ну молодец! Так и до вылета ТК в трубу недалеко. Very Happy

А теперь поясняю, что у тебя происходит. Ты выделил в стеке место для буфера и вписал в него путь. Далее, ты вызываешь фоновую функцию и передаешь ей адрес этого буфера, и не дожидаясь ее завершения выходишь из функции, в которой буфер был выделен, то есть, уничтожаешь его! Что будет? Система при отправке сообщения WM_COPYDATA скопирует указанное число байт по указанному адресу в свой буфер (заметь, там уже может быть что угодно, так как основной поток продолжает работать и использовать стек по своему усмотрению) и отправит сообщение ТК, указав новый адрес буфера (функция позволяет передавать буфера между процессами, поэтому она переписывает данные в буфер в адресном пространстве процесса-получателя). Итак, ТК просто получит мусор. Но хрен его знает, насколько правильно он этот мусор интерпретирует.

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

Еще один момент - плагин у юзера необязательно будет называться "net", имя можно дать любое в настройке FS-плагинов.


Кстати, заметил, что у меня может теряться память, если будет ошибка создания фонового потока. Модернизировал:
Code:
struct BackgroundSendDataData {
   COPYDATASTRUCT CopyData;
   char Raw[0];
};

DWORD __stdcall BackgroundSendData(void* Data) {
   BackgroundSendDataData* bsd=(BackgroundSendDataData*)Data;
   auto_ptr<char> ash((char*)Data);
   SendMessage(hMainWnd, WM_COPYDATA, 0, (LPARAM)&bsd->CopyData);
   return 0;
}

bool ChangeCurrentDir(const wchar_t* Path, bool NewTab) {
   int length=lstrlen(Path);
   auto_ptr<char> ash(new char[sizeof(BackgroundSendDataData)+20+2*length]);
   BackgroundSendDataData* bsd=(BackgroundSendDataData*)ash.get();

   bsd->CopyData.dwData='DC';
   bsd->CopyData.lpData=bsd->Raw;
   char* p=bsd->Raw;
   if (Unicode) p+=wsprintfA(p, "\xEF\xBB\xBF");
   p+=WideCharToMultiByte(Unicode ? CP_UTF8 : CP_ACP, 0, Path, length, p, 2*length, 0, 0);
   p+=wsprintfA(p, "\r%cS%s", 0, NewTab ? "T" : "");
   bsd->CopyData.cbData=p-bsd->Raw+1;

   HANDLE thread=CreateThread(0, 0, &BackgroundSendData, ash.get(), 0, 0);
   if (!thread) return 0;

   ash.release();
   CloseHandle(thread);
   return 1;
}

(заодно сделал структуру буфера более понятной - вначале идет COPYDATASTRUCT, а сразу за ней - буфер произвольной длины, адрес и размер которого она содержит)

И ANSI-версия ChangeCurrentDir (вроде так, проверить нет времени; функция фонового потока общая):
Code:
bool ChangeCurrentDir(const char* Path, bool NewTab) {
   int length=lstrlen(Path);
   auto_ptr<char> ash(new char[sizeof(BackgroundSendDataData)+20+length]);
   BackgroundSendDataData* bsd=(BackgroundSendDataData*)ash.get();

   bsd->CopyData.dwData='DC';
   bsd->CopyData.lpData=bsd->Raw;
   char* p=bsd->Raw;
   p+=wsprintf(p, "%s\r%cS%s", Path, length, 0, NewTab ? "T" : "");
   bsd->CopyData.cbData=p-bsd->Raw+1;

   HANDLE thread=CreateThread(0, 0, &BackgroundSendData, ash.get(), 0, 0);
   if (!thread) return 0;

   ash.release();
   CloseHandle(thread);
   return 1;
}



На оффтоп отвечать не буду, раз модераторы против. Хотя, могу в личку.


HankHank wrote:
При нахождении “в среде плагина” попытка ввести “cd \\< IP или имя>” не приводит к успеху – надо слегка подриххтовать логику. Ты, впрочем, об этом вскользь уже говорил.

Заметил этот абзац - и возник вопрос. Ты вводишь команду для перехода в сетевую папку, находясь в папке плагина, и оно не работает (в ТК команда cd не работает в папках FS-плагинов; ты должен вручную реализовать обработку команды cd и изменить текущую папку - например, вызвав ChangeCurrentDir, как делает моя VirtualPanel), или ты пытаешься обойти хук с помощью команды cd (я говорил как раз об этом - не нужно блокировать команду cd, раз юзер пишет ее, у него есть на то причины), или же этот абзац тоже подразумевает установку текста командной строки и выполнение для смены папки (маловероятно, что ты имел в виду это, но вдруг)?

#25:  Author: HankHank PostPosted: Tue Apr 20, 2010 09:16
    —
Тока появился на работе. Ничего ещё не успел, а в форуме – такая радость – детальный ответ. Very Happy Отвечу тогда сразу, а позже уже - эксперименты.
MVV wrote:

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

Было подозрение, что может повлиять. Поскольку программирую эпизодически, и нет качественной документации под рукой, лезу в Тырнет. Где-то нашёл, что функция передачи сообщений с указанным параметром WM_COPYDATA работает синхронно, т.е. ждёт, когда дойдут параметры в hMainWnd. И перенёс бездумно увиденное. Не учёл процесса.

MVV wrote:

Еще один момент - плагин у юзера необязательно будет называться "net", имя можно дать любое в настройке FS-плагинов.

Это точно. Но пока что надо получить работоспособную программулину. Причешу позже.

MVV wrote:

Кстати, заметил, что у меня может теряться память, если будет ошибка создания фонового потока. Модернизировал:…

Беру на вооружение.

MVV wrote:

На оффтоп отвечать не буду, раз модераторы против. Хотя, могу в личку.

Не будем хулиганить. Напиши в личку. Найдётся ещё вопрос-другой. Может, и я на что сгожусь.

MVV wrote:

HankHank wrote:
При нахождении “в среде плагина” попытка ввести “cd \\< IP или имя>” не приводит к успеху – надо слегка подриххтовать логику. Ты, впрочем, об этом вскользь уже говорил.

…Ты вводишь команду для перехода в сетевую папку, находясь в папке плагина, и оно не работает (в ТК команда cd не работает в папках FS-плагинов; ты должен вручную реализовать обработку команды cd и изменить текущую папку - например, вызвав ChangeCurrentDir, как делает моя VirtualPanel), или ты пытаешься обойти хук с помощью команды cd (я говорил как раз об этом - не нужно блокировать команду cd, раз юзер пишет ее, у него есть на то причины), или же этот абзац тоже подразумевает установку текста командной строки и выполнение для смены папки (маловероятно, что ты имел в виду это, но вдруг)?

Пользователю невдомёк, что командная строка работает по-разному в плагине и без него. Поэтому не хотелось бы забивать ему мозги ещё и такими деталями. И надо бы это как-то реализовать... Да, и в принципе, возможна ситуёвина, когда в обеих панелях уже плагин, а пользователь ещё и в командной строке набирает типа cd \\<хост>.

#26:  Author: MVVLocation: Ростов-Дон PostPosted: Tue Apr 20, 2010 10:45
    —
HankHank wrote:
Пользователю невдомёк, что командная строка работает по-разному в плагине и без него. Поэтому не хотелось бы забивать ему мозги ещё и такими деталями. И надо бы это как-то реализовать... Да, и в принципе, возможна ситуёвина, когда в обеих панелях уже плагин, а пользователь ещё и в командной строке набирает типа cd \\<хост>.

Вот для этого и нужно обрабатывать команду cd, выдирать ее параметр и устанавливать как путь - делается элементарно. Я лично проверяю, есть ли кавычка в начале параметра - если есть, считаю путем то, что в кавычках, если нету - считаю путем весь параметр команды cd (за исключением пробелов, идущих в самом конце строки):
Code:
cd "путь\путь" не путь 
cd путь\п у т ь\путь путь     


В функции FsExecuteFileW смотришь, если строка Verb начинается с "quote cd " (лучше сравнивать без учета регистра) - и действуешь, анализируя параметр команды (то есть, строку Verb+9).

#27:  Author: AvadaLocation: Россия, Саратов PostPosted: Tue Apr 20, 2010 11:35
    —
HankHank
MVV
Мне кажется, тему лучше перенести в подфорум "Написание плагинов", поскольку обсуждаемые вопросы — достаточно специфические. Нет возражений?

#28:  Author: HankHank PostPosted: Tue Apr 20, 2010 11:41
    —
Avada:
Переносите, конечно.

MVV:
В личке посмотри.

 !  Avada:
Тема перенесена.

#29:  Author: MVVLocation: Ростов-Дон PostPosted: Tue Apr 20, 2010 15:03
    —
Avada wrote:
Мне кажется, тему лучше перенести в подфорум "Написание плагинов", поскольку обсуждаемые вопросы — достаточно специфические. Нет возражений?

У меня у самого такая мысль была - полотна исходников явно не для общего подфорума.

HankHank wrote:
В личке посмотри.

На вопросы по теме отвечу тут, может, кому-то пригодится. Надеюсь, не будешь сильно возражать.

HankHank wrote:
Покуролесил с вчерашним кодом в свете твоего сообщения о динамической памяти:
Code:

DWORD __stdcall BackgroundSendData(void* Data)
{
   int ii=SendMessage(hMainWnd, WM_COPYDATA, 0, (LPARAM) Data);
   return 0;
}

static COPYDATASTRUCT cds;
static char buffer[]="cd \\\\\\net";

bool ChangeCurrentDir()
{
   cds.dwData='DC';
   cds.lpData=&buffer;
   cds.cbData=sizeof(buffer);

   HANDLE thread=CreateThread(0, 0, &BackgroundSendData, &cds, 0, 0);
   if (!thread) return 0;

   CloseHandle(thread);
   return 1;
}

Передаваемая процессу память никуда теперь не исчезает. Но код проще. (Пробовал static char buffer[]="cd \\\\\\net" и static char buffer[]="\\\\\\net".)
Но что-то ничего не выходит…

Конечно, код проще. Тебе ж не нужно каждый раз менять содержимое буфера, поэтому и статический буфер подойдет.
А почему не работает, ща объясню. Видимо, ты плохо разобрался с форматом буфера для WM_COPYDATA, который ожидает ТК. Вот он:
Code:
<first_path>\r<second_path>\0<flags>

Флаги: 'T' - в новой вкладке, 'S' - менять пути активной и неактивной панелей вместо левой и правой.

Таким образом, правильный буфер:
Code:
static char cdnet[]="\\\\\\net\r\0S";

(то есть, изменить путь на \\\net в активной панели)

Но размер такого буфера уже функцией strlen не определишь - внутри есть нулевой символ. Поэтому либо TSIZE(cdnet), либо ручками циферку. И циферка обязательно должна включать нулевой байт в конце буфера - иначе ТК может хрен знает куда зайти в его поисках и набрать себе левых флагов из блока памяти за пределами буфера (я с таким уже сталкивался, обсуждение тут).

#30:  Author: HankHank PostPosted: Tue Apr 20, 2010 15:46
    —
MVV wrote:
Видимо, ты плохо разобрался с форматом буфера для WM_COPYDATA, который ожидает ТК. Вот он:
Code:
<first_path>\r<second_path>\0<flags>

Флаги: 'T' - в новой вкладке, 'S' - менять пути активной и неактивной панелей вместо левой и правой.

Так ясно. По началу строчка wsprintf показалась заумной. И я решил, что хватит с меня и первого параметра с путём, куда надо переключить активную панель. А откуда эта инфо ?

MVV wrote:
Таким образом, правильный буфер:
Code:
static char cdnet[]="\\\\\\net\r\0S";


Да, так работает. Буду ковать дальше.

Ещё заметил такую деталь. Может, интересно кому.
Вот здесь http://www.firststeps.ru/mfc/winapi/win/r.php?126 прочитал про WM_COPYDATA:
Quote:
Если принимающая программа обрабатывает это сообщение, она должна возвратить значение ИСТИНА (TRUE); в противном случае она должна возвратить - ЛОЖЬ (FALSE).

У меня же передача параметров срабатывает, происходит переход куда требуется, но SendMessage возвращает при этом 0.



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


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

Goto page Previous  1, 2, 3  Next  :| |:
Page 2 of 3

Powered by phpBB © 2001, 2005 phpBB Group