Total Commander Forum Index Total Commander
Форум поддержки пользователей Total Commander
Сайты: Все о Total Commander | Totalcmd.net | Ghisler.com | RU.TCKB
 
 RulesRules   SearchSearch   FAQFAQ   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Подмена "штатного" сетевого окружения при возврате с хоста
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander printer-friendly view
View previous topic :: View next topic  
Author Message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Sun Apr 18, 2010 12:50    Post subject: Reply with quote

MVV wrote:
В функции IsForbiddenLevelUp я беру текст из панели в строке состояния, текст в которой есть независимо от режима панели.

Тогда может быть другое ложное срабатывание - при выходе из виртуальной папки. Если, к примеру, ты в Control Panel, то текст панели будет "\\Control Panel\*.*".
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Sun Apr 18, 2010 14:34    Post subject: Reply with quote

VadiMGP wrote:
MVV wrote:
В функции IsForbiddenLevelUp я беру текст из панели в строке состояния, текст в которой есть независимо от режима панели.

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

Вообще-то, конечно, "\\Панель управления>", но это детали. На этот счет я рекомендовал запоминать имя папки верхнего уровня и действовать только в том случае, если оно не изменилось - моя задача была раскрыть общую идею того, как работать с хуками.
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
VadiMGP



Joined: 21 Mar 2007
Posts: 1625

Post (Separately) Posted: Sun Apr 18, 2010 14:55    Post subject: Reply with quote

MVV wrote:
Вообще-то, конечно, "\\Панель управления>", но это детали.
Это, разумеется, детали, хотя у меня стоит имено "\\Control Panel\*.*". Smile
В любом случае, я вовсе не отвергаю идею, как таковую, я лишь указываю на некоторые подводные камни, об которые сам бился.
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Sun Apr 18, 2010 21:48    Post subject: Reply with quote

Тут проблема действительна для любой виртуальной папки вообще, так что панель управления - лишь пример.

А под деталями я имел в виду не то, что панель по-русски, а то, что в конце стоит знак больше, а не слэш и звездочка точка звездочка (я ведь беру текст из строки состояния, а не из панели пути).
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
HankHank



Joined: 15 Apr 2010
Posts: 39

Post (Separately) Posted: Mon Apr 19, 2010 10:02    Post subject: Reply with quote

Привет, 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- го.
Что говорят профи ? И, кстати, на чём работает Гислер ?

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

С уважением.
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Mon Apr 19, 2010 10:59    Post subject: Reply with quote

Описек не было. Я писал для Юникод-версии, поэтому везде буквы 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 уже не тянет).


Гислер пишет ТК на второй дельфе. И я его понимаю. Чем выше версия дельфи, тем больше весит пустой проект (на шестой - в два раза больше, чем в третьей!) - и компоненты. А если не использовать эти извращения, то и второй вполне достаточно. Единственное что хороший компилятор бы ему не помешал наверняка (оптимизация и всё такое), но я не знаю, есть ли для дельфи хорошие компиляторы.
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
HankHank



Joined: 15 Apr 2010
Posts: 39

Post (Separately) Posted: Mon Apr 19, 2010 15:58    Post subject: Reply with quote

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 ? Так ли нельзя без него обойтись ?
Back to top
View user's profile Send private message
Avada



Joined: 01 Aug 2008
Posts: 10236
Location: Россия, Саратов

Post (Separately) Posted: Mon Apr 19, 2010 16:33    Post subject: Reply with quote

HankHank wrote:
И ещё немного оффтопа.

А вот этого не надо. Правила форума существуют для того, чтобы их соблюдали.
Ответ на первый вопрос — например, здесь. Или здесь. Второй вопрос имеет смысл прояснять в подфоруме по разработке плагинов, к "Общим вопросам" он никак не относится.
_________________
Даже самая богатая фантазия
Не представит себе наши безобразия.
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Mon Apr 19, 2010 18:04    Post subject: Reply with quote

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, раз юзер пишет ее, у него есть на то причины), или же этот абзац тоже подразумевает установку текста командной строки и выполнение для смены папки (маловероятно, что ты имел в виду это, но вдруг)?
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
HankHank



Joined: 15 Apr 2010
Posts: 39

Post (Separately) Posted: Tue Apr 20, 2010 09:16    Post subject: Reply with quote

Тока появился на работе. Ничего ещё не успел, а в форуме – такая радость – детальный ответ. 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 \\<хост>.
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Tue Apr 20, 2010 10:45    Post subject: Reply with quote

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

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


В функции FsExecuteFileW смотришь, если строка Verb начинается с "quote cd " (лучше сравнивать без учета регистра) - и действуешь, анализируя параметр команды (то есть, строку Verb+9).
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
Avada



Joined: 01 Aug 2008
Posts: 10236
Location: Россия, Саратов

Post (Separately) Posted: Tue Apr 20, 2010 11:35    Post subject: Reply with quote

HankHank
MVV
Мне кажется, тему лучше перенести в подфорум "Написание плагинов", поскольку обсуждаемые вопросы — достаточно специфические. Нет возражений?
_________________
Даже самая богатая фантазия
Не представит себе наши безобразия.
Back to top
View user's profile Send private message
HankHank



Joined: 15 Apr 2010
Posts: 39

Post (Separately) Posted: Tue Apr 20, 2010 11:41    Post subject: Reply with quote

Avada:
Переносите, конечно.

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

 !  Avada:
Тема перенесена.
Back to top
View user's profile Send private message
MVV



Joined: 15 Oct 2009
Posts: 4811
Location: Ростов-Дон

Post (Separately) Posted: Tue Apr 20, 2010 15:03    Post subject: Reply with quote

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), либо ручками циферку. И циферка обязательно должна включать нулевой байт в конце буфера - иначе ТК может хрен знает куда зайти в его поисках и набрать себе левых флагов из блока памяти за пределами буфера (я с таким уже сталкивался, обсуждение тут).
_________________
TCFS2 + TCFS2Tools: Полноэкранный режим и многое другое (обсуждение)
WINCMD.RU: AskParam, CopyTree, NTLinks, Sudo, VirtualPanel…
Back to top
View user's profile Send private message
HankHank



Joined: 15 Apr 2010
Posts: 39

Post (Separately) Posted: Tue Apr 20, 2010 15:46    Post subject: Reply with quote

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.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Total Commander Forum Index -> Написание плагинов для Total Commander All times are GMT + 4 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group