Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.02.04;
Скачать: [xml.tar.bz2];

Вниз

Получение имён файлов   Найти похожие ветки 

 
SerjVasiljev   (2007-01-16 20:19) [0]

Здравствуйте, интересует вопрос.
Есть программа (плеер), нашёл код, который не даёт запустить вторую копию программы http://read.excode.ru/art4055p1.html.
Мне нужно получать список имён файлов которые я выделил в проводнике и после выбрал в попап меню проводника Открыть в "Имя моего плеера". Тоесть как сделать так, что бы моя программа принимала названия файлов так же как и WinAmp.
 У меня получилось реализовать это используя вышеуказанный код, но работает очень медленно (пока откроется каждая копия программы, передастся параметр и т.д.).
 Есть предположение, что винамп каким-то образом сразу загружает весь список песен которые пользователь выбрал в проводнике. Если я прав, как это реализовать? Как мне решить проблемму?

P.S.
  Перепробовал множество примеров закрытия второй копии программы. Скорость одна и таже при передаче параметров. Рациональнее передавать сразу все файлы в прогу, как это сделать?


 
tesseract ©   (2007-01-16 22:20) [1]


>  Есть предположение, что винамп каким-то образом сразу загружает
> весь список песен которые пользователь выбрал в проводнике.
>  Если я прав, как это реализовать? Как мне решить проблемму?
>


См мультивыбор, winamp одной строкой все файлы кидает.


 
SerjVasiljev   (2007-01-16 22:28) [2]

Где смотреть? Можно пример? Пожалуйста.


 
clickmaker ©   (2007-01-17 11:23) [3]


> передавать сразу все файлы в прогу, как это сделать?

ParamStr(1) .. ParamStr(N) если аргументы командной строки разделены пробелами (имена файлов с пробелами должны быть в кавычках)
StringList.CommaText := ParamStr(1) если аргументы через запятую,
потом StringList.Strings[i]


 
SerjVasiljev   (2007-01-17 15:42) [4]

У меня получалось за одно открытие программы передать только один параметр (так как программу открывает первый файл выделенных песен, а потом второй и тд). Тоесть сколько бы мы не выбрали песен, каждая пытается открыть свой плеер и мы можем отловить только одно имя.
 Нужно сто-то другое, не через ParamStr. :(


 
clickmaker ©   (2007-01-17 15:49) [5]


> Тоесть сколько бы мы не выбрали песен, каждая пытается открыть
> свой плеер и мы можем отловить только одно имя

тогда программа эта должна проверять, а не запущена ли она уже. Если да, то активизировать окно своего клона (SetForegroundWindow) и передавать ему имя файла, например с помощью WM_COPYDATA


 
SerjVasiljev   (2007-01-17 18:46) [6]

Пожалуйста, можно пример? Очень прошу.


 
SerjVasiljev   (2007-01-17 20:08) [7]

Разобрался с WM_COPYDATA. Есть ещё другие варианты??? Скорость также мала.


 
Rial ©   (2007-01-17 20:15) [8]

Создай небольшую программу (как это сделано и в WinAMP), и именно
с этой программой ассоциируй свой тип файлов.
При запуске эта маленькая программа будет смотреть,
если ли уже запущенная "большая" программа. Если есть,
то передаешь ей имя файла. Если нет - то создаешь новый
процесс и передаешь ему имя файла.
Только "маленькую" программу лучше сделать вообще без
окон, и, конечно же, без VCL.


 
SerjVasiljev   (2007-01-17 20:35) [9]

Спасибо, попробую ;)


 
SerjVasiljev   (2007-01-17 21:07) [10]

Минимизировал прогу как мог.


program Project1;

uses
 Forms, Windows, Messages, SysUtils, Controls;

{$R *.res}

var
  aCopyData: TCopyDataStruct;
  hTargetWnd: HWND;

begin
 Application.Initialize;

  with aCopyData do
  begin
    dwData := 0;
    cbData := StrLen(PChar(ParamStr(1))) + 1;
    lpData := PChar(ParamStr(1));
  end;
  hTargetWnd := FindWindowEx(0, 0, nil, PChar("Form1"));
  SendMessage(hTargetWnd, WM_COPYDATA, Longint(Application.Handle), Longint(@aCopyData));

 Application.Run;
end.


