做IE外挂程序怎样引用图标资源!--要得到一个图标资源在资源文件中的偏移量标号该怎么办?(300) (300分)

  • 主题发起人 主题发起人 jrq
  • 开始时间 开始时间
to dontal 兄弟:你好!留言看到。
1. 当时我的问题是描述的不确切,Dcom服务需要在服务器上和客户端机器上都注册的。
Server的注册 即运行程序就可以了。运行服务程序,就会生成一个GUID(写在了注册表中,即注册了)。
Dcom服务需要在服务器上和客户端机器上都注册。
在服务器上运行服务程序,注册。在客户端也运行注册一下,会生成同样的GUID。这是个唯一的号码,用来调用服务的。
当然了,用Delphi的tregsvr.exe也可以注册。
2. 一般是midas.dll随客户端一起发布并注册(win98好像没有Midas.dll的)。另外也许需要dbClient.dll、STDVCL40.DLL两个文件,你可试试。
或者你直接可以手工注册。 COPY MIDAS.dll到你所安装程序的机器的系统目录中,如c:/windows/system等,然后运行 regsvr32 midas.dll 即可。
或者在程序中使用winexec("regsvr32.exe midas.dll",SW_NORMAL); 语句来注册。
这只是对系统进行的注册(可理解为类似于补丁的东东),不关怎么只要注册了这样的东东,你的系统就可跑了。
3. 还不太清楚你说的什么。
dcomcnfg中的用户,我理解是客户端的计算机系统用户(如Administrator等),和你的软件客户端的用户(数据库)有联系吗?
4. 用Socket连接,scktsrvr.exe 放在应用程序服务器上运行就可以了。

不好意思,我的DCOM也是用在公司局域网上,没有打包发布过。
但是Socket的发布我用了 midas.dll 、Pncrt.dll、rmoc3260.dll,没有出现问题。
就象以前的旧帖说的,DCOM配置真是费劲,远不如Socket来的快。
 
Dcom的问题多多,李维《系统篇》的第9章就是讲Dcom配置的。
客户端是自动激活服务程序的。一种是可见的,一种是不可见(后台运行),李维在9-14页也讲了。
可以参看讨论 http://www.delphibbs.com/delphibbs/dispq.asp?LID=721861
 
Decom 的配置要求权限十分严格! 最起码的是客户端要登陆到服务器的域中!
 
言归正传。继续讨论资源的图标问题。
我现在调用的是ICO图标的路径,但是这个路径有所变化,图标就显示不出来了。

另:那位大侠把上面 wukw兄弟 的C++代码翻译一下?? 谢谢。
 
自己用文本编辑器写RS文件,然后编译成RES再引用。
 
to jsxjd 大侠:
自己用文本编辑器写RS文件,能出来那个“标号”吗??
这个所谓的“标号”是自己指定的 还是系统自动获得的?
 
to jsxjd 大侠:
你的QQ是多少
或qq的妮称
 
http://www.delphibbs.com/delphibbs/DispQ.asp?LID=1766872
我给200,如何?
 
xzh2000:
好吧,谢兄,成交。
你开贴吧。 [:)]
 
TO:jrq,
标号和名字,在资源中不表示序号或其他物理的东西,实际上都是名字啊。Delphi 和 VC
都是通过名字调用资源的,Delphi 更强调使用名字串,Vc 中通过一个宏 MAKEINTRESOURCE
转换为名字串。这个问题可是很长时间了哦。 :-)
 
上面那个 C 代码替你转到 Delphi 如下:
function MyEnumProcedure(hModule: HINST; lpszType,
lpszName: PChar;lParam:LongInt): BOOL;
var
szBuffer:array[0..255]of Char;
nIndex,ID:LongInt;
lpID:PChar;
begin
ID:=HIWORD(DWord(lpszName));
if ID=0 then // 原文:Name is from MAKEINTRESOURCE
begin
ZeroMemory(@szBuffer,256);
StrPCopy(@szBuffer,Format('Icon %p', [lpszName]));
lpID:=lpszName; // 指针别名? :-)
end
else
begin
ZeroMemory(@szBuffer,256);
GetMem(lpID,1024); // 本段中,我没有 Free ,看得懂就行...
StrCopy(lpID,lpszName);
StrCopy(@szBuffer,lpID);
end;
// 下面 2 句需要原来的程序的上下文,才能通过编译,具体内容我已经标明
nIndex = SendDlgItemMessage(HWND(lParam),
IDC_LIST1, // 一个 ListBox 控件的资源标识
LB_ADDSTRING, // 一个 ListBox 添加 S 消息
0,LPARAM(szBuffer)^); // 把地址指针作为 LongInt 传过去
SendDlgItemMessage(HWND(lParam),IDC_LIST1,LB_SETITEMDATA,WPARAM(nIndex),
LPARAM(lpID)); // 这个已经是指针了
end;
 
