话题215471的标题是: 有关在Delphi中编程实现拨号连接的中文资料(200分) (200分)
分类:局域网 / 通讯 dyxfromxf (2000-04-08 7:14:00)
各位:
最近有一任务,要在Delphi中编程实现拨号连接,关系到肚子问题,请各位赐教,一定是要中文资料喔!献上200分!
xWolf (2000-04-08 12:30:00)
在DELPHI程序管理拨号网络
用MODEM拨号上网,仍是大多数个人网民选择上网的方式.如果能在我们的应用程序中管理拨号
网络(如Foxmail、Sygate中的拨号功能),无疑将会方便我们的软件用户(不用再切换应用程序,
运行拨号网络),提高我们的软件的友好性从而提高软件的竞争力.
在WIN9X下,如果安装了拨号网络,则在WINDOWS系统的系统目录System下将有两个拨号网络管理
程序库RasApi32.DLL和RasApi16.DLL,我们可利用其中的函数来获取和设置拨号连接网络的信息。在
Delphi帮助文件中,有相关函数的说明。
在此,我们要讨论的管理项目有:
1、获取当前系统中可用的拨号连接名称
2、新建拨号连接、修改拨号连接的属性
3、获取和设置拨号连接的拨号参数
4、用指定的拨号连接拨号、挂断指定的拨号连接
5、获取当前活动的连接及其连接状态
零、获取RasAPI函数执行失败的错误信息
RasAPI的调用接口是统一的,但对于不同的Windows版本,许多常量和数据结构的定义是不同的。
如果使用的数据结构与Windows版本不对应,RasAPI函数执行会失败;另外,其它原因如其它程序也
在使用同一个拨号连接进行拨号等,也会造成RasAPI函数执行失败.鉴于此原因,我们需要先讨论获
取RasAPI函数执行失败的错误信息的函数。
当一个RasAPI函数执行结束时,会返回一个结果标识,为0时表示执行成功,否则作为一个错误标
识符表示执行失败的原因。RasAPI函数RasGetErrorString可以根据错误标识符返回其错误描述信息,
在中文WIN9X下可提供一个中文错误信息.
RasGetErrorString的函数原型为:
function RasGetErrorString (
uErrorValue : UINT;//错误标识符
lpszErrorString : PChar;//错误提示信息的缓冲区
cBufSize : DWORD//错误提示信息的缓冲区大小
) : DWORD; stdcall;
function RasGetErrorString;external RasApiDll name 'RasGetErrorStringA';
( 注:RasApiDll = 'Rasapi32.dll'; )
为了方便,我们可以自己编写一个函数,用于获取RasAPI函数执行失败的错误信息。在下面的例
子中,会经常用到该函数。函数代码如下所示:
{ 根据错误标识符,获取RasAPI函数执行失败的错误信息 }
function GetRasError( ErrorID : UINT ) : string;
var
buffer : array[ 0..255 ] of char;
begin
if 0 = RasGetErrorString( ErrorID, buffer, 256 ) then
result := strpas( buffer )//如果能正确返回错误信息,则转化为Pascal字符串
else//否则返回16进制形式的错误代码
result := 'GetRasError Failure:ErrorID=' + Format( '%x',[ErrorID] );
end;
一、获取当前系统中可用的拨号连接名称
即获取系统中已建立的拨号连接的名称,可用来让用户选择使用哪个拨号连接进行拨号.
可以用两种方法来实现.一种是利用RasAPI函数;另一种是不用RasAPI函数,直接在注册表中查询.
1、不用RasAPI函数,直接在注册表中查询
在注册表的HKEY_USERS/.Default/RemoteAccess/Addresses下,列出了已经在拨号网络中建立
了的拨号连接的名称及其属性设置,其中各项目的名称即为可用的拨号连接的名称;各项目的值即
为各拨号连接的属性设置,不过是二进制串,笔者还看不懂.由此可见,我们只要读出各项目的名
称即可获取当前系统中可用的拨号连接名称.
var
registryTemp : TRegistry;
stringsTemp : TStringlist;
begin
registryTemp := TRegistry.Create;
stringsTemp := TStringlist.Create;
with registryTemp do
begin
RootKey := HKEY_USERS;//根键设置为HKEY_USERS
//如果存在子键.Default/RemoteAccess/Addresses
if OpenKey('.Default/RemoteAccess/Addresses',false) then
GetValueNames( stringsTemp );//读出各项目的名称,即拨号连接名称
end;
combobox1.Items.assign( stringsTemp );//显示,供选择
end;
2、用RasAPI函数
RasAPI函数RasEnumEntries可获取当前系统中可用的拨号连接名称.其函数原型为
function RasEnumEntries(
reserved : PChar;//保留字段,必须为NIL
lpszPhonebook : PChar;//电话本名称,在Win9X下无作用,可为空字符串
lprasentryname : LPRASENTRYNAME;//接收拨号连接名称的缓冲区,是一个RASENTRYNAME类型数组的指针
var lpcb : DWORD;//接收拨号连接名称的缓冲区的大小(Bytes)
var lpcEntries: DWORD//实际获得的拨号连接名称的数目
) : DWORD; stdcall;
function RasEnumEntries;external RasApiDll name 'RasEnumEntriesA';
参数lprasentryname提供了一个RASENTRYNAME类型数组的指针,指向一个接收拨号连接名称的缓冲
区,其中RASENTRYNAME及LPRASENTRYNAME的类型说明如下:
LPRASENTRYNAME = ^RASENTRYNAME;
RASENTRYNAME = record
dwSize : DWORD;//该结构所占内存的大小(Bytes),一般设置为SizeOf(RASENTRYNAME)
szEntryName : array [ 0..RAS_MaxEntryName ] of char;//拨号连接名称
end;
lpcb为缓冲区的大小,一般设置为dwSize的倍数,倍数为可能有的连接的个数.
lpcEntries实际的连接的个数.
下面是一个应用例子,列出了当前系统中可用的拨号连接名称.
注意,应在RASENTRYNAME缓冲区的第一个RASENTRYNAME结构中设置dwSize.
const
MaxPhoneEntries = 10;//最多的拨号连接数目
var
intIndex : integer;
PhoneEntries : array[ 0..MaxPhoneEntries - 1 ] of RASEntryName;
dwSize, dwEntries, dwResult : DWORD;
begin
//在RASENTRYNAME缓冲区的第一个RASENTRYNAME结构中设置dwSize
PhoneEntries[ 0 ].dwSize := sizeof( RASEntryName );
dwSize := MaxPhoneEntries * sizeof( RASEntryName );//为缓冲区的大小
//调用RasAPI函数,获取当前系统中可用的拨号连接名称
dwResult := RasEnumEntries ( NIL,'',@PhoneEntries[ 0 ],dwSize, dwEntries );
if dwResult <> 0 then
begin//RasAPI函数,执行错误
memo1.lines.add('RasEnumEntries错误:' + GetRasError( dwResult ));
exit;
end;
//显示当前系统中可用的拨号连接名称
memo1.lines.add('共有' + inttostr( dwEntries ) + '个RAS连接,如下所示');
for intIndex := 0 to dwEntries -1 do
memo1.lines.add( strpas( PhoneEntries[ intIndex ].szEntryName ) );
end;
3、获取默认的拨号连接的名称
默认的拨号连接,即用户在浏览器中设置的拨号连接,该连接可以认为是用户最常用
的拨号连接.
在注册表的HKEY_USERS/.Default/RemoteAccess位置,有一个字符串名Profile,它对应
字符值即为HKEY_USERS/.Default/RemoteAccess/Addresses.
二、新建拨号连接、修改拨号连接的属性
RasAPI函数RasCreatePhonebookEntry、RasEditPhonebookEntry通过调用Win9X的
新建拨号连接、修改拨号连接的设置界面,允许用户新建拨号连接、修改拨号连接,具体
的设置操作还要由系统来完成.
1、新建拨号连接
新建拨号连接的RasAPI函数为RasCreatePhonebookEntry,其函数原型为:
function RasCreatePhonebookEntry(
hwnd : THandle; //新建拨号连接窗口的父窗口的句柄,为NIL表示桌面(DeskTop)
lpszPhonebook: pchar//电话本名称,在Win9X下无作用,可为空字符串
) : DWORD;stdcall;
function RasCreatePhonebookEntry;external RasApiDll name 'RasCreatePhonebookEntryA';
函数返回值为0表示执行成功;否则为错误代码.
下面是一个应用例子,允许用户新建一个拨号连接.
var
dwResult : DWORD;
begin
//在当前窗口中新建拨号连接
dwResult := RasCreatePhonebookEntry( handle, '' );
if dwResult = 0 then
memo1.lines.add('新建拨号连接成功!')
else
memo1.lines.add('新建拨号连接失败:!' + GetRasError( dwResult ))
end;
2、修改拨号连接的属性
修改拨号连接的属性的RasAPI函数为RasEditPhonebookEntry,其函数原型为:
function RasEditPhonebookEntry(
hwnd : THandle; //新建拨号连接窗口的父窗口的句柄,为NIL表示桌面(DeskTop)
lpszPhonebook: pchar;//电话本名称,在Win9X下无作用,可为空字符串
lpszEntryName: pchar//拨号连接的名称,如'163'、'169'等
) : DWORD; stdcall;
function RasEditPhonebookEntry;external RasApiDll name 'RasEditPhonebookEntryA';
函数返回值为0表示执行成功;否则为错误代码.
下面是一个应用例子,允许用户修改指定拨号连接的属性.
var
dwResult : DWORD;
begin
//在当前窗口中修改拨号连接的属性
dwResult := RasEditPhonebookEntry( handle, '', '163' );
if dwResult = 0 then
memo1.lines.add('修改拨号连接成功!')
else
memo1.lines.add('修改拨号连接失败:!' + GetRasError( dwResult ))
end;
三、获取和设置拨号连接的拨号参数
用RasAPI函数RasGetEntryDialParams、RasSetEntryDialParams可以直接获取和设置指定拨号
连接的拨号参数,其中包括用户名称和用户密码!
1、获取拨号连接的拨号参数
获取拨号连接的拨号参数RasAPI函数为RasGetEntryDialParams,其函数原型为:
function RasGetEntryDialParams(
lpszPhonebook: pchar;//电话本名称,在Win9X下无作用,可为空字符串
pRASDIALPARAMS:LPRASDIALPARAMS;//拨号参数,是一个RASDIALPARAMS类型的指针
var lpfPassword : WordBool//是否需要用户密码
) : DWORD; stdcall;
function RasGetEntryDialParams;external RasApiDll name 'RasGetEntryDialParamsA';
参数pRASDIALPARAMS是一个RASDIALPARAMS类型的指针,指向一个拨号连接的拨号参数数据
的缓冲区,其中RASDIALPARAMS及LPRASDIALPARAMS的类型说明如下:
LPRASDIALPARAMS = ^RASDIALPARAMS;
RASDIALPARAMS = record
dwSize : DWORD;//该结构所占内存的大小(Bytes),一般设置为SizeOf(RASDIALPARAMS)
szEntryName : array[0..RAS_MaxEntryName] of char;//拨号连接名称
szPhoneNumber : array[0..RAS_MaxPhoneNumber] of char;//拨号号码
szCallbackNumber : array[0..RAS_MaxCallbackNumber] of char;//回叫号码
szUserName : array[0..UNLEN] of char;//用户名称
szPassword : array[0..PWLEN] of char;//用户密码
szDomain : array[0..DNLEN] of char;//域名
end;
函数返回值为0表示执行成功;否则为错误代码.
下面是一个应用例子,获取指定拨号连接的拨号参数.
var
dwResult : DWORD;
RASDIALPARAMSData : RASDIALPARAMS;
NeedPWD : WordBool;
begin
//指定拨号连接的名称
with RASDIALPARAMSData do
begin
dwSize := sizeof( RASDIALPARAMS );//结构大小
szEntryName := '163';//指定拨号连接的名称
szUserName := '';//其它五个参数初始化
szPassword := '';
szDomain := '';
szCallbackNumber := '';
szPhoneNumber := '';
end;
NeedPWD := true;//需要用户密码
//获取指定拨号连接的拨号参数
dwResult := RasGetEntryDialParams( '',@RASDIALPARAMSData,NeedPWD );
if dwResult <> 0 then //获取指定拨号连接的拨号参数失败
memo1.lines.add( '获取'+StrPAS(RASDIALPARAMSData.szEntryName )+'拨号参数失败:'
+ GetRasError( dwResult ))
else
begin//显示指定拨号连接的拨号参数
memo1.lines.add( StrPAS(RASDIALPARAMSData.szEntryName )+'拨号参数如下');
memo1.lines.add( '用户名称:' + StrPAS(RASDIALPARAMSData.szUserName ));
memo1.lines.add( '用户密码:' + StrPAS(RASDIALPARAMSData.szPassword ));
memo1.lines.add( '域 名:' + StrPAS(RASDIALPARAMSData.szDomain ));
memo1.lines.add( '回叫号码:' + StrPAS(RASDIALPARAMSData.szCallbackNumber ));
memo1.lines.add( '拨号号码:' + StrPAS(RASDIALPARAMSData.szPhoneNumber ));
end;
end;
2、设置拨号连接的拨号参数
设置拨号连接的拨号参数RasAPI函数为RasSetEntryDialParams,其函数原型为:
function RasSetEntryDialParams(
lpszPhonebook: pchar;//电话本名称,在Win9X下无作用,可为空字符串
pRASDIALPARAMS:LPRASDIALPARAMS;//拨号参数,是一个RASDIALPARAMS类型的指针
var lpfPassword : WordBool//是否删除用户密码
) : DWORD; stdcall;
function RasSetEntryDialParams;external RasApiDll name 'RasSetEntryDialParamsA';
参数pRASDIALPARAMS的说明同RasGetEntryDialParams.
参数lpfPassword的含义与RasGetEntryDialParams不同,在此表示是否删除用户密码,为
TRUE时将原来的用户密码删除.
函数返回值为0表示执行成功;否则为错误代码.
下面是一个应用例子,设置指定拨号连接的拨号参数.
var
dwResult : DWORD;
RASDIALPARAMSData : RASDIALPARAMS;
RemovePWD : WordBool;
begin
//指定拨号连接的拨号参数
with RASDIALPARAMSData do
begin
dwSize := sizeof( RASDIALPARAMS );//结构大小
szEntryName := '163';//指定拨号连接的名称
szUserName := 'MyName';//指定用户名称
szPassword := 'MyPassword';//指定用户密码
szDomain := 'MyDomain';//指定域名
szCallbackNumber := '';//指定回叫号码
szPhoneNumber := '';//指定拨号号码
end;
RemovePWD := false;//不需要删除用户密码
//设置指定拨号连接的拨号参数
dwResult := RasSetEntryDialParams( '',@RASDIALPARAMSData,RemovePWD );
if dwResult <> 0 then //设置指定拨号连接的拨号参数失败
memo1.lines.add( '设置'+StrPAS(RASDIALPARAMSData.szEntryName )+'拨号参数失败:'
+ GetRasError( dwResult ))
else
begin//显示指定拨号连接的拨号参数
memo1.lines.add( StrPAS(RASDIALPARAMSData.szEntryName )+'拨号参数设置成功');
memo1.lines.add( '用户名称:' + StrPAS(RASDIALPARAMSData.szUserName ));
memo1.lines.add( '用户密码:' + StrPAS(RASDIALPARAMSData.szPassword ));
memo1.lines.add( '域 名:' + StrPAS(RASDIALPARAMSData.szDomain ));
memo1.lines.add( '回叫号码:' + StrPAS(RASDIALPARAMSData.szCallbackNumber ));
memo1.lines.add( '拨号号码:' + StrPAS(RASDIALPARAMSData.szPhoneNumber ));
end;
end;
四、用指定的拨号连接拨号、挂断指定的拨号连接
1、用指定的拨号连接拨号
拨号有两种方法,一种是调用拨号网络中的拨号程序,就象用户自己用鼠标双击拨号连接名称一
样,用户可以修改拨号号码、用户名称和用户密码,最后由拨号网络来完成拨号过程;另一个方法则
是调用RasAPI函数.
(1)用拨号网络中的拨号程序
在程序中可以用如下代码:
winexec('rundll32.exe rnaui.dll,RnaDial 169',SW_SHOWNORMAL);
其中字符串中的最后一个参数“169”为拨号连接的名称。
(2)用RasAPI函数拨号
用拨号连接拨号的RasAPI函数为RasDial,其函数原型为:
function RasDial(
pRasDialExtensions : LPRASDIALEXTENSIONS;//在WIN9X下无用,可设置为NIL
lpszPhonebook : PChar;//电话本名称,在Win9X下无作用,可为空字符串
lpRasDialParams : LPRASDIALPARAMS;//拨号参数
dwNotifierType : DWORD;//消息通知方式
handle : TRasDialFunc;//消息处理事件
var lphRasConn : DWORD//返回的成功连接的连接句柄
) : DWORD; stdcall;
function RasDial;external RasApiDll name 'RasDialA';
参数pRASDIALPARAMS的说明同RasGetEntryDialParams.
参数dwNotifierType表示消息通知方式.在拨号过程中,系统发出拨号事件消息可以通知拨号
进度,因而需要提供接受消息的方式和处理消息的函数.当其值为$FFFFFFFF时,则参数handle被
视为一个窗口的句柄,事件消息被发生该窗口处理;当其值为0时,handle被视为TRasDialFunc类型
的函数的指针;当其值为1时,handle被视为TRasDialFunc1类型的函数的指针.
参数handle表示消息处理函数指针,其类型可以THandle、TRasDialFunc、TRasDialFunc1.当该
参数不为NULL或NIL时,其代表的消息处理函数指针将接受拨号进度通知消息;为NIL时,拨号过程由
异步方式变为同步方式,直到拨号过程成功或失败后RasDial函数才返回.详细可参见Delphi帮助文件
中关于RasDial函数的帮助。
当拨号连接成功时,lphRasConn将表示其连接句柄.
函数返回值为0表示执行成功;否则为错误代码.
下面是一个应用例子,按指定的拨号参数拨号.
var
RASDIALPARAMSData : RASDIALPARAMS;
dwResult : DWord;
RasCon : DWord;
begin
//指定拨号连接的拨号参数
with RASDIALPARAMSData do
begin
dwSize := sizeof( RASDIALPARAMS );//结构大小
szEntryName := '163';//指定拨号连接的名称
szUserName := 'MyName';//指定用户名称
szPassword := 'MyPassword';//指定用户密码
szDomain := 'MyDomain';//指定域名
szCallbackNumber := '';//指定回叫号码
szPhoneNumber := '';//指定拨号号码
end;
//用指定的拨号参数拨号,采用同步拨号方式
dwResult := RasDial( NIL,'',@RASDIALPARAMSData,0,NIL,RasCon );
if dwResult <> 0 then //设置指定拨号连接的拨号参数失败
memo1.lines.add( '用'+StrPAS(RASDIALPARAMSData.szEntryName )+'拨号失败:'
+ GetRasError( dwResult ))
else
memo1.lines.add( '用'+StrPAS(RASDIALPARAMSData.szEntryName )+'拨号成功!' );
end;
2、挂断指定的拨号连接
挂断拨号连接的RasAPI函数为RasHangUp,其函数原型为:
function RasHangUp(
hRasConn : DWORD//要挂断的拨号连接的句柄
) : DWORD; stdcall;
function RasHangUp;external RasApiDll name 'RasHangUpA';
函数返回值为0表示执行成功;否则为错误代码.
下面是一个应用例子,挂断由RasDial建立的拨号连接.
//挂断由RasDial建立的拨号连接
dwResult := RasHangUp( RasCon );
if dwResult <> 0 then //挂断失败
memo1.lines.add( '挂断失败:' + GetRasError( dwResult ))
else
memo1.lines.add( '挂断成功!');
五、获取当前活动的连接及其连接状态
1、获取当前活动的连接
获取当前活动的连接的RasAPI函数为RasEnumConnections,其函数原型为:
function RasEnumConnections( var lprasconn : RASCONN ;//接收活动连接的缓冲区的指针
var lpcb: DWORD;//缓冲区大小
var lpcConnections : DWORD//实际的活动连接数
) : DWORD; stdcall;
function RasEnumConnections;external RasApiDll name 'RasEnumConnectionsA';
参数lprasconn提供了一个RASCONN类型数组的指针,指向一个接收活动连接的缓冲
区,其中RASCONN的类型说明如下:
RASCONN = record
dwSize : DWORD;//该结构所占内存的大小(Bytes),一般设置为SizeOf(RASCONN)
hrasconn : HRASCONN;//活动连接的句柄
szEntryName : array[0..RAS_MaxEntryName] of char;//活动连接的名称
szDeviceType : array[0..RAS_MaxDeviceType] of char;//活动连接的所用的设备类型
szDeviceName : array[0..RAS_MaxDeviceName] of char;//活动连接的所用的设备名称
end;
参数lpcb为缓冲区大小(Bytes).
参数lpcConnections将返回实际的连接数目.
函数返回值为0表示执行成功;否则为错误代码.
2、获取指定连接的连接状态
获取指定连接的连接状态的RasAPI函数为RasGetConnectStatus,其函数原型为:
function RasGetConnectStatus(
hrasconn : HRASCONN; //指定活动连接的句柄
lprasconnstatus : LPRASCONNSTATUS//连接状态参数
) : DWORD; stdcall;
function RasGetConnectStatus;external RasApiDll name 'RasGetConnectStatusA';
连接状态参数lprasconnstatus是一个RASCONNSTATUS类型的指针,将返回连接状态参数.
RASCONNSTATUS和LPRASCONNSTATUS的类型说明如下:
LPRASCONNSTATUS = ^RASCONNSTATUS;
RASCONNSTATUS = record
dwSize : DWORD;//该结构所占内存的大小(Bytes),一般设置为SizeOf(RASCONNSTATUS)
rasconnstate : RASCONNSTATE;//连接状态标识,一组DWORD类型数值的集合。
dwError : DWORD;//错误类型标识符
szDeviceType : array[0..RAS_MaxDeviceType] of char;//活动连接的所用的设备类型
szDeviceName : array[0..RAS_MaxDeviceName] of char;//活动连接的所用的设备名称
end;
函数返回值为0表示执行成功;否则为错误代码.
下面是一个应用例子,列出了当前系统中活动的连接的名称及其连接状态.
注意,应在RASCONN缓冲区的第一个RASCONN结构中设置dwSize.
const
MaxConnections = 10;//最多的拨号连接数目
var
connections : array[0..MaxConnections-1] of RASCONN;
longSize : dword;
intAvailabelConnections : dword;
intIndex : integer;
dwResult : DWORD;
strTemp : string;
RASCONNSTATUSData : RASCONNSTATUS;
begin
connections[ 0 ].dwSize := sizeof(RASCONN);//结构的大小
longSize := MaxConnections * connections[ 0 ].dwSize;//缓冲区大小
intAvailabelConnections := 0;//实际的活动连接的数目
//获取当前系统中活动的连接
dwResult := RasEnumConnections( connections[ 0 ], longSize,intAvailabelConnections );
if dwResult <> 0 then //获取当前系统中活动的连接
memo1.lines.add( '获取当前系统中活动的连接:' + GetRasError( dwResult ))
else
begin
memo1.lines.add( '当前系统中活动的连接' + inttostr( intAvailabelConnections )
+ '个,列举如下' );
for intIndex := 0 to intAvailabelConnections - 1 do
begin
strTemp := '连接名称:' + StrPAS( connections[ intIndex ].szEntryName )
+ ' 设备类型:' + StrPAS( connections[ intIndex ].szDeviceType )
+ ' 设备名称:' + StrPAS( connections[ intIndex ].szDeviceName );
//获取连接状态
dwResult := RasGetConnectStatus( connections[ intIndex ].hRasConn,@RASCONNSTATUSData );
if 0 <> dwResult then
strTemp := strTemp + ' 连接状态未知:' + GetRasError( dwResult )
else if RASCONNSTATUSData.rasconnstate = RASCS_Connected then
strTemp := strTemp + ' 连接状态:已连接'
else
strTemp := strTemp + ' 连接状态
' +
inttostr(RASCONNSTATUSData.rasconnstate)+')';
memo1.lines.add( strTemp );
end;
end;
end;
以上程序在PWIN98+Delphi3.0下调试通过。
avant (2000-04-08 20:01:00)
xWolf:
真厉害!
szCallbackNumber := '';//指定回叫号码
szPhoneNumber := '';//指定拨号号码
回叫号码有什么用?拨号号码是不是只能是ISP的号码?可不可以是任一连有
计算机的号码?
我对此很感兴趣,但所知甚少,希望多多赐教!
谢谢!
spear (2000-04-08 22:07:00)
拨号号码就是RAS服务器上的电话号码, 当然可是ISP的号码,
回叫号码就是RAS服务器可以回拨的你的号码.
我看还是去www.xxxcl.com找个控件吧, 卦装得不错, 名字我
忘了, 用起来还是很简单的.
网痞 (2000-04-08 23:54:00)
在DELPHI程序中拨号上网
用MODEM拨号上网,仍是大多数个人网民选择上网的方式.如果能在我们的应用程序中启动拨号
连接(如IE浏览器程序中的自动拨号功能),无疑将会方便我们的软件用户(不用再切换应用程序,
运行拨号网络),提高我们的软件的友好性从而提高软件的竞争力.
在WIN9X下,如果安装了拨号网络,则在WINDOWS系统的系统目录System下将有两个拨号网络管理
程序库RasApi32.DLL和RasApi16.DLL,我们可利用其中的函数来创建、修改拨号连接,并利用指定的
拨号连接进行拨号上网。
一、新建拨号连接
当WIN9X系统中已经建立了拨号连接,则可利用现成的拨号连接。如果没有拨号连接,则需要新建
一个拨号连接。RasAPI中提供了相应的函数,其函数名为RasCreatePhonebookEntryA,函数原型为:
function RasCreatePhonebookEntryA( hwnd : THandle;lpszPhonebook: pchar ) : DWORD;
stdcall; { 位于interface部分 }
function RasCreatePhonebookEntryA ; external 'Rasapi32.dll';{ 位于implementation部分 }
参数:
hwnd(THandle):新建拨号连接窗口的父窗口的句柄,可以为TForm的Handle,为NIL表示
Windows桌面(DeskTop)
lpszPhonebook(pchar):电话本名称,在Win9X下无作用,可设为空字符串
函数返回值:
0表示执行成功;否则为错误.
下面是一个新建拨号连接的例子.
{ 新建拨号连接 }
procedure TForm1.Button1Click(Sender: TObject);
var
dwResult : DWORD;
begin
//在当前窗口中新建拨号连接
dwResult := RasCreatePhonebookEntryA( handle, '' );
if dwResult = 0 then
memo1.lines.add('新建拨号连接成功!')
else
memo1.lines.add('新建拨号连接失败!')
end;
二、修改指定拨号连接的属性
如果用户需要修改拨号连接的属性如电话号码、国家及区号、连接方式、服务器类型
等,可以用RasAPI函数来实现,其函数名为RasEditPhonebookEntryA,函数原型为:
function RasEditPhonebookEntryA( hwnd : THandle; lpszPhonebook: pchar;
lpszEntryName: pchar ) : DWORD;stdcall; { 位于interface部分 }
function RasEditPhonebookEntryA; external 'Rasapi32.dll';{ 位于implementation部分 }
参数:
hwnd(THandle):新建拨号连接窗口的父窗口的句柄,可以为TForm的Handle,为NIL表示
Windows桌面(DeskTop)
lpszPhonebook(pchar):电话本名称,在Win9X下无作用,可设为空字符串
lpszEntryName:( pchar):要修改的拨号连接的名称,如'163'、'169'等
函数返回值:
0表示执行成功;否则为错误.
下面是一个修改指定拨号连接属性的例子.
{ 修改指定拨号连接属性 }
procedure TForm1.Button2Click(Sender: TObject);
var
dwResult : DWORD;
strDialName : string;
begin
strDialName := '163';//拨号连接的名称设为163
//在当前窗口中指定修改拨号连接的属性
dwResult := RasEditPhonebookEntryA( handle, '', PChar( strDialName ) );
if dwResult = 0 then
memo1.lines.add('修改拨号连接' + strDialName + '成功!')
else
memo1.lines.add('修改拨号连接' + strDialName + '失败!')
end;
三、获取当前系统中可用的拨号连接名称
为了让用户选择使用拨号连接进行拨号,我们需要获取系统中已建立的拨号连接的名称。在建立了
拨号连接后,WIN9X将拨号连接的名称和属性写在了注册表中,我们可以从注册表中获取当前系统中可
用的拨号连接名称及在Internet Explorer中设置的默认连接名称。
在注册表的HKEY_USERS/.Default/RemoteAccess/Addresses下,列出了已经在拨号网络中建立了的
拨号连接的名称及其属性设置,其中各项目的名称即为可用的拨号连接的名称;各项目的值即为各拨号
连接的属性设置.我们只要读出各项目的名称即可获取当前系统中可用的拨号连接名称.
如果在Internet Explorer中设置了默认连接名称(查看=》Internet选项=》连接=》连接=》
设置=》使用以下拨号网络连接),则在注册表的HKEY_USERS/.Default/RemoteAccess下,有一个字符
串类型的键值,键值名InternetProfile,其值即为Internet Explorer中设置的默认连接名称。
下面是一个获取当前系统中可用的拨号连接名称的例子.
{ 注意在Uses中增加Registry单元,用于操作注册表 }
{ 获取当前系统中可用的拨号连接名称 }
procedure TForm1.Button3Click(Sender: TObject);
var
registryTemp : TRegistry;
stringsTemp : TStringlist;
intIndex : integer;
begin
registryTemp := TRegistry.Create;
stringsTemp := TStringlist.Create;
with registryTemp do
begin
RootKey := HKEY_USERS;//根键设置为HKEY_USERS
//如果存在子键.Default/RemoteAccess/Addresses
if OpenKey('.Default/RemoteAccess/Addresses',false) then
GetValueNames( stringsTemp );//读出各项目的名称,即拨号连接名称
CloseKey;
end;
//当前系统中可用的拨号连接
memo1.lines.add( '******************当前系统中有'+ IntToStr( stringsTemp.count )
+'个可用的拨号连接如下****************');
for intIndex := 0 to stringsTemp.count - 1 do
memo1.lines.add( stringsTemp.strings[ intIndex ] );
//列出Internet Explorer中设置的默认连接名称
if registryTemp.OpenKey('.Default/RemoteAccess',false) then
memo1.lines.add( 'Internet Explorer中设置的默认连接名称为' +
registryTemp.ReadString('InternetProfile') );
//释放内存
registryTemp.free;
stringsTemp.free;
end;
四、用指定的拨号连接拨号
以上的三个工作的目的就是为了拨号上网,现在就来看看如果用指定的拨号连接拨号上网。
最好的方法就是调用WIN9X的拨号网络服务了,就是运行WIN9X下的现成程序。
在Delphi程序中可以用如下代码实现拨号上网:
winexec('rundll32.exe rnaui.dll,RnaDial 163',SW_SHOWNORMAL);
其中字符串中的最后一个参数“163”为拨号连接的名称。
下面是一个用指定的拨号连接拨号上网的例子.
{ 用指定的拨号连接拨号上网 }
procedure TForm1.Button4Click(Sender: TObject);
var
strDialName : string;
begin
strDialName := '163';//拨号连接的名称设为163
memo1.lines.add( '******************用拨号连接'+ strDialName
+'实现拨号上网****************');
winexec( PChar('rundll32.exe rnaui.dll,RnaDial ' + strDialName),SW_SHOWNORMAL);
end;
以上程序在PWIN98+Delphi3.0下调试通过。
(作者:王发军 wangfajun@163.net http://wangfajun.163.net)
刚玩过拨号,呵呵,借花献佛 ^_^
avant (2000-04-10 15:53:00)
<<刚玩过拨号
俺也是,不过是连到163,用了一个TDialup请松搞定,设用户名、密码什么
的都挺简单,问题是现在想直接在两台远程(>100km)计算机之间通信,不通过ISP,
那么是不是要在两台机子上装上RAS服务器软件???具体如何实现?多多赐教!
谢谢!
Luckm (2000-04-10 22:06:00)
利用DirectX的DirectPlay!
honghs (2000-04-11 10:01:00)
找个有例子的拨号控件rascomp。rascomp的例子已经是够详细的了:建立、删除、编辑、
改名拨号连接都有,你把先把所有E文都改成中文,再把界面改一下,加上一些功能,然后搞个About窗口把自己的大名挂上就成了。
至少肚子问题解决了。
网痞 (2000-04-13 1:15:00)
给avant:
如果是NT,RAS都得装,注意设定拨进和拨出。
问大家:
在NT下取拨号信息出问题了,如下:
int intIndex;
RASENTRYNAME PhoneEntries[MaxPhoneEntries];
unsigned long dwSize, dwEntries, dwResult;
//在RASENTRYNAME缓冲区的第一个RASENTRYNAME结构中设置dwSize
PhoneEntries[0].dwSize = sizeof(RASENTRYNAME);
dwSize = MaxPhoneEntries * sizeof(RASENTRYNAME); //为缓冲区的大小
//调用RasAPI函数,获取当前系统中可用的拨号连接名称
dwResult = RasEnumEntries(NULL, NULL, &PhoneEntries[0], &dwSize, &dwEntries);
此时dwResult 为 632,错误信息为"结构大小不正确。",何解?
dyxfromxf (2000-05-09 16:16:00)
感谢各位,尤其是xWolf
dyxfromxf (2000-05-09 16:36:00)
接受答案了.
xWolf的回答最终被接受。