Запускаю через неё песни, а потом передаю плееру, но скорость таже, тоесть песни передаются по одной. Надо как-нибудь по другому, только как?


 
Rial ©   (2007-01-17 21:45) [11]

У тебя всю беда в коде.
С каких "маленькое" приложение весит 400 КБ ?
Это нехорошо.

Забудь ты про этот Application !!
И про модули Forms и Controls тоже. И будет тебе счастье
размером в 40КБ и скоростью запуска в 1 раз выше.


 
SerjVasiljev   (2007-01-17 22:16) [12]

А как тогда Application.Handle и т.д. ? Может дело не в коде, дело в методе передачи параметров?


 
SerjVasiljev   (2007-01-17 22:56) [13]

Вот уменьшил


program Project1;

uses
 Windows, Messages, SysUtils;

{$R *.res}

var
  aCopyData: TCopyDataStruct;
  hTargetWnd: HWND;

begin
  with aCopyData do
  begin
    dwData := 0;
    cbData := StrLen(PChar(ParamStr(1))) + 1;
    lpData := PChar(ParamStr(1));
  end;
  hTargetWnd := FindWindowEx(0, 0, nil, PChar("Form1"));
  SendMessage(hTargetWnd, WM_COPYDATA, 0, Longint(@aCopyData));
end.


Но результат почти не изменился. Нужен другой метод :(


 
TRUNK ©   (2007-01-17 23:05) [14]

Привожу исходники своей программы (вернее DLL). Оставил основной каркас и добавил комментарии.
За основу был взят файл ContextM.pas в папке Delphi6\Demos\ActiveX\ShellExt.

Пришлось разбить текст на части :(

// 1-я часть:

library CntxtHandler;
uses
 ComServ,
 CntxtUnit in "CntxtUnit.pas";
exports
 DllGetClassObject,
 DllCanUnloadNow,
 DllRegisterServer,
 DllUnregisterServer;
{$R *.RES}
begin
end.

unit CntxtUnit;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses
 Windows,ActiveX,Classes,ComObj,ShlObj;
type
 TContextMenuHandler = class(TComObject,IShellExtInit,IContextMenu)
 private
   FFileCount: Cardinal;
   FFileNames: array of string;
   FidCmdFirst,FidCmdLast: Cardinal;
 protected
   function IShellExtInit.Initialize = SEIInitialize;
   function SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject; hKeyProgID: HKEY): HResult; stdcall;
   function QueryContextMenu(Menu: HMENU; indexMenu,idCmdFirst,idCmdLast,uFlags: Cardinal): HResult; stdcall;
   function InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; stdcall;
   function GetCommandString(idCmd,uType: Cardinal; pwReserved: PCardinal;
                             pszName: PChar; cchMax: Cardinal): HResult; stdcall;
 end;
const
 Class_ContextMenuHandler: TGUID = "{CEF775AF-336C-4EAD-80FE-1D17EE1EFC90}";


 
TRUNK ©   (2007-01-17 23:06) [15]

// 2-я часть:

implementation
uses
 ComServ, SysUtils, ShellApi;
(*****************************************************************************)
(* Вызывается перед созданием контекстного меню и указывает выбранные файлы; *)
(* По типам файлов здесь можно решить - добавлять свои пункты в меню или нет *)
function TContextMenuHandler.SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject; hKeyProgID: HKEY): HResult;
// pidlFolder -> Specifies the parent folder
// lpdobj     -> Spefifies the set of items selected in that folder
// hkeyProgID -> Specifies the type of the focused item in the selection
var
i: Integer;
StrBuf: PChar;
BufSize,StrLength: Cardinal;
StgMedium: TStgMedium;
FormatEtc: TFormatEtc;
begin
if (lpdobj = nil) then
 begin
 Result := E_INVALIDARG;
 Exit;
 end;
with FormatEtc do
 begin
 cfFormat := CF_HDROP;
 ptd := nil;
 dwAspect := DVASPECT_CONTENT;
 lindex := -1;
 tymed := TYMED_HGLOBAL;
 end;
// Render the data referenced by the IDataObject pointer
// to an HGLOBAL storage medium in CF_HDROP format
Result := lpdobj.GetData(FormatEtc,StgMedium);
if Failed(Result) then
 Exit;