谢谢 小雨哥 的热心帮助。

去年写了个小东东,看了看IE的外挂程序,大部分是针对注册表的操作,
后来发现NetAnts 和 FlashGet在注册表中写的东西,用eXeScope打开都能看到,
比如说FlashGet在IE工具栏上注册的那个图标。

我当时也想把图标写到资源中去,然后在注册表中指定,用来在IE中显示。
(当然,在程序中指定ico图标的存放路径也可达到一样效果,不过比较累赘)

当时这个问题没有解决(用的路径),做完了就扔起来了。
这两天我再试试, 然后也就结贴了。

再次感谢小雨哥的帮助。您是大侠,盼望能留下QQ或其他,进一步交流。
 
To:jrq
哈哈,别开玩笑啦。我的 QQ:2543915 认证:DFW 。不知道你试好了没有,在 IE 中
加工具条按钮可以看官方指导:
http://msdn.microsoft.com/workshop/browser/ext/tutorials/button.asp
简单点,就用下面的例程,一步搞定(一个添加函数,一个删除函数):

uses Registry,ActiveX,ComObj; // 代码中用到的单元
type
TConnType = (COM_OBJECT,EXPLORER_BAR,SCRIPT,EXECUTABLE); // 四种添加类型
const
YouAppReg ='DelphiApplication'; // 这里应该是你自己程序的注册路径

function AddToolbarBtn(Visible: Boolean; ConnType: TConnType;
BtnText, HotIcon, Icon, GuidOrPath: string): string;
var
G: TGUID;
Reg: TRegistry;
UID: string;
begin
CoCreateGuid(G); // 随机创建一个 GUID :-) 本来就是随机的嘛
UID := GuidToString(G);
Reg := TRegistry.Create;
with Reg do try
RootKey := HKEY_LOCAL_MACHINE;
// 全部 IE 工具条添加都在下面这个键值下
OpenKey('/Software/Microsoft/Internet Explorer/Extensions/' + UID, True);
if Visible then
WriteString('Default Visible', 'Yes') else // 默认显示?
WriteString('Default Visible', 'No');
WriteString('ButtonText', BtnText); // 文字
WriteString('HotIcon', HotIcon); // 热图标
WriteString('Icon', Icon); // 冷图标
case ConnType of
COM_OBJECT: begin // 按钮启动 COM
WriteString('CLSID', '{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}');
WriteString('ClsidExtension', GuidOrPath);
end;
EXPLORER_BAR: // 按钮启动 Explorer 扩展
begin
WriteString('CLSID', '{E0DD6CAB-2D10-11D2-8F1A-0000F87ABD16}');
WriteString('BandCLSID', GuidOrPath);
end;
SCRIPT: // 按钮启动解释脚本
begin
writeString('CLSID', '{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}');
WriteString('Script', GuidOrPath);
end;
EXECUTABLE: // 按钮启动外部 exe
begin
WriteString('CLSID', '{1FBA04EE-3024-11D2-8F1F-0000F87ABD16}');
WriteString('Exec', GuidOrPath);
end;
end;
CloseKey;
OpenKey('/Software/'+YouAppReg+'/ToolBar Buttons/', True); // 用来存放下述:
WriteString(BtnText, UID); // 按 Text 记下这个随机的 GUID
CloseKey; // 要删除就容易找了
finally
Free;
end;
Result := UID;
end;

function RemoveToolbarBtn(BtnText: string): Boolean;
var
Reg: TRegistry;
UID: string;
begin
Reg := TRegistry.Create;
with Reg do begin
RootKey := HKEY_LOCAL_MACHINE;
// 打开注册存放处
OpenKey('/Software/'+YouAppReg+'/ToolBar Buttons/', False);
// 从存放地按文字找 GUID
UID := ReadString(BtnText);
if length(UID) = 38 then begin
DeleteValue(BtnText);
CloseKey;
// 删除这个键值下全部
DeleteKey('/Software/Microsoft/Internet Explorer/Extensions/' + UID);
free;
Result := True;
end else
Result := True;
end;
end;

