程序怎样从资源管理器的右键命令中接受多个文件并且本身只运行一次?(100分)

  • 主题发起人 主题发起人 fcputao
  • 开始时间 开始时间
F

fcputao

Unregistered / Unconfirmed
GUEST, unregistred user!
就像在资源管理器中选择多个文件,右击UltraEdit-32,UltraEdit只打开一个窗口,但却打开了多个页来显示这些文件.

我在工程文件(.dpr)中用这段代码实现本身只运行一次:
var hMutex, Ret: integer;
begin
Application.Initialize;
Application.Title := 'aaaaaaa';
hMutex := CreateMutex(nil, false, 'aaaaaaa');
Ret := GetLastError;
if Ret <> ERROR_ALREADY_EXISTS Then
begin
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end
else
ReleaseMutex(hMutex);
end.

在MainForm的Create事件中用这段代码接受参数:
if ParamCount <> 0 then
begin
tmpFileLists := TStringList.Create;
for ix := 1 to ParamCount do
tmpFileLists.Add(ParamStr(ix));
end;

可是当我在资源管理器中选择多个文件,然后右击"Process"(右键启动的注册表配置我已经确认可用),总是只接受到其中的一个文件.

请问怎样改代码才能实现UltraEdit那样的功能?

谢谢!
 
你的参数个数结果是1,所以。。。;
对文件的选择事件还要进行处理(也就是传参数的过程)。
 
UltraEdit使用的就是多页标签技术!你用TabelNoteBook控件试试就知道了!
 
你的dpr文件有问题,当你的软件已经运行时,你应该通知原来的那个去打开新的文件,而不是简单退出!
if Ret <> ERROR_ALREADY_EXISTS Then
begin
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end
else
begin
ReleaseMutex(hMutex);
通过消息机制或者其他方法,通知已经存在的程序去读取你新打开的文件!
end;
 
To yzhshi:
能再详细些吗?
怎么通过消息机制?

谢谢!
 
能!
因为我手头没有Delphi,只能给你说一下思路了。
程序里面设置wndproc,接收所有消息,然后过滤,使用自定义消息如:WM_OpenFile。
在你发觉程序已经打开时,则向他发送消息,将文件名作为参数传递过去。
那边接受到了文件名,就按照这个打开了。
主要需要解决的技术点有:
1、建立消息机制。
2、将文件名作为消息参数发送。
3、多文档窗体的实现。
 
parastr[1]就是第一个参数,parastr[n]就是第那个参数
paracount就知道共传递了几个参数
 
我的意思是从资源管理器传送文件参数,而资源管理器每次只会串给我一个文件名(即使选中了多个文件).
但是WinZip用了ClassID就可以接受多文件了,请问这具体怎么实现?
 
//资源管理器每次只会串给我一个文件名(即使选中了多个文件).
那你试一试修改注册表,把原来的“我的程序.exe %1” 改成:
我的程序.exe "%1" "%*"
 
在你的资源管理器扩展dll中,将多个文件名相加为一个长字符串,传递给应用程序。
在应用程序中再将其分解为多个文件名,分别予以处理。
 
To beta:
但是我看Dreamweaver也只用%1,他就可以打开多个文件.
 
To beta:
试过了,不行呀.
 
我试了一下,你的应用程序的确可以获得所有文件的文件名,不过每次只有一个——
你的应用程序会被启用多次。用你一开始的方法的确只启动了一个实例,可是同时也
就“抛弃”其他几个参数,正确的做法是:
在当前实例诊测到已有实例启动后,首先把该实例获得的参数通过消息发送给第一个
实例,然后再关闭;在第一个实例中接受到相应消息后再打开相应文件即可实现打开
多个文件。
 
To beta:
请问怎样判断某个实例是第一个实例?
 
我暂时也没有很好的方法,不过也不是完全没有办法:
如果程序没有进入 if Ret <> ERROR_ALREADY_EXISTS Then 则说明当前是第一个实例,
不管其他的,只当成唯一实例、唯一文件打开那个文件。待会儿再等着接收其他文件的消息;
当程序进入了 if Ret <> ERROR_ALREADY_EXISTS Then 则说明当前不是第一个实例,
只要找到第一个实例,并把文件参数传过去,然后自己退出即可。
现在关键是如何查找那第一个实例,通过刚才的分析可以看出,若某实例的主窗口已经
打开,则说明那是第一个实例。你可以用 FindWindow 找到他(第一实例主窗口),然后
就可以给他发送消息把文件参数传给他了。

之所以我认为这不是一个好办法,是因为它用到了 FindWindow,如果你的主窗口的标题
是可变的话,就…… 当然,你可以给你的主窗口取一个特别的名字,于是就有了一个特别
的类名,因此也可以达到目的(我没有试过,你自己试一试吧)。 Good luck!
 
用WM_COPYDATA,如果发现内存有自己的程序的副本,就把得到的文件名
WM_COPYDATA传送过去,然后退出。。。
 
应该是程序启动是通过 GetClassName API 找出上一个实例
再用 WM_COPYDATA 消息给这个实例送出 ParamStr(1)...
 
To SupermanTm
我的意思就是你说的 [:D]
不过我是想通过互斥达到目的.........
 
传那个参数当然是用 WM_COPYDATA,但是要有句柄才行啊。
刚才我说的重点就是如何找到第一实例的主窗口的 Handle :-)
 
你先用findwindow找窗口,再设置你自己的application.title就OK了
 
后退
顶部