// Извлекаем кол-во выбранных файлов
FFileCount := DragQueryFile(StgMedium.hGlobal,$FFFFFFFF,nil,0);
SetLength(FFileNames,FFileCount);
// Копируем их имена
StrBuf := nil;
BufSize := 4096;
ReallocMem(StrBuf,BufSize);
for i := 0 to FFileCount-1 do
 begin
 StrLength := DragQueryFile(StgMedium.hGlobal,i,StrBuf,BufSize);
 FFileNames[i] := Copy(StrBuf,1,StrLength);
 end;
ReallocMem(StrBuf,0);
ReleaseStgMedium(StgMedium);
Result := NOERROR;
end;


 
TRUNK ©   (2007-01-17 23:07) [16]

// 3-я часть:

(*************************************************************************)
(* Вызывается, когда Explorer создаёт контекстного меню для файла;       *)
(* данный пример добавляет пункт "Пункт 0" с 2-мя вложенными подпунктами *)
function TContextMenuHandler.QueryContextMenu(Menu: HMENU; indexMenu,idCmdFirst,idCmdLast,uFlags: Cardinal): HResult;
// Menu       -> Handle of the menu
// indexMenu  -> Location to insert first menu item
// idCmdFirst -> Minimum value for a menu item identifier
// idCmdLast  -> Maximum value for a menu item identifier
// uFlags     -> Specifies zero or more status values
var
ItemName: string;
SBM: HMENU;
MII: TMenuItemInfo;
begin
Result := 0;
if ((uFlags and $0000000F) = CMF_NORMAL)or((uFlags and CMF_EXPLORE) <> 0) then
 begin
 SBM := CreatePopupMenu;
 ItemName := "Подпункт 1";
 MII.cbSize := SizeOf(MII);
 MII.fMask := MIIM_TYPE or MIIM_STATE or MIIM_ID or MIIM_CHECKMARKS;
 MII.fType := MFT_STRING;
 MII.fState := MFS_ENABLED or MFS_UNCHECKED;
 MII.wID := idCmdFirst+1; // индекс, к-рый идентифицирует этот пункт;
                          // индекс задаётся произвольно при условии,
                          // что idCmdFirst <= индекс <= idCmdLast
 MII.hSubMenu := 0;
 MII.hbmpChecked := 0;
 MII.hbmpUnchecked := 0;
 MII.dwItemData := 0;
 MII.dwTypeData := PChar(ItemName);
 MII.cch := Length(ItemName);
 MII.hbmpItem := 0;
 InsertMenuItem(SBM,0,true,MII);
 ItemName := "Подпункт 2";
 MII.cbSize := SizeOf(MII);
 MII.fMask := MIIM_TYPE or MIIM_STATE or MIIM_ID or MIIM_CHECKMARKS;
 MII.fType := MFT_STRING;
 MII.fState := MFS_ENABLED or MFS_UNCHECKED;
 MII.wID := idCmdFirst+2; // индекс, к-рый идентифицирует этот пункт
 MII.hSubMenu := 0;
 MII.hbmpChecked := 0;
 MII.hbmpUnchecked := 0;
 MII.dwItemData := 0;
 MII.dwTypeData := PChar(ItemName);
 MII.cch := Length(ItemName);
 MII.hbmpItem := 0;
 InsertMenuItem(SBM,1,true,MII);
 ItemName := "Пункт 0";
 MII.cbSize := SizeOf(MII);
 MII.fMask := MIIM_TYPE or MIIM_STATE or MIIM_ID or MIIM_SUBMENU or MIIM_CHECKMARKS;
 MII.fType := MFT_STRING;
 MII.fState := MFS_ENABLED or MFS_UNCHECKED;
 MII.wID := idCmdFirst; // индекс, к-рый идентифицирует этот пункт
 MII.hSubMenu := SBM;
 MII.hbmpChecked := 0;
 MII.hbmpUnchecked := 0;
 MII.dwItemData := 0;
 MII.dwTypeData := PChar(ItemName);
 MII.cch := Length(ItemName);
 MII.hbmpItem := 0;
 // Добавляем в контекстное меню
 InsertMenuItem(Menu,indexMenu,true,MII);
 // Возвращаем кол-во добавленных пунктов меню
 Result := 3;
 FidCmdFirst := idCmdFirst;
 FidCmdLast := idCmdLast;
 end;
