Тогда может быть другое ложное срабатывание - при выходе из виртуальной папки. Если, к примеру, ты в Control Panel, то текст панели будет "\\Control Panel\*.*".MVV писал(а):В функции IsForbiddenLevelUp я беру текст из панели в строке состояния, текст в которой есть независимо от режима панели.
Подмена "штатного" сетевого окружения при возврате с хоста
Модераторы: d-view, Моторокер, Avada, CaptainFlint, Nik
Вообще-то, конечно, "\\Панель управления>", но это детали. На этот счет я рекомендовал запоминать имя папки верхнего уровня и действовать только в том случае, если оно не изменилось - моя задача была раскрыть общую идею того, как работать с хуками.VadiMGP писал(а):Тогда может быть другое ложное срабатывание - при выходе из виртуальной папки. Если, к примеру, ты в Control Panel, то текст панели будет "\\Control Panel\*.*".MVV писал(а):В функции IsForbiddenLevelUp я беру текст из панели в строке состояния, текст в которой есть независимо от режима панели.
Привет, MVV.
Написанное тобой только слегка подрихтовал под Visual c 6.0: в функциях, содержащих L”…, перешёл с обнобайтовым строкам, и двухбайтовые char-типы соответственно заменил на char).
Небольшая описЬка в
Заменена на
и… всё заработало почти с пол-оборота. Отдаю должное профессиональной прозрачности написанного кода. И всё это – при вполне удовлетворительной скорости.
Поразмыслив о твоём предложении запрограммировать контроль, когда находимся “в среде моего плагина” – работает хук, вышли – хук сбросить, пришёл к выводу, который озвучивал ранее:
- возможны коллизии, когда в обеих панелях сетевая среда,
- моя “сетевая среда” была создана плагином, вышли из него, но вошли через командную строку, написав ту же магическую строчку cd \\< IP или имя>.
Поэтому решил оставить хук работающим после вызова плагина – хуже не будет.
Остались несколько мелких вопросов:
1. Поскольку имитируем ввод в командную строку “забивкой в клавиатуру” Коммандеру:,
то в командной строчке успевает мелькнуть пресловутый вызов “cd \\\net”.
Нет ли другого способа “невидимого” вызова пллагина, чтобы “погасить” cd \\\net ?
2. При нахождении “в среде плагина” попытка ввести “cd \\< IP или имя>” не приводит к успеху – надо слегка подриххтовать логику. Ты, впрочем, об этом вскользь уже говорил.
3. До сего момента руки не доходили разобраться с вызовом плагина, как DLL-библиотеки. Поэтому был слегка озадачен, когда увидел, что вызов
происходит несколько раз (!) с параметрами ul_reason_for_call 1 и 2 – запуск самого процесса и первого его TREAD'а. Меня, собственно интересовал момент с условием
, которого я так и не увидел.
Интересно, при каких условиях Гислер выдаёт такой параметр ? Или этот момент целиком на откупе у операционной системы ?
4. И последнее. Поскольку уже много лет, как профессионально не занимаюсь программированием, инструментарий у меня – дедовский – 6-я версия Visual’а.
Пробовал как-то из любопытства установить MS Visual 2005-ый из журнального диска – “Trial Express”, так был сильно разочарован. Внешне “верстак” выглядит красивее, чем в 6-ке, но в сущности – мЕньшая функциональность, ужасные объёмы базы MSDN. При том, что этот монстр ставится на комп довольно долго. И сносится также весьма небыстро. С месяц-два назад в Сети проходила инфо о выпуске Visual 2010- го.
Что говорят профи ? И, кстати, на чём работает Гислер ?
------------------------
Обновив страничку, увидел, что подключились ещё спецы с комментариями. За что участникам обсуждения – гран мерси.
Немного позже попробую внести соответствующие изменения.
С уважением.
Написанное тобой только слегка подрихтовал под Visual c 6.0: в функциях, содержащих L”…, перешёл с обнобайтовым строкам, и двухбайтовые char-типы соответственно заменил на char).
Небольшая описЬка в
Код: Выделить всё
bool IsForbiddenLevelUp()
{
char buf[1024];
GetWindowText(stpath, buf, TSIZE(buf));
if (*(int*)buf!='\\\0\\' || buf[2]=='\\')
…
Код: Выделить всё
bool IsForbiddenLevelUp()
{
char buf[1024];
GetWindowText(stpath, buf, TSIZE(buf));
if (!((buf[0]=='\\' && buf[1]=='\\') || buf[2]=='\\'))
…
Поразмыслив о твоём предложении запрограммировать контроль, когда находимся “в среде моего плагина” – работает хук, вышли – хук сбросить, пришёл к выводу, который озвучивал ранее:
- возможны коллизии, когда в обеих панелях сетевая среда,
- моя “сетевая среда” была создана плагином, вышли из него, но вошли через командную строку, написав ту же магическую строчку cd \\< IP или имя>.
Поэтому решил оставить хук работающим после вызова плагина – хуже не будет.
Остались несколько мелких вопросов:
1. Поскольку имитируем ввод в командную строку “забивкой в клавиатуру” Коммандеру:
Код: Выделить всё
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-библиотеки. Поэтому был слегка озадачен, когда увидел, что вызов
Код: Выделить всё
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
Код: Выделить всё
ul_reason_for_call==DLL_PROCESS_DETACH
Интересно, при каких условиях Гислер выдаёт такой параметр ? Или этот момент целиком на откупе у операционной системы ?
4. И последнее. Поскольку уже много лет, как профессионально не занимаюсь программированием, инструментарий у меня – дедовский – 6-я версия Visual’а.
Пробовал как-то из любопытства установить MS Visual 2005-ый из журнального диска – “Trial Express”, так был сильно разочарован. Внешне “верстак” выглядит красивее, чем в 6-ке, но в сущности – мЕньшая функциональность, ужасные объёмы базы MSDN. При том, что этот монстр ставится на комп довольно долго. И сносится также весьма небыстро. С месяц-два назад в Сети проходила инфо о выпуске Visual 2010- го.
Что говорят профи ? И, кстати, на чём работает Гислер ?
------------------------
Обновив страничку, увидел, что подключились ещё спецы с комментариями. За что участникам обсуждения – гран мерси.
Немного позже попробую внести соответствующие изменения.
С уважением.
Описек не было. Я писал для Юникод-версии, поэтому везде буквы L. А условие (*(int*)buf!='\\\0\\') эквивалентно тому, что первые два юникод-символа буфера равны слэшу (т.е., байты идут 5C 00 5C 00, что соответствует константе 0x005C005C, или '\\\0\\', хранящейся в первых 4 байтах буфера). Но согласен, твой вариант понятнее (признаю, есть у мя некая извратомания).
Скорость куды больше, чем в системном хуке от AHK.
Менять путь, посылая сообщение установки текста полю пути - извращение и маразм. ТК поддерживает специальное оконное сообщение WM_COPYDATA, в котором можно послать путь для перехода. Но надо это делать в фоновом потоке (у меня из плагина не работало, если в основном).
Первая функция посылает сообщение 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 уже не тянет).
Гислер пишет ТК на второй дельфе. И я его понимаю. Чем выше версия дельфи, тем больше весит пустой проект (на шестой - в два раза больше, чем в третьей!) - и компоненты. А если не использовать эти извращения, то и второй вполне достаточно. Единственное что хороший компилятор бы ему не помешал наверняка (оптимизация и всё такое), но я не знаю, есть ли для дельфи хорошие компиляторы.
Скорость куды больше, чем в системном хуке от AHK.
Менять путь, посылая сообщение установки текста полю пути - извращение и маразм. ТК поддерживает специальное оконное сообщение WM_COPYDATA, в котором можно послать путь для перехода. Но надо это делать в фоновом потоке (у меня из плагина не работало, если в основном).
Код: Выделить всё
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;
}При первой подгрузке к процессу библиотеки функцией 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 уже не тянет).
Гислер пишет ТК на второй дельфе. И я его понимаю. Чем выше версия дельфи, тем больше весит пустой проект (на шестой - в два раза больше, чем в третьей!) - и компоненты. А если не использовать эти извращения, то и второй вполне достаточно. Единственное что хороший компилятор бы ему не помешал наверняка (оптимизация и всё такое), но я не знаю, есть ли для дельфи хорошие компиляторы.
Дык я тоже чувствую, что как-то уж очень топорно получается. Должен быть выход. Попробовал приладить код с вызовом фонового процесса, получилось так:MVV писал(а):Менять путь, посылая сообщение установки текста полю пути - извращение и маразм. ТК поддерживает специальное оконное сообщение WM_COPYDATA, в котором можно послать путь для перехода. Но надо это делать в фоновом потоке (у меня из плагина не работало, если в основном)...
Код: Выделить всё
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;
}
Может, свежим взглядом косяк виден сразу ?
И ещё немного оффтопа.
1. Поскольку в основном эксплуатирую всякий софт, а не занимаюсь разработкой, то отстал от жизни. Не очень понимаю перспективы 64-битной судьбы Коммандера. В Сети встречал рассуждения, что, вроде бы для TC особой нужды нет в переходе на 64-ю платформу. Как 32-битное приложение TC вполне справляется со всеми практическими задачами. Мол, есть системные папки под Windows 7, которые напрямую сейчас не доступны, но к ним TC доступ обеспечивает, тем не менее.
2. Также интересен вопрос UNICODE под TC. Ещё в примере реализации FS-плагина TC я обратил внимание на функции API TC, содержащие буковку "w". Насколько учёт UNICODE оказывает практическое влияние на разработку плагинов под TC ? Так ли нельзя без него обойтись ?
А вот этого не надо. Правила форума существуют для того, чтобы их соблюдали.HankHank писал(а):И ещё немного оффтопа.
Ответ на первый вопрос — например, здесь. Или здесь. Второй вопрос имеет смысл прояснять в подфоруме по разработке плагинов, к "Общим вопросам" он никак не относится.
Даже самая богатая фантазия
Не представит себе наши безобразия.
Не представит себе наши безобразия.
Ну молодец! Так и до вылета ТК в трубу недалеко.HankHank писал(а):Попробовал приладить код с вызовом фонового процесса, получилось так:Компиллятор не взбрыкнул. Нужный процесс рождается. Код возврата thread ненулевой. Но эффекта - нет. Так и стоим на месте - на [..]. Подробнее пока не глядел.Код: Выделить всё
...
Может, свежим взглядом косяк виден сразу ?
А теперь поясняю, что у тебя происходит. Ты выделил в стеке место для буфера и вписал в него путь. Далее, ты вызываешь фоновую функцию и передаешь ей адрес этого буфера, и не дожидаясь ее завершения выходишь из функции, в которой буфер был выделен, то есть, уничтожаешь его! Что будет? Система при отправке сообщения WM_COPYDATA скопирует указанное число байт по указанному адресу в свой буфер (заметь, там уже может быть что угодно, так как основной поток продолжает работать и использовать стек по своему усмотрению) и отправит сообщение ТК, указав новый адрес буфера (функция позволяет передавать буфера между процессами, поэтому она переписывает данные в буфер в адресном пространстве процесса-получателя). Итак, ТК просто получит мусор. Но хрен его знает, насколько правильно он этот мусор интерпретирует.
Выход? Выделять память динамически. Ты убрал юникод из функции - да, это тебе не нужно. Но советую вернуть назад динамическое выделение памяти, без него передавать что-либо в другой поток не советую. В моих функциях память выделялась динамически и передавался указатель на выделенный буфер, который затем освобождался функцией в фоновом потоке.
Еще один момент - плагин у юзера необязательно будет называться "net", имя можно дать любое в настройке FS-плагинов.
Кстати, заметил, что у меня может теряться память, если будет ошибка создания фонового потока. Модернизировал:
Код: Выделить всё
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;
}И ANSI-версия ChangeCurrentDir (вроде так, проверить нет времени; функция фонового потока общая):
Код: Выделить всё
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;
}На оффтоп отвечать не буду, раз модераторы против. Хотя, могу в личку.
Заметил этот абзац - и возник вопрос. Ты вводишь команду для перехода в сетевую папку, находясь в папке плагина, и оно не работает (в ТК команда cd не работает в папках FS-плагинов; ты должен вручную реализовать обработку команды cd и изменить текущую папку - например, вызвав ChangeCurrentDir, как делает моя VirtualPanel), или ты пытаешься обойти хук с помощью команды cd (я говорил как раз об этом - не нужно блокировать команду cd, раз юзер пишет ее, у него есть на то причины), или же этот абзац тоже подразумевает установку текста командной строки и выполнение для смены папки (маловероятно, что ты имел в виду это, но вдруг)?HankHank писал(а):При нахождении “в среде плагина” попытка ввести “cd \\< IP или имя>” не приводит к успеху – надо слегка подриххтовать логику. Ты, впрочем, об этом вскользь уже говорил.
Тока появился на работе. Ничего ещё не успел, а в форуме – такая радость – детальный ответ.
Отвечу тогда сразу, а позже уже - эксперименты.
Было подозрение, что может повлиять. Поскольку программирую эпизодически, и нет качественной документации под рукой, лезу в Тырнет. Где-то нашёл, что функция передачи сообщений с указанным параметром WM_COPYDATA работает синхронно, т.е. ждёт, когда дойдут параметры в hMainWnd. И перенёс бездумно увиденное. Не учёл процесса.MVV писал(а): Ты выделил в стеке место для буфера и вписал в него путь. Далее, ты вызываешь фоновую функцию и передаешь ей адрес этого буфера, и не дожидаясь ее завершения выходишь из функции, в которой буфер был выделен, то есть, уничтожаешь его!
Это точно. Но пока что надо получить работоспособную программулину. Причешу позже.MVV писал(а): Еще один момент - плагин у юзера необязательно будет называться "net", имя можно дать любое в настройке FS-плагинов.
Беру на вооружение.MVV писал(а): Кстати, заметил, что у меня может теряться память, если будет ошибка создания фонового потока. Модернизировал:…
Не будем хулиганить. Напиши в личку. Найдётся ещё вопрос-другой. Может, и я на что сгожусь.MVV писал(а): На оффтоп отвечать не буду, раз модераторы против. Хотя, могу в личку.
Пользователю невдомёк, что командная строка работает по-разному в плагине и без него. Поэтому не хотелось бы забивать ему мозги ещё и такими деталями. И надо бы это как-то реализовать... Да, и в принципе, возможна ситуёвина, когда в обеих панелях уже плагин, а пользователь ещё и в командной строке набирает типа cd \\<хост>.MVV писал(а):…Ты вводишь команду для перехода в сетевую папку, находясь в папке плагина, и оно не работает (в ТК команда cd не работает в папках FS-плагинов; ты должен вручную реализовать обработку команды cd и изменить текущую папку - например, вызвав ChangeCurrentDir, как делает моя VirtualPanel), или ты пытаешься обойти хук с помощью команды cd (я говорил как раз об этом - не нужно блокировать команду cd, раз юзер пишет ее, у него есть на то причины), или же этот абзац тоже подразумевает установку текста командной строки и выполнение для смены папки (маловероятно, что ты имел в виду это, но вдруг)?HankHank писал(а):При нахождении “в среде плагина” попытка ввести “cd \\< IP или имя>” не приводит к успеху – надо слегка подриххтовать логику. Ты, впрочем, об этом вскользь уже говорил.
Вот для этого и нужно обрабатывать команду cd, выдирать ее параметр и устанавливать как путь - делается элементарно. Я лично проверяю, есть ли кавычка в начале параметра - если есть, считаю путем то, что в кавычках, если нету - считаю путем весь параметр команды cd (за исключением пробелов, идущих в самом конце строки):HankHank писал(а):Пользователю невдомёк, что командная строка работает по-разному в плагине и без него. Поэтому не хотелось бы забивать ему мозги ещё и такими деталями. И надо бы это как-то реализовать... Да, и в принципе, возможна ситуёвина, когда в обеих панелях уже плагин, а пользователь ещё и в командной строке набирает типа cd \\<хост>.
Код: Выделить всё
cd "путь\путь" не путь
cd путь\п у т ь\путь путь У меня у самого такая мысль была - полотна исходников явно не для общего подфорума.Avada писал(а):Мне кажется, тему лучше перенести в подфорум "Написание плагинов", поскольку обсуждаемые вопросы — достаточно специфические. Нет возражений?
На вопросы по теме отвечу тут, может, кому-то пригодится. Надеюсь, не будешь сильно возражать.HankHank писал(а):В личке посмотри.
Конечно, код проще. Тебе ж не нужно каждый раз менять содержимое буфера, поэтому и статический буфер подойдет.HankHank писал(а):Покуролесил с вчерашним кодом в свете твоего сообщения о динамической памяти:Передаваемая процессу память никуда теперь не исчезает. Но код проще. (Пробовал static char buffer[]="cd \\\\\\net" и static char buffer[]="\\\\\\net".)Код: Выделить всё
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; }
Но что-то ничего не выходит…
А почему не работает, ща объясню. Видимо, ты плохо разобрался с форматом буфера для WM_COPYDATA, который ожидает ТК. Вот он:
Код: Выделить всё
<first_path>\r<second_path>\0<flags>Таким образом, правильный буфер:
Код: Выделить всё
static char cdnet[]="\\\\\\net\r\0S";Но размер такого буфера уже функцией strlen не определишь - внутри есть нулевой символ. Поэтому либо TSIZE(cdnet), либо ручками циферку. И циферка обязательно должна включать нулевой байт в конце буфера - иначе ТК может хрен знает куда зайти в его поисках и набрать себе левых флагов из блока памяти за пределами буфера (я с таким уже сталкивался, обсуждение тут).
Так ясно. По началу строчка wsprintf показалась заумной. И я решил, что хватит с меня и первого параметра с путём, куда надо переключить активную панель. А откуда эта инфо ?MVV писал(а): Видимо, ты плохо разобрался с форматом буфера для WM_COPYDATA, который ожидает ТК. Вот он:Флаги: 'T' - в новой вкладке, 'S' - менять пути активной и неактивной панелей вместо левой и правой.Код: Выделить всё
<first_path>\r<second_path>\0<flags>
Да, так работает. Буду ковать дальше.MVV писал(а): Таким образом, правильный буфер:Код: Выделить всё
static char cdnet[]="\\\\\\net\r\0S";
Ещё заметил такую деталь. Может, интересно кому.
Вот здесь http://www.firststeps.ru/mfc/winapi/win/r.php?126 прочитал про WM_COPYDATA:
У меня же передача параметров срабатывает, происходит переход куда требуется, но SendMessage возвращает при этом 0.Если принимающая программа обрабатывает это сообщение, она должна возвратить значение ИСТИНА (TRUE); в противном случае она должна возвратить - ЛОЖЬ (FALSE).