Форум: "Начинающим";
Текущий архив: 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