end;


 
TRUNK ©   (2007-01-17 23:08) [17]

// 4-я часть:

(**********************************************************)
(* Вызывается при выборе нашего пункта в контекстном меню *)
function TContextMenuHandler.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
var
i: Integer;
begin
// Убеждаемся, что не вызваны приложением
if (HiWord(Integer(lpici.lpVerb)) <> 0) then
 begin
 Result := E_FAIL;
 Exit;
 end;
// Убеждаемся, что вызваны одним из наших пунктов меню
if (LoWord(lpici.lpVerb) > 2) then // 2 - это максимальный индекс наших пунктов меню
 begin
 Result := E_INVALIDARG;
 Exit;
 end;
case LoWord(lpici.lpVerb) of
 1: DoAction_1; // выбран пункт меню с индексом 1
 2: DoAction_2; // выбран пункт меню с индексом 2
end;
Result := NOERROR;
end;

function TContextMenuHandler.GetCommandString(idCmd,uType: Cardinal; pwReserved: PCardinal;
                                             pszName: PChar; cchMax: Cardinal): HResult;
begin
// Проверяем, что у нас запрашивается строка с подсказкой
if (uType <> GCS_HELPTEXT) then
 begin
 Result := E_FAIL;
 Exit;
 end;
// Выдаём строку с подсказкой для пункта меню
// с индексом idCmd (показывается в StatusBar"е Explorer"а)
case idCmd of
 0: StrCopy(pszName,"Подсказка для пункта 0");
 1: StrCopy(pszName,"Подсказка для пункта 1");
 2: StrCopy(pszName,"Подсказка для пункта 2");
else
 Result := E_FAIL;
 Exit;
end;
Result := NOERROR;
end;

initialization

TComObjectFactory.Create(ComServer,TContextMenuHandler,Class_ContextMenuHandler,
                        "ContextMenuHandler","",ciMultiInstance,tmApartment);
end.


После компиляции DLL нужно зарегистрировать (Run->Register ActiveX Server).
Также в реестре прописать для каких типов файлов будет использоваться:
HKEY_CLASSES_ROOT\расширение_файла\shellex\ContextMenuHandlers\GUID_этого_CntxtH andler
например:
HKEY_CLASSES_ROOT\.mp3\shellex\ContextMenuHandlers\{CEF775AF-336C-4EAD-80FE-1D17EE1EFC90}

Остаётся только открыть программу и передать в неё список файлов.


 
SerjVasiljev ©   (2007-01-17 23:13) [18]

Класс :) . Буду разбираться, спасибо ;)


 
SerjVasiljev ©   (2007-01-17 23:21) [19]

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


 
SerjVasiljev ©   (2007-01-17 23:21) [20]

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


 
SerjVasiljev ©   (2007-01-17 23:26) [21]

Совсем запутался :(


 
TRUNK ©   (2007-01-17 23:27) [22]


> Не получается соединить модули, постоянно ошибки


Что за ошибки? И куда залить?


 
SerjVasiljev ©   (2007-01-17 23:38) [23]

Вообщем я создал новую dll, вставил туда все куски кода, в папку вложил файл ContexM (Переименовал в CntxtUnit, как понял). Когда запускаю dll много ошибок. Наверное что-то не допонял.
 Можете отправить весь проект (рабочий) на serjpochta@mail.ru ? Было бы здорово, я новичок, мне тяжело в таких кодах разбираться, извеняюсь :(


 
TRUNK ©   (2007-01-18 00:19) [24]

OK, вышлю проект. Он будет несколько отличаться от приведённого, т.к. здесь я описал всего лишь обобщённый вариант, к-рый ничего полезного не делает :)

P.S. Прочитай приложенный ReadMe



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.02.04;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.041 c
15-1168878501
den_c
2007-01-15 19:28
2007.02.04
Компонент для работы с zip-архивом


2-1169148215
malyar
2007-01-18 22:23
2007.02.04
idpop3.delete (удаление письма)


15-1168590355
Empleado
2007-01-12 11:25
2007.02.04
Календарь менять будем? Аль так оставим?


6-1157010803
Undertaker12345
2006-08-31 11:53
2007.02.04
indy почта


15-1168698485
Гарри Поттер
2007-01-13 17:28
2007.02.04
Старый Новый год.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский