WLX-плагин для Total Commander на Lazarus

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

WLX-плагин для Total Commander на Lazarus

Сообщение Nik » 08.10.2011 23:27:30

Собрался, наконец, портировать свой AmpView на Lazarus. Для начала конвертировал проект средствами Lazarus. Результат (после небольшой правки) откомпилировался, но работать отказался (намертво вешает TC).

Чтобы локализовать проблему (плагин отладчиком не погоняешь, да и падает TC), до предела упростил код (пока даже логику работы плагина поломал). В результате плагин стал загружаться и корректно вызывать проигрыватель. Но есть одно "но" - пока работает проигрыватель, окно TC "висит". После закрытия проигрывателя управление корректно возвращается TC.

Кто-нибудь писал wlx-плагин на Lazarus (именно под TC, а не DC)?

Вот нынешний код:

Код: Выделить всё
library AmpView;

{$MODE Delphi}

uses
  Windows, wlxplugin,
  SysUtils;

const
  PARSE_FUNCTION = 'MULTIMEDIA | EXT="MP3" | EXT="WAV" | EXT="WMA" |'+
                   'EXT="OGG" | EXT="CDA" | EXT="MO3" | EXT="IT" |'+
                   'EXT="XM" | EXT="S3M" | EXT="MOD" | EXT="M3U" |'+
                   'EXT="PLS" | EXT="MID"| EXT="MIDI" | EXT="KAR"';

var
  wc: TWndClass;

function WindowProc(wnd:HWND; Msg : Integer; Wparam:Wparam; Lparam:Lparam):Lresult; stdcall;
var
LW: HWND;
begin
  LW:=GetParent(wnd);
  PostMessage(LW, $0100, 27, 0);
  Result := DefWindowProc(wnd,msg,wparam,lparam);
end;

function CallKiller(aListerWindow:HWND):HWND;
begin
  result:=CreateWindowEx(WS_EX_CONTROLPARENT,'AMPVIEW_PLAYER','AMPVIEW_PLAYER',WS_CHILD or WS_VISIBLE or WS_CLIPSIBLINGS,0,0,10,10,aListerWindow,0,Hinstance,nil);
end;

function ListLoad(ParentWin: HWND;  FileToLoad: pchar;  ShowFlags: integer): HWND; stdcall;
var
  PlayerExe: string;
begin
  PlayerExe:='c:\Program Files\Total Commander 7.56\Plugins\wlx\AmpView\AmpView.exe';

  Result := CallKiller(ParentWin);
  if Result = 0 then Exit;
  SetWindowPos(ParentWin, 0, -100, -100, 0, 0, SWP_HIDEWINDOW);

  SysUtils.ExecuteProcess(PlayerExe, ['\n', FileToLoad]);
end;

procedure ListGetDetectString(DetectString: pchar; maxlen: integer); stdcall;
begin
StrLCopy(DetectString, PChar(PARSE_FUNCTION), MaxLen);
end;


exports
ListLoad,
ListGetDetectString;

begin
  WC.lpfnWndProc     := @WindowProc;
  WC.style           := CS_VREDRAW or CS_HREDRAW;
  WC.hInstance       := hInstance;
  WC.hIcon           := 0;
  WC.hCursor         := LoadCursor(0,IDC_ARROW);
  WC.hbrBackground   := CreateSolidBrush( COLOR_BTNFACE+1 );
  WC.lpszMenuName    := nil;
  WC.cbClsExtra      := 0;
  WC.cbWndExtra      := 0;
  wc.lpszClassName   := 'AMPVIEW_PLAYER';
  Windows.RegisterClass(wc);
end.

Аватара пользователя
Nik
энтузиаст
 
Сообщения: 573
Зарегистрирован: 04.02.2006 00:08:09
Откуда: Киров

Re: WLX-плагин для Total Commander на Lazarus

Сообщение скалогрыз » 09.10.2011 04:28:47

очевидно же. SysUtils.ExecuteProcess() синхронный - ожидает завершения процесса, без обработки очереди сообщений.
(вырезка кода из sysutils)
Код: Выделить всё
if WaitForSingleObject(Proc, dword($ffffffff)) <> $ffffffff then

правильные запустить процесс и забыть =) хорошо подойдёт ShellExecute().

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

на самом деле плагин должен работать чуточку умнее:
1) запустить процесс (запомнить хендл). естественно НЕ дожидаться конца проигрывания.
2) если вызвано проигрывание другого файла, то открывать файл уже существующим процессом (если предусмотрено межпроцессное взаимодействие). либо прибить существующий процесс и запустить новый (чтобы не плодить проигрыватели).
3) по завершению работы TC, прибивать открытый процесс, хотя лучше сделать это опцией. Но по-умолчанию прибивать.
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: WLX-плагин для Total Commander на Lazarus

Сообщение Nik » 09.10.2011 10:17:49