// 添加函数的演示 ===========
procedure TForm1.AddBtnButtonClick(Sender: TObject);
var
s:string;
begin
s:=AddToolbarBtn(true,EXECUTABLE,'MyTest', // BtnText
'c:/windows/notePad.exe,1', // HotIcon
'c:/windows/notePad.exe,2', // Icon
'c:/windows/notePad.exe'); // exe Name 或是 Com 的 GUID 串
s:='随机 GUID 是'+#13+s+#13+'已记录在册';
ShowMessage(s);
end;
// 删除函数的演示 ===========
procedure TForm1.DelBtnButtonClick(Sender: TObject);
begin
if RemoveToolbarBtn('MyTest') then
ShowMessage('找到并已经删除,它不会再烦您了')
else
ShowMessage('没找到 :-( ,检查提供的信息是否准确');
end;

注意这个按钮不会自己跑到工具条上,一定要点 IE 工具条(右键)-->自定义-->添加(按钮)
这样自己选上去,不然看不到效果。
 
试试ExtractIconEx/ExtractIcon两个API函数吧,一定能解决您的问题,
要么使用EnumResourceNames函数也行,后者的功能可能会更强大些,可以提取WIN32
下的几乎所有静态资源;而前者则仅仅能提取ICON图标资源,如果同意的话给俺加分吧!
 
多谢楼上二位了。
ExtractIconEx/ExtractIcon没有用过,我回去继续看去。

to 小雨哥:
我看到您给的函数了。
当时我是参照这个帖子来的:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=438838

您看看他3楼的回答当中的第4点:
>>>(4)Icon
>>>默认状态下的图标全路径,例如c:/vckbase.ico。也可以是EXE文件中包含的图标,例
>>>如:C:/PROGRAM FILES/NETANTS/NetAnts.exe,1000

我是想在资源中得到这个“C:/PROGRAM FILES/NETANTS/NetAnts.exe,1000”当中的
“1000”,没有成功。
假如能得到,写注册表时就可以不用指定“图标全路径”了。
您可以用eXeScope打开NetAnts.exe看看,在资源--图标中找到1000和1001,刚好就是IE中
所对应的冷图标和热图标。
我现在就是不知道这个 1000和1001 是怎么来的。 [:(]

IE5Tools 的那个单元也看了,当时就用这个做的。 ^ō^
 
慢慢来。我好象不认为这是个问题,也许我理解错了。
比如,有一个程序是 NetAnts.exe ,而我希望用到这 2 个图标。于是,我在自己的程序里这样做 :
....
implementation
{$R *.DFM}
uses ShellAPI,ExtCtrls;
function PickIconDlgA(OwnerWnd: HWND; lpstrFile:PWideChar;
var nMaxFile: LongInt; var lpdwIconIndex:
LongInt):LongBool;stdcall; external 'SHELL32.DLL' index 62;
procedure TForm1.Button1Click(Sender: TObject);
var
fSize, fIndex: LongInt;
Icon: TIcon;
Ap:array[0..1023]of WideChar;
Temp:string;
Form: TForm;
Image:TImage;
begin
Temp:='NetAnts.exe'; // 需要取图标的文件名
StringToWideChar(Temp,@Ap,1024);
if PickIconDlgA(Handle,@Ap,fSize,fIndex)and (fIndex <> -1) then
begin
Icon := TIcon.Create;
Icon.Handle := ExtractIcon(hInstance, PChar(Temp),fIndex);
// 以下动态建立一个显示用的 Form
Form := TForm.Create(Self);
try
with Form do
begin
BorderStyle := bsToolWindow;
Caption := '图标显示';
ClientWidth := 36;
ClientHeight := 36;
Position := poOwnerFormCenter;
Image := TImage.Create(Form);
end;
with Image do
begin
Parent := Form;
AutoSize := True;
Left := 0;
Top := 0;
Align:=alClient;
Center:=True;
end;
// 动态 Form 建立完成
Image.Picture.Icon := Icon;
Image.Picture.Icon.SaveToFile('Save.ico'); // 需要另存为的文件名
Form.ShowModal;
Icon := nil;
Icon.Free;
finally
Form.Free;
end;
end;
end;
我在 Windows 2000 中编译通过,你试试看。
 
使用 LoadLibrary('NetAnts.exe') 的办法,我还没试。试完后再贴。
 
LoadLibrary 的代码试好了,你试试看,比较匆忙,没有用 GDI 画图标,用了 VCL 控件,
看看是不是你要的:
procedure TForm1.Button2Click(Sender: TObject);
var
LibHandle:HINST;
Icon:HICon;
begin
LibHandle:=LoadLibrary('NetAnts.exe'); // 需要取图标的文件名
if LibHandle=0 then
begin
MessageBox(0,PChar(SysErrorMessage(GetLastError)),'Error',MB_OK);
FreeLibrary(LibHandle);
exit;
end;

ICON:=HICON(LoadImage(LibHandle,MakeIntResource(1001),IMAGE_ICON,0,0,0));
Image1.Picture.Icon.Handle:=ICON; // 放到一个 Image 控件中
Image1.Picture.Icon.SaveToFile('1001.ico');

FreeLibrary(LibHandle);
end;

注意看到 MakeIntResource(1001) 这行,就是将资源 ID 转成字串的,你可以试着代入其
他 ID ,我没有充分测试,试了 1000 和 1001 ,是 16X16 工具条图标,结果是 OK 的。
 
有劳 小雨哥 了!
在此我真诚的说声:谢谢!

您给出的代码我收了,我要仔细的看看。
现在手上有活,不过我一定给您个答复!
 
再灌点水 :-)
我又看了遍问题,觉得前面讨论的后我后面回答的,距离越来越大。呵呵。
原来,jrq 兄是为了在注册表中达到 NetAnts.exe,1000 的效果。这样的话,ICON 资源
必须在资源里出现为序号的表示方法,即:ICON ,1000 。
这在 Delphi 中存在默认方法。就是,如果在 rc 文件中使用的是数字做为名字,这个名字
最后保留为数字,如果其中出现字母,这个名字就保存为字符形式(带引号的那种)。还有一
个注意事项我现在想不起来了,就是数字命名约束的问题,比如,不要使用 负数、不要使
用 $F000 以后的数字等,需要查资料来确定具体内容了,在此略过。现在来看下面:
My.rc 文件定义如下:
~~~~~~~~~~~~~~~~~~~
1000 ICON "1.ico"
1001 ICON "2.ico"
1002 ICON "3.ico"
1003 ICON "4.ico"
第一列:资源名字,这个在本文讨论
第二列:资源类型,这个还有点内容,在此略过
第三列:资源对应的外部文件或数据,在此略过
把这个 rc 文件编译后产生 My.res 文件链入程序中,将得到以数字表示的名字。通过资源
编辑器,看到的内容如下:
My.res
|
Icon
|- 1000
|- 1001
......
反过来,我们在 rc 文件中使用任何字母:
100A ICON "1.ico"
100B ICON "2.ico"
得到的将是如下:
My.res
|
Icon
|- "100A"
|- "100B"
.....
可以看到资源名字变成了字符串的表示了。混合使用时,数字的还是数字,字符的就变成了
字符。jrq 兄链入的资源,如果按照数字表示法,就可以象 NetAnts.exe,1000 这样使用了。
话要说清楚,资源在程序中调用,使用字符串名字比较直观,很多调用资源的 API 也是支
持名字调用的,但 LoadStr 就不同,它是直接使用数字调用的,原因可能是利用数字有一
个便利,就是连续的资源,用一个循环就可以装入。数字调用还有一个便利,是我们仍然
可以在程序中使数字有意义起来,比如我们可以在程序开头写这样一些别名常量:
count
MyIcon1=1000;
MyIcon2=1002;
....
调用时,我们就可以放弃难记的数字,使用别名来引用资源了。呵呵,又是灌水了。

另外补充一点,就是 MakeIntResource 宏在干什么,凭记忆,好象是转换数字标识为字符
,转换的规律在 MSND 文档中默认定义,比如,MS 规定 ICON 资源从 40000 序号开始,那
么我们定义的 1000 就会最终被这个宏函数在考虑默认序号的基础上转为字符。具体又要查
文档了。
 
后退
顶部