В версии для Delphi именно такая логика и была (+ я ещё убирал окно Lister'а, а при вызове в режиме быстрого просмотра - встраивал окно внешнего плеера в панель TC). Но после порта на Lazarus плагин стал намертво вешать TC при вызове ShellExecute() или WinExec().

UPD. Поигрался с параметрами ShellExecute - теперь работает. При вызове из Lazarus нужен немного другой набор параметров, отличный от вызова из Delphi (хотя копилируются оба варианта).
Аватара пользователя
Nik
энтузиаст
 
Сообщения: 573
Зарегистрирован: 04.02.2006 00:08:09
Откуда: Киров

Re: WLX-плагин для Total Commander на Lazarus

Сообщение скалогрыз » 09.10.2011 22:22:30

возможно разница в вызванном CoInitializeEx()? не знаю насчёт тонкостей WinExec() (т.к. функция была названа deprecated ещё со времён Win95), но ShellExecute() не дожидается завершения выполняемого процесса (в отличии от SysUtils.ExecuteProcess()).

т.к. ShellExecute() функция системная, я бы грешил на разницу в настройках компиляции .dll для fpc и delphi, иначе всё должно работать на 100% одинаково!

Дарвинистское программирование это замечательно, но всё таки, можно ли узнать подробности - какие именно параметры пришлось поменять в вызове ShellExecute()?
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: WLX-плагин для Total Commander на Lazarus

Сообщение Nik » 09.10.2011 23:28:55

В общем, нерабочую версию я уже благополучно угрохал, а финальный вариант выглядит так:

Код: Выделить всё
ShellExecute(0, nil, PChar(PlayerExe), PChar('\n "'+FileToLoad+'"'), nil, 5)
Аватара пользователя
Nik
энтузиаст
 
Сообщения: 573
Зарегистрирован: 04.02.2006 00:08:09
Откуда: Киров

Re: WLX-плагин для Total Commander на Lazarus

Сообщение скалогрыз » 10.10.2011 00:49:14

как замечательно. а есть вариант заставить её снова работать НЕ правильно?
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: WLX-плагин для Total Commander на Lazarus

Сообщение Nik » 11.10.2011 10:06:11

Не могу вспомнить, с какими параметрами первый раз эту функцию вызывал. И вообще начинаю подозревать, что хотя всё вешалось именно на строчке с ShellExecute (проверял, вставляя вывод MessageBox), причина была в другом (основной поток Lister/TC почему-то периодически стопорится при попытке вызвать в основном потоке плагина банальный if; с case заработало).
Вот такая вот особая TC-плагинная магия... :) :(
Аватара пользователя
Nik
энтузиаст
 
Сообщения: 573
Зарегистрирован: 04.02.2006 00:08:09
Откуда: Киров

Re: WLX-плагин для Total Commander на Lazarus

Сообщение kotompazb » 25.08.2016 15:14:03

Nik
Нашел тут исходники вашего плагина. Спасибо. Скомпилил. Все отлично работает. Но.
Вы в ListLoad запускаете свой экзешник с собственным окном. А не подскажете мне, как делаются более "стандартные" плагины, в смысле, как дочерняя форма окна Lister. Пусть там будет хотя б просто тот же Memo и отображает FileToLoad просто в виде текста. А то что-то не получается самому понять. А иногда надо (для себя скорее мелкие специфичные плагины писать). Спасибо.

Добавлено спустя 9 часов 36 минут 6 секунд:
Может, кто еще писал Lister-плагины?
Нужен по сути простейший вариант для изучения предмета.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: WLX-плагин для Total Commander на Lazarus

Сообщение v-t-l » 26.08.2016 10:50:34

Давно как-то ещё на Delphi экспериментировал, сырцов не осталось. Помню только, что все завязано на constructor TWinControl.CreateParented(AParentWindow: HWND).
Кажется даже, проектировал форму визульно, а потом создавал её через CreateParented, хотя точно не скажу.

Добавлено спустя 4 минуты 3 секунды:
Кстати, многие плагины к TC написаны на Delphi, некоторые из них с сырцами.
v-t-l
энтузиаст
 
Сообщения: 733
Зарегистрирован: 13.05.2007 16:27:22
Откуда: Belarus

Re: WLX-плагин для Total Commander на Lazarus

Сообщение kotompazb » 26.08.2016 12:46:23

v-t-l писал(а):Кстати, многие плагины к TC написаны на Delphi, некоторые из них с сырцами.

Да вот что-то у меня ни одного плагина под Lazarus'ом завести не получилось:(
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: WLX-плагин для Total Commander на Lazarus

Сообщение kotompazb » 27.08.2016 22:47:49

Короче решил задачу пока через костыли до лучших времен. А именно аналогично плагину Топикстартера, то есть через запуск отдельного приложения (сам плагин таким образом - просто оберта-запускалка). В его случае это решение, в моем - костыли. Какие у данного решения недостатки (кроме лишнего экзешника):
  • Нельзя сменить режим просмотра (если плагин решил, что файл его (детекчу по размеру и расширению), то запускается отдельное приложение),
  • Нельзя смотреть файлы в архивах.
Все. Спасибо за внимание.
Аватара пользователя
kotompazb
постоялец
 
Сообщения: 151
Зарегистрирован: 21.06.2012 13:03:39
Откуда: Novosibirsk, xUSSR

Re: WLX-плагин для Total Commander на Lazarus

Сообщение eastorwest » 28.07.2022 22:05:00

Пусть там будет хотя б просто тот же Memo и отображает FileToLoad просто в виде текста.

Недавно искал такой же пример. Не нашёл.
Портировал из Delphi в Lazarus пример из статьи http://wincmd.ru/article/ListSimple.html.
В принципе работает, как в Double Commander (версии 1.0.0 или выше), так и в Total Commander (проверял в 9.51).
Контекстное меню Memo, созданное средствами Lazarus, не открывается или вызывает ошибку.
Собирал версии для Windows x86 и x86_64.
Для сборки рекомендую использовать последние версии Lazarus IDE (2.0 или выше).
У вас нет необходимых прав для просмотра вложений в этом сообщении.
eastorwest
новенький
 
Сообщения: 57
Зарегистрирован: 23.07.2009 20:21:46
Откуда: Н-ск

Re: WLX-плагин для Total Commander на Lazarus

Сообщение Alex2013 » 29.07.2022 21:27:55

Кстати интересно, а плагины для андроид версии ТС в лазарусе можно собирать ?
Alex2013
долгожитель
 
Сообщения: 3049
Зарегистрирован: 03.04.2013 11:59:44


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 24

Рейтинг@Mail.ru