<?xml version="1.0" encoding="utf-8" ?>
<!-- generator="crazycoder cms 1.0(beta)" -->
<rss version="2.0" xmlns:sns="http://www.crazycoder.cn/rss/news">
	<channel>
		<title>vb开发activex控件</title>
		<description></description>
		<link>http://CrazyCoder.cn/Tag/18026/Index.html</link>
		<lastBuildDate>2010-03-11</lastBuildDate>
		<generator>CrazyCoder 1.0(beta)</generator>
		<language>zh-cn</language>
		<copyright>Copyright 1996 - 2008 疯狂代码  All Rights Reserved.</copyright>
		<pubDate>2010-03-11</pubDate>
		<item>
			<title><![CDATA[vbactivex控件:用vb6的ActiveX控件实现异步下载-vb教程]]></title>
			<link>http://CrazyCoder.cn/VisualBasic/Article15599.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
          6<img src='/icons/72753de.gif' />ActiveXControl控件实现异步下载<br/><br/><br/>序:笔者(airon,softWorker)注意到<img src='/icons/72753dou.gif' />在VB6中<img src='/icons/72753dou.gif' />要实现文件下载<img src='/icons/72753dou.gif' /><img src='/icons/72753yi.gif' />般用和思路方法都是使用第 3方Control控件<img src='/icons/72753dou.gif' />比如IEControl控件呀<img src='/icons/72753dou.gif' />winscok呀<img src='/icons/72753dou.gif' />但在本文中<img src='/icons/72753dou.gif' />不用添加任何Control控件<img src='/icons/72753dou.gif' />也不引用任何object<img src='/icons/72753dou.gif' />就可实现文件下载<img src='/icons/72753dou.gif' />而且<img src='/icons/72753chengxu.gif' />不支持文件下载进度<img src='/icons/72753dou.gif' />捕获下载<img src='/icons/72753cuowu.gif' /><img src='/icons/72753dou.gif' />激活下载完成事件等<img src='/icons/72753dou2.gif' /><br/><br/>具体思路方法:<br/>1.新建<img src='/icons/72753yi.gif' />VB6工程(默认有<img src='/icons/72753yi.gif' />个Form1窗体)<br/>2.选择工程菜单<img src='/icons/72753de.gif' />“添加用户Control控件”来添加<img src='/icons/72753yi.gif' />个用户Control控件<img src='/icons/72753dou2.gif' /><br/>3.更改Activex用户Control控件<img src='/icons/72753de.gif' />名称<img src='/icons/72753dou.gif' />更改为 Downloader (此项可省) <img src='/icons/72753dou2.gif' /><br/>4.输入代码:(在用户Control控件<img src='/icons/72753de.gif' />代码窗口中)<br/><br/><STRONG>Option Explicit<br/>Event DownloadProgress(CurBytes As Long, MaxBytes As Long, SaveFile As String)<br/>Event DownloadError(SaveFile As String)<br/>Event DownloadComplete(MaxBytes As Long, SaveFile As String)<br/>&acute;Public downStat As Boolean</STRONG><br/><br/><br/><STRONG>Public Function CancelAsyncRead<img src='/icons/72753kh.gif' /> As Boolean<br/> _disibledevent=>&acute; Exit Sub<br/>&acute; End If<br/>&acute; Static Cs As Integer<br/>&acute; If Cs &gt; 2 Then Cs = 0<br/>&acute; UserControl.Picture = P1(Cs).Picture<br/>&acute; Cs = Cs + 1<br/>&acute; DoEvents<br/>&acute;End Sub<br/>Private Sub UserControl_AsyncReadComplete(AsyncProp As AsyncProperty)<br/> _disibledevent=> f = AsyncProp.Value<br/> Open AsyncProp.PropertyName For Binary Access Write As #fn<br/> Put #fn, , f<br/> Close #fn<br/> Else<br/> RaiseEvent DownloadError(AsyncProp.PropertyName)<br/> End If<br/> RaiseEvent DownloadComplete(CLng(AsyncProp.BytesMax), AsyncProp.PropertyName)<br/> downStat = False<br/>End Sub<br/>Private Sub UserControl_AsyncReadProgress(AsyncProp As AsyncProperty)<br/> _disibledevent=> End If<br/>End Sub<br/>&acute;Private Sub UserControl_Resize<img src='/icons/72753kh.gif' /><br/>&acute; SizeIt<br/>&acute;End Sub<br/>Public Sub BeginDownload(url As String, SaveFile As String)<br/> _disibledevent=> UserControl.AsyncRead url, vbAsyncTypeByteArray, SaveFile, vbAsyncReadForceUpdate<br/> Timer1.Enabled = True<br/> Exit Sub<br/>ErrorBeginDownload:<br/> downStat = False<br/> MsgBox Err &amp; \"开始下载数据失败！\" _<br/> &amp; vbCrLf &amp; vbCrLf &amp; \"<img src='/icons/72753cuowu.gif' />:\" &amp; Err.Description, vbCritical, \"<img src='/icons/72753cuowu.gif' />\"<br/>End Sub<br/>&acute;Public Sub SizeIt<img src='/icons/72753kh.gif' /><br/>&acute; _disibledevent=>&acute; .Height = ScaleY(32, vbPixels, vbTwips)<br/>&acute; End With<br/>&acute; Exit Sub<br/>&acute;ErrorSizeIt:<br/>&acute;End Sub<br/>&acute;Public Sub kill<img src='/icons/72753kh.gif' /><br/>&acute; downStat = False<br/>&acute; Dim m As AsyncProperty<br/>&acute; MsgBox m.Value<br/>&acute;End Sub</STRONG><br/><br/>-----------------------------------------------------<br/><img src='/icons/72753chengxu.gif' />介绍说明:<br/><br/>本文采取VB6中OCX中<img src='/icons/72753de.gif' /> 异步获取思路方法来下载文件<img src='/icons/72753dou2.gif' /><br/>用到 AsyncRead(异步读取)<br/><br/>文中带注解<img src='/icons/72753de.gif' />部分为下载界面控制<img src='/icons/72753dou.gif' />在下载时<img src='/icons/72753dou.gif' />会有像 FlashGet<img src='/icons/72753yi.gif' />样<img src='/icons/72753de.gif' />有动画图标在动<img src='/icons/72753dou.gif' />要添加此功能<img src='/icons/72753dou.gif' />请在用户Control控件上添加 3个image<img src='/icons/72753dou.gif' />(image上要带图片)<br/><br/><br/>-----------------------------------------------------<br/><br/>4.关闭用户Control控件<img src='/icons/72753de.gif' />代码和设置窗口<img src='/icons/72753dou.gif' />回到 Form1<br/>5.这时你会看到在左边<img src='/icons/72753de.gif' />工具栏下多了<img src='/icons/72753yi.gif' />用户Control控件<img src='/icons/72753dou.gif' />把它添加到窗体上<img src='/icons/72753dou2.gif' />命名为 Downloader1<br/>6.在窗体上添加<img src='/icons/72753yi.gif' /> command 控钮<img src='/icons/72753dou.gif' />命名为 Command1<br/>7.在窗体 Form1<img src='/icons/72753de.gif' />代码窗口输入代码:<br/><br/><STRONG>Option Explicit<br/>&acute;<img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><br/>&acute;<br/>&acute; <img src='/icons/72753chengxu.gif' />编写<img src='/icons/72753dou.gif' /> airon,softWoker 2004-02-20<br/>&acute; </STRONG><STRONG> </STRONG><br/><STRONG>&acute; </STRONG><br/><STRONG>&acute;<br/>&acute;<img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><img src='/icons/72753dd.gif' /><br/>Private Sub Command1_Click<img src='/icons/72753kh.gif' /><br/> Downloader1.BeginDownload url, SaveFile 
		
          
              
          <br/>
        <br/>
          <br/> &acute;请把 URL 替代为 Http://文件路径<br/> &acute;请把 savefile 替代为下载到本地文件<img src='/icons/72753de.gif' />路径和名称<img src='/icons/72753dou2.gif' /><br/>End Sub<br/> <br/>Private Sub Downloader1_DownloadComplete(MaxBytes As Long, SaveFile As String)<br/> MsgBox \"文件下载完成<img src='/icons/72753dou.gif' />保存文件名为:\" &amp; SaveFile, vbInformation Or vbOKOnly, \"提示:\"<br/>End Sub</STRONG><br/><br/><STRONG>Private Sub Downloader1_DownloadError(SaveFile As String)<br/> MsgBox \"下载发生<img src='/icons/72753cuowu.gif' />！\", vbExclamation Or vbOKOnly, \"<img src='/icons/72753cuowu.gif' />:\"<br/>End Sub</STRONG><br/><br/><STRONG>Private Sub Downloader1_DownloadProgress(CurBytes As Long, MaxBytes As Long, SaveFile As String)<br/> &acute;在这里添加进度第<img src='/icons/72753de.gif' />代码<br/>End Sub</STRONG><br/><br/>最后申明: 本文为 airon,softWorker 原作<img src='/icons/72753dou.gif' />未经本人同意<img src='/icons/72753dou.gif' />不作出版<img src='/icons/72753dou.gif' />(CSDN 除外),但可以转载<img src='/icons/72753dou.gif' />转载时请注明作者<img src='/icons/72753dou2.gif' /> 如需在源<img src='/icons/72753chengxu.gif' /><img src='/icons/72753de.gif' />请mail联系我<img src='/icons/72753dou.gif' />  <img src='/icons/72753dou2.gif' />希望本文能给广大读者带来帮助<img src='/icons/72753dou2.gif' /><br/><br/><br/><br />  <a href="/mypdf/15599.pdf" title="查看 vbactivex控件:用vb6的ActiveX控件实现异步下载-vb教程 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>VB教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/VisualBasic/Article15599.html</guid>
		</item>
		<item>
			<title><![CDATA[activexdll:用vb制作ActiveX Dll中，怎么让程序连接远程机器1888端口，并且等待接收信息-vb教程]]></title>
			<link>http://CrazyCoder.cn/VisualBasic/Article15508.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
          制作ActiveX Dll中<img src='/icons/4103dou.gif' />如何让<img src='/icons/4103chengxu.gif' />连接远程机器1888端口<img src='/icons/4103dou.gif' />并且等待接收信息<br/><br/>在 asp中无法返回信息阿<img src='/icons/4103dou2.gif' /><br/><br/>这个没有问题<img src='/icons/4103dou2.gif' />可以连接<img src='/icons/4103dou2.gif' /><br/><br/>Winsock1.RemoteHost = \"61.144.176.36\"<br/>Winsock1.RemotePort = 3052<br/>Winsock1.Connect<br/><br/>下面<img src='/icons/4103de.gif' /><img src='/icons/4103dou2.gif' />就有问题了<img src='/icons/4103dou2.gif' /><br/><br/>Private Sub Winsock1_DataArrival(ByVal <img src='/icons/4103byte.gif' />sTotal As Long)<br/><br/>&nbsp;<br/><br/>这个<img src='/icons/4103hanshu.gif' />在asp中如何<img src='/icons/4103diaoyong.gif' />阿<img src='/icons/4103dou2.gif' /><br/><br/>或者有没有别<img src='/icons/4103de.gif' />办法阿<img src='/icons/4103dou2.gif' /><br/><br/>谢谢<img src='/icons/4103dou2.gif' /><br/><br/>Email:qubolwyx@163.com<br/><br/><br />  <a href="/mypdf/15508.pdf" title="查看 activexdll:用vb制作ActiveX Dll中，怎么让程序连接远程机器1888端口，并且等待接收信息-vb教程 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>VB教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/VisualBasic/Article15508.html</guid>
		</item>
		<item>
			<title><![CDATA[vbactivex控件:如何在VB中实现ActiveX控件的IobjectSafety接口-vb教程]]></title>
			<link>http://CrazyCoder.cn/VisualBasic/Article15406.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
          VB中实现ActiveXControl控件<img src='/icons/41014de.gif' />IobjectSafety接口<br/><br/><br/>--------------------------------------------------------------------------------<br/><br/><br/>总述<br/>本文叙述了如何在VB中实现Control控件<img src='/icons/41014de.gif' />IobjectSafety接口<img src='/icons/41014dou.gif' />以标志该Control控件是脚本安全和<img src='/icons/41014chushi.gif' />化安全<img src='/icons/41014de.gif' /><img src='/icons/41014dou2.gif' />VBControl控件默认<img src='/icons/41014de.gif' />处理方式是在注册表中注册组件类来标识其安全性<img src='/icons/41014dou.gif' />但实现IobjectSafety接口是更好<img src='/icons/41014de.gif' />思路方法<img src='/icons/41014dou2.gif' />本言语包括了实现过程中所需<img src='/icons/41014de.gif' />所有代码<img src='/icons/41014dou2.gif' /> <br/><br/>请注意<img src='/icons/41014dou.gif' />Control控件只有确确实实是安全<img src='/icons/41014de.gif' /><img src='/icons/41014dou.gif' />才能被标识为“安全<img src='/icons/41014de.gif' />”<img src='/icons/41014dou2.gif' />本文并未论及如何确保Control控件<img src='/icons/41014de.gif' />安全性<img src='/icons/41014dou.gif' />这个问题请参阅Internet Client Software Development Kit (SDK)中<img src='/icons/41014de.gif' />相关文档 \"Safe Initialization and Scripting for ActiveX Controls\"<img src='/icons/41014dou.gif' />它在Component Development 栏目中<img src='/icons/41014dou2.gif' /> <br/><br/><br/><br/>相关信息:<br/>&lt;此处略去了<img src='/icons/41014yi.gif' />段也许无关紧要<img src='/icons/41014de.gif' />警告&gt;<br/><br/>现在开始循序渐进地举例介绍说明怎样创建<img src='/icons/41014yi.gif' />个简单<img src='/icons/41014de.gif' />VBControl控件<img src='/icons/41014dou.gif' />以及怎样将它标识为脚本安全和<img src='/icons/41014chushi.gif' />化安全<img src='/icons/41014dou2.gif' /><br/>首先新建<img src='/icons/41014yi.gif' />个文件夹来存放在本例中所产生<img src='/icons/41014de.gif' />文件<img src='/icons/41014dou2.gif' /><br/><br/>从VB CD-ROM取得OLE 自动化类库<img src='/icons/41014de.gif' />制作工具<img src='/icons/41014dou2.gif' />将VB安装光盘中\\Common\\Tools\\VB\\Unsupprt\\Typlib\\目录下所有内容<img src='/icons/41014yi.gif' />并拷贝到前面新建<img src='/icons/41014de.gif' />项目文件夹中<img src='/icons/41014dou2.gif' /><br/><br/><br/>把下列内容拷贝到“记事本”中<img src='/icons/41014dou.gif' />然后保存到上述文件夹<img src='/icons/41014dou.gif' />文件名为Objsafe.odl: <br/><br/><br/> [<br/> uuid(C67830E0-D11D-11cf-BD80-00AA00575603),<br/> help<img src='/icons/41014string.gif' />(\"VB IObjectSafety Interface\"),<br/> version(1.0)<br/> ]<br/> library IObjectSafetyTLB<br/> {<br/> importlib(\"stdole2.tlb\");<br/> [<br/> uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064),<br/> help<img src='/icons/41014string.gif' />(\"IObjectSafety Interface\"),<br/> odl<br/> ]<br/> <img src='/icons/41014int.gif' />erface IObjectSafety:IUnknown {<br/> [help<img src='/icons/41014string.gif' />(\"GetInterfaceSafetyOptions\")]<br/> HRESULT GetInterfaceSafetyOptions(<br/> [in] long riid,<br/> [in] long *pdwSupportedOptions,<br/> [in] long *pdwEnabledOptions);<br/><br/> [help<img src='/icons/41014string.gif' />(\"SetInterfaceSafetyOptions\")]<br/> HRESULT SetInterfaceSafetyOptions(<br/> [in] long riid,<br/> [in] long dwOptionsSetMask,<br/> [in] long dwEnabledOptions);<br/> }<br/> }<br/>在命令行提示符下切换到项目文件夹<img src='/icons/41014dou.gif' />输入下列命令创建<img src='/icons/41014yi.gif' />个.tlb 文件:<br/><br/><br/>MKTYPLIB objsafe.odl /tlb objsafe.tlb <br/>在VB中新建<img src='/icons/41014yi.gif' />个ActiveX Control 项目<img src='/icons/41014dou2.gif' />修改属性<img src='/icons/41014dou.gif' />把项目命名为IobjSafety<img src='/icons/41014dou.gif' />Control控件命名为DemoCtl<img src='/icons/41014dou2.gif' />在Control控件上放置<img src='/icons/41014yi.gif' />个按钮<img src='/icons/41014dou.gif' />命名为cmdTest<img src='/icons/41014dou.gif' />在它<img src='/icons/41014de.gif' />Click事件中加入<img src='/icons/41014yi.gif' />句代码 MsgBox \"Test\" <img src='/icons/41014dou2.gif' /><br/><br/><br/>打开菜单“工程-&gt;引用”<img src='/icons/41014dou.gif' />点“浏览”<img src='/icons/41014dou.gif' />找到刚刚建立<img src='/icons/41014de.gif' />Objsafe.tlb<img src='/icons/41014dou.gif' />把它加入到引用中<img src='/icons/41014dou2.gif' /><br/><br/><br/>增加<img src='/icons/41014yi.gif' />个新module名为basSafeCtl<img src='/icons/41014dou.gif' />并在其中加入下列代码:<br/><br/><br/> Option Explicit<br/><br/> Public Const IID_IDispatch = \"{00020400-0000-0000-C000-000000000046}\"<br/> Public Const IID_IPersistStorage = _<br/> \"{0000010A-0000-0000-C000-000000000046}\"<br/> Public Const IID_IPersistStream = _<br/> \"{00000109-0000-0000-C000-000000000046}\"<br/> Public Const IID_IPersistPropertyBag = _<br/> \"{37D84F60-42CB-11CE-8135-00AA004BB851}\"<br/><br/> Public Const INTERFACESAFE_FOR_UNTRUSTED_CALLER = &amp;H1<br/> Public Const INTERFACESAFE_FOR_UNTRUSTED_DATA = &amp;H2 
		
          
              
          <br/>
        <br/>
          <br/> Public Const E_NOINTERFACE = &amp;H80004002<br/> Public Const E_FAIL = &amp;H80004005<br/> Public Const MAX_GUIDLEN = 40<br/><br/> Public Declare Sub CopyMemory Lib \"kernel32\" Alias \"RtlMoveMemory\" _<br/> (pDest As Any, pSource As Any, ByVal ByteLen As Long)<br/> Public Declare Function StringFromGUID2 Lib \"ole32.dll\" (rguid As _<br/> Any, ByVal lpstrClsId As Long, ByVal cbMax As Integer) As Long<br/><br/> Public Type udtGUID<br/> Data1 As Long<br/> Data2 As Integer<br/> Data3 As Integer<br/> Data4(7) As Byte<br/> End Type<br/><br/> Public m_fSafeForScripting As Boolean<br/> Public m_fSafeForInitializing As Boolean<br/><br/> Sub Main<img src='/icons/41014kh.gif' /><br/> m_fSafeForScripting = True<br/> m_fSafeForInitializing = True<br/> End Sub<br/>在工程属性中把启动对象改成Sub Main确保上述代码会被执行<img src='/icons/41014dou2.gif' />m_fSafeForScripting 和m_fSafeForInitializing两件变量<img src='/icons/41014de.gif' />值分别指定了脚本安全和<img src='/icons/41014chushi.gif' />化安全取值<img src='/icons/41014dou2.gif' /><br/><br/><br/>打开Control控件代码窗口<img src='/icons/41014dou.gif' />在声明部分加入如下代码(如果有Option Explicit语句<img src='/icons/41014dou.gif' />当然要保证代码放在其后): <br/><br/><br/>Implements IObjectSafety<br/>把下面两个过程代码拷贝到Control控件代码中:<br/><br/><br/> Private Sub IObjectSafety_GetInterfaceSafetyOptions(ByVal riid As _<br/> Long, pdwSupportedOptions As Long, pdwEnabledOptions As Long)<br/><br/> Dim Rc As Long<br/> Dim rClsId As udtGUID<br/> Dim IID As String<br/> Dim bIID<img src='/icons/41014kh.gif' /> As Byte<br/><br/> pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER Or _<br/> INTERFACESAFE_FOR_UNTRUSTED_DATA<br/><br/> If (riid &lt;&gt; 0) Then<br/> CopyMemory rClsId, ByVal riid, Len(rClsId)<br/><br/> bIID = String$(MAX_GUIDLEN, 0)<br/> Rc = StringFromGUID2(rClsId, VarPtr(bIID(0)), MAX_GUIDLEN)<br/> Rc = InStr(1, bIID, vbNullChar) - 1<br/> IID = Left$(UCase(bIID), Rc)<br/><br/> Select Case IID<br/> Case IID_IDispatch<br/> pdwEnabledOptions = IIf(m_fSafeForScripting, _<br/> INTERFACESAFE_FOR_UNTRUSTED_CALLER, 0)<br/> Exit Sub<br/> Case IID_IPersistStorage, IID_IPersistStream, _<br/> IID_IPersistPropertyBag<br/> pdwEnabledOptions = IIf(m_fSafeForInitializing, _<br/> INTERFACESAFE_FOR_UNTRUSTED_DATA, 0)<br/> Exit Sub<br/> Case Else<br/> Err.Raise E_NOINTERFACE 
		
          
              
          <br/>
        <br/>
          <br/> Exit Sub<br/> End Select<br/> End If<br/> End Sub<br/><br/> Private Sub IObjectSafety_SetInterfaceSafetyOptions(ByVal riid As _<br/> Long, ByVal dwOptionsSetMask As Long, ByVal dwEnabledOptions As Long)<br/> Dim Rc As Long<br/> Dim rClsId As udtGUID<br/> Dim IID As String<br/> Dim bIID<img src='/icons/41014kh.gif' /> As Byte<br/><br/> If (riid &lt;&gt; 0) Then<br/> CopyMemory rClsId, ByVal riid, Len(rClsId)<br/><br/> bIID = String$(MAX_GUIDLEN, 0)<br/> Rc = StringFromGUID2(rClsId, VarPtr(bIID(0)), MAX_GUIDLEN)<br/> Rc = InStr(1, bIID, vbNullChar) - 1<br/> IID = Left$(UCase(bIID), Rc)<br/><br/> Select Case IID<br/> Case IID_IDispatch<br/> If ((dwEnabledOptions And dwOptionsSetMask) &lt;&gt; _<br/> INTERFACESAFE_FOR_UNTRUSTED_CALLER) Then<br/> Err.Raise E_FAIL<br/> Exit Sub<br/> Else<br/> If Not m_fSafeForScripting Then<br/> Err.Raise E_FAIL<br/> End If<br/> Exit Sub<br/> End If<br/><br/> Case IID_IPersistStorage, IID_IPersistStream, _<br/> IID_IPersistPropertyBag<br/> If ((dwEnabledOptions And dwOptionsSetMask) &lt;&gt; _<br/> INTERFACESAFE_FOR_UNTRUSTED_DATA) Then<br/> Err.Raise E_FAIL<br/> Exit Sub<br/> Else<br/> If Not m_fSafeForInitializing Then<br/> Err.Raise E_FAIL<br/> End If 
		
          
              
          <br/>
        <br/>
          <br/> Exit Sub<br/> End If<br/><br/> Case Else<br/> Err.Raise E_NOINTERFACE<br/> Exit Sub<br/> End Select<br/> End If<br/> End Sub<br/>保存后<img src='/icons/41014dou.gif' />把工程编译成OCX文件<img src='/icons/41014dou2.gif' />现在Control控件已经实现了IObjectSafety 接口<img src='/icons/41014dou2.gif' />在.htm中加入这件Control控件试<img src='/icons/41014yi.gif' />试吧<img src='/icons/41014dou2.gif' /><br/><br/><br/><br />  <a href="/mypdf/15406.pdf" title="查看 vbactivex控件:如何在VB中实现ActiveX控件的IobjectSafety接口-vb教程 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>VB教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/VisualBasic/Article15406.html</guid>
		</item>
		<item>
			<title><![CDATA[vbactivex:在VB中使用未注册的ActiveX 代码]]></title>
			<link>http://CrazyCoder.cn/VisualBasic/Article15226.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
          \'大家<img src='/icons/20334yi.gif' />起来看代码<img src='/icons/20334de.gif' />使用思路方法<img src='/icons/20334dou.gif' />新手朋友好好<img src='/icons/20334de.gif' />琢磨下:<br/>\'Dim pDll As Long \'记录Dll<img src='/icons/20334dou.gif' />用来最后完美释放<br/>\'Dim Update As Update.Handle \'要例子化<img src='/icons/20334de.gif' />对象<br/>\'Set Update = LoadObjectByName(App.Path &amp; \"Update.dll\", \"Handle\", pDll) \' New Update.Handle<br/>\'If Update Is Nothing Then Exit Sub<br/>\'Update.Test \'&lt;--类中<img src='/icons/20334de.gif' />思路方法<br/>\'Set Update = Nothing \'&lt;-----这句不能少<img src='/icons/20334dou.gif' />否则会出现意外<img src='/icons/20334cuowu.gif' /><br/>\'UnLoadDll pDll \'&lt;----释放<br/><br/>
\'模块中:<br/>Option Explicit<br/>Private Declare Function LoadLibrary<img src='/icons/20334kh.gif' />Function LoadLibrary Lib \"kernel32\" Alias \"LoadLibraryW\" (ByVal lpLibFileName As Long) As Long<br/>Private Declare Function GetProcAddress<img src='/icons/20334kh.gif' />Function GetProcAddress Lib \"kernel32\" (ByVal hModule As Long, ByVal lpProcName As String) As Long<br/>Private Declare Function FreeLibrary<img src='/icons/20334kh.gif' />Function FreeLibrary Lib \"kernel32\" (ByVal hLibModule As Long) As Long<br/>Private Declare Function CallAsmCode<img src='/icons/20334kh.gif' />Function CallAsmCode Lib \"user32\" Alias \"CallWindowProcW\" (FirstAsmCode As Long, ByVal pA As Long, ByVal pB As Long, ByVal pC As Long, lpD As Long) As Long<br/>Private Declare Sub CopyMemory<img src='/icons/20334kh.gif' />Sub CopyMemory Lib \"kernel32\" Alias \"RtlMoveMemory\" (Destination As Any, Source As Any, ByVal Length As Long)<br/><br/>
Private AsmCode(94) As Long<br/><br/>
Public Function LoadObjectByName<img src='/icons/20334kh.gif' />Function LoadObjectByName(ByVal DllPath As String, ByVal ClsName As String, pDll As Long) As Object<br/> Dim pObj As Long, TLIAPP As Object, TLI As Object<br/> Dim CLSID As String, IID As String, IIDName As String<br/><br/>
 _disibledevent=> Set TLI = TLIAPP.TypeLibInfoFromFile(DllPath)<br/><br/>
 IIDName = \"_\" &amp; Trim(ClsName)<br/><br/>
 CLSID = TLI.GetTypeInfo(Trim(ClsName)).GUID<br/> IID = TLI.GetTypeInfo(Trim(IIDName)).GUID<br/><br/>
 Set LoadObjectByName = LoadObjectByID(DllPath, CLSID, IID, pDll)<br/> Set TLI = Nothing<br/>Err:<br/>End Function<br/><br/>
Public Function LoadObjectByID<img src='/icons/20334kh.gif' />Function LoadObjectByID(ByVal DllPath As String, ByVal CLSID As String, ByVal IID As String, pDll As Long) As Object<br/> Dim pObj As Long<br/> Call InitAsmCode<br/> pObj = CallAsmCode(AsmCode(20), StrPtr(DllPath), StrPtr(CLSID), StrPtr(IID), pDll)<br/> CopyMemory LoadObjectByID, pObj&amp;, 4&amp;<br/>End Function<br/><br/>
Public Function UnLoadDll<img src='/icons/20334kh.gif' />Function UnLoadDll(pDll As Long) As Long<br/> Call InitAsmCode<br/> UnLoadDll = CallAsmCode(AsmCode(79), pDll, 0, 0, 0)<br/>End Function<br/><br/>
[Page]Private Sub InitAsmCode<img src='/icons/20334kh.gif' />Sub InitAsmCode<img src='/icons/20334kh.gif' /><br/> If AsmCode(4) Then Exit Sub<br/> Dim pDll As Long<br/><br/>
 pDll = LoadLibrary(StrPtr(\"kernel32\"))<br/> AsmCode(0) = GetProcAddress(pDll, \"LoadLibraryW\")<br/> AsmCode(1) = GetProcAddress(pDll, \"GetProcAddress\")<br/> AsmCode(2) = GetProcAddress(pDll, \"FreeLibrary\")<br/> Call FreeLibrary(pDll)<br/><br/>
 AsmCode(4) = &amp;H476C6C44<br/> AsmCode(5) = &amp;H6C437465<br/> AsmCode(6) = &amp;H4F737361<br/> AsmCode(7) = &amp;H63656A62<br/> AsmCode(8) = &amp;H4C430074<br/> AsmCode(9) = &amp;H46444953<br/> AsmCode(10) = &amp;H536D6F72<br/> AsmCode(11) = &amp;H6E697274<br/> AsmCode(12) = &amp;H10067<br/> AsmCode(13) = &amp;H0&amp;<br/> AsmCode(14) = &amp;HC00000<br/> AsmCode(15) = &amp;H0&amp;<br/> AsmCode(16) = &amp;H6F4600<br/> AsmCode(17) = &amp;H65006C<br/> AsmCode(18) = &amp;H320033<br/> AsmCode(19) = &amp;H0&amp;<br/> AsmCode(20) = &amp;H83EC8B55 \'创建对象<img src='/icons/20334hanshu.gif' />入口<br/> AsmCode(21) = &amp;HE853D8C4<br/> AsmCode(22) = &amp;H0&amp;<br/> AsmCode(23) = &amp;H6CEB815B<br/> AsmCode(24) = &amp;H8D100010<br/> AsmCode(25) = &amp;H105293<br/> AsmCode(26) = &amp;H93FF5210<br/> AsmCode(27) = &amp;H10001010<br/> AsmCode(28) = &amp;H32938D50<br/> AsmCode(29) = &amp;H52100010<br/> AsmCode(30) = &amp;H1493FF50<br/> AsmCode(31) = &amp;H8D100010<br/> AsmCode(32) = &amp;H101C93<br/> AsmCode(33) = &amp;HFF028910<br/> AsmCode(34) = &amp;H101893<br/> AsmCode(35) = &amp;H875FF10<br/> AsmCode(36) = &amp;H101093FF<br/> AsmCode(37) = &amp;HC00B1000<br/> AsmCode(38) = &amp;H86840F 
		
          
              
          <br/>
        <br/>
          <br/> AsmCode(39) = &amp;H45890000<br/> AsmCode(40) = &amp;H20938DFC<br/> AsmCode(41) = &amp;H52100010<br/> AsmCode(42) = &amp;H1493FF50<br/> AsmCode(43) = &amp;HB100010<br/> AsmCode(44) = &amp;H506674C0[Page]<br/> AsmCode(45) = &amp;H52EC558D<br/> AsmCode(46) = &amp;HFF0C75FF<br/> AsmCode(47) = &amp;H101C93<br/> AsmCode(48) = &amp;H558D5810<br/> AsmCode(49) = &amp;H938D52D8<br/> AsmCode(50) = &amp;H10001042<br/> AsmCode(51) = &amp;HEC558D52<br/> AsmCode(52) = &amp;HBD0FF52<br/> AsmCode(53) = &amp;H8D3E75C0<br/> AsmCode(54) = &amp;HFF52DC55<br/> AsmCode(55) = &amp;H93FF1075<br/> AsmCode(56) = &amp;H1000101C<br/> AsmCode(57) = &amp;HD8558B50<br/> AsmCode(58) = &amp;H8D54128B<br/> AsmCode(59) = &amp;H6A50DC45<br/> AsmCode(60) = &amp;HD875FF00<br/> AsmCode(61) = &amp;HB0C52FF<br/> AsmCode(62) = &amp;H8B1575C0<br/> AsmCode(63) = &amp;H4D8BFC45<br/> AsmCode(64) = &amp;H59018914<br/> AsmCode(65) = &amp;H8BD18B51<br/> AsmCode(66) = &amp;H52FF5112<br/> AsmCode(67) = &amp;H14EB5804<br/> AsmCode(68) = &amp;HEB06EB58<br/> AsmCode(69) = &amp;HEB02EB0F<br/> AsmCode(70) = &amp;HFC75FF0B<br/> AsmCode(71) = &amp;H101893FF<br/> AsmCode(72) = &amp;HC0331000<br/> AsmCode(73) = &amp;H10C2C95B<br/> AsmCode(74) = &amp;H6C6C4400<br/> AsmCode(75) = &amp;H556E6143<br/> AsmCode(76) = &amp;H616F6C6E<br/> AsmCode(77) = &amp;H776F4E64<br/> AsmCode(78) = &amp;H0&amp;<br/> AsmCode(79) = &amp;H53EC8B55 \'尝试卸载DLL<img src='/icons/20334hanshu.gif' />入口<br/> AsmCode(80) = &amp;HE8&amp;<br/> AsmCode(81) = &amp;HEB815B00<br/> AsmCode(82) = &amp;H10001155<br/> AsmCode(83) = &amp;H1139938D<br/> AsmCode(84) = &amp;HFF521000<br/> AsmCode(85) = &amp;H93FF0875<br/> AsmCode(86) = &amp;H10001014<br/> AsmCode(87) = &amp;H1374C00B<br/> AsmCode(88) = &amp;HC00BD0FF<br/> AsmCode(89) = &amp;H75FF0E74<br/> AsmCode(90) = &amp;H1893FF08<br/> AsmCode(91) = &amp;H33100010<br/> AsmCode(92) = &amp;H4801EBC0<br/> AsmCode(93) = &amp;H10C2C95B<br/> AsmCode(94) = &amp;H90909000[Page]<br/>End Sub<br/><br/>  <a href="/mypdf/15226.pdf" title="查看 vbactivex:在VB中使用未注册的ActiveX 代码 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>VB教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/VisualBasic/Article15226.html</guid>
		</item>
		<item>
			<title><![CDATA[activexdll:用vb制作ActiveX Dll中，怎么让程序连接远程机器1888端口且等待接收信息]]></title>
			<link>http://CrazyCoder.cn/VisualBasic/Article15139.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
              <B>【学网教程】</B> 用vb制作ActiveX Dll中<img src='/icons/2678dou.gif' />如何让<img src='/icons/2678chengxu.gif' />连接远程机器1888端口<img src='/icons/2678dou.gif' />并且等待接收信息<br/><br/>在 asp中无法返回信息阿<img src='/icons/2678dou2.gif' /><br/><br/>这个没有问题<img src='/icons/2678dou2.gif' />可以连接<img src='/icons/2678dou2.gif' /><br/><br/>Winsock1.RemoteHost = \"61.144.176.36\"<br/>Winsock1.RemotePort = 3052<br/>Winsock1.Connect<br/><br/>下面<img src='/icons/2678de.gif' /><img src='/icons/2678dou2.gif' />就有问题了<img src='/icons/2678dou2.gif' /><br/><br/>Private Sub Winsock1_DataArrival(ByVal <img src='/icons/2678byte.gif' />sTotal As Long)<br/><br/>&nbsp;<br/><br/>这个<img src='/icons/2678hanshu.gif' />在asp中如何<img src='/icons/2678diaoyong.gif' />阿<img src='/icons/2678dou2.gif' /><br/><br/>或者有没有别<img src='/icons/2678de.gif' />办法阿<img src='/icons/2678dou2.gif' /><br/><br/>谢谢<img src='/icons/2678dou2.gif' /><br/><br/> <br/> <br/>  <a href="/mypdf/15139.pdf" title="查看 activexdll:用vb制作ActiveX Dll中，怎么让程序连接远程机器1888端口且等待接收信息 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>VB教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/VisualBasic/Article15139.html</guid>
		</item>
		<item>
			<title><![CDATA[vbactivex:VB COM基本的讲座之ActiveX EXEs]]></title>
			<link>http://CrazyCoder.cn/VisualBasic/Article15094.html</link>
			<description>
				<![CDATA[

			
            　　 到现在为止，本教程一直讨论基于ActiveX DLLs中的类的内容，但是没有一本教程不说明与DLL相似的ActiveX EXEs。 <BR><BR>　　 所以，想在这里实际编写一个ActiveX EXE工程。事实上，它和ActiveX DLL没有太大的区别，甚至没有区别。在启动Visual Basic后选择\"ActiveX EXE\"就可创建，然后像以前一样构造自己的类。 <BR><BR>　　 但这里不想再作更详细的讨论，因为ActiveX EXE和ActiveX DLL除了在运行时有一些微小区别外，其他都相同。 <BR><BR>　　 它们的区别首先表现在它们的\"进程空间\"的不同。所谓\"进程空间\"是用于运行、处理和存取的一块计算机内存。任何Windows程序，如Microsoft Word等，都有自己的\"进程空间\"，它很像程序的桌面那样。 <BR><BR>　　 当使用ActiveX DLLs工程运行时，DLL是在使用它的程序的进程空间中运行的，而ActiveX EXE是在进程空间外面工作的。但是，ActiveX EXE还有自己的\"桌面\"。这究竟如何理解呢？ <BR><BR>　　 假如，ActiveX DLL变得不稳定或意外受损时，使用它的应用程序常常出现蓝屏的死机现象，而在EXEs中却不会发生，因为它有自己的\"进程空间\"，即使被破坏，也仅仅是桌面受损，当然用户程序应该很好地去修复它。 <BR><BR>　　 其次，它们的区别还表现在装载的速度上。由于DLL是直接装载到已存在的进程空间，所以它的速度非常快。而EXEs由于还要分配自己的进程空间，所以速度上相对慢一点。 <BR><BR>　　 上述两点区别可以说是它们真正的区别。 <BR><BR>　　 总之，如果使用不同的Windows工具来实现相应的ActiveX组件，那么相应的工程类型就应该有所不同。例如，若使用MTS，则应创建DLL工程，若使用DCOM，则应创建EXE工程。当然，即使现在不理解这此缩写字母的含义，我们也不必担心。因为它们是针对高级用户的，并用于COM远程的工具组件。以后有机会再来给出相应的教程。 <BR><BR>　　 这里再来分析第二点的区别。 <BR><BR>　　 如果现在需要创建这样的一个程序，它不断地检测一个数据库是否有什么改变。那么我们想到的是在程序中使用一些\"timer\"(计时器)，每隔10分钟激发一次并检测该数据库。但问题来了，在该进程空间的其他所有代码都要被停止运行直至数据库检测完毕。 <BR><BR>　　 而ActiveX EXEs伟大之处，就在于它有自己的进程空间。所以在其中添加的计时器也只会工作在自己的进程空间中而不会影响其他使用它的程序。也就是说，对于前面的工程来说，若使用ActiveX EXE来检测数据库，则不会停止其他使用它的程序的运行；即使需要从其他程序中返回一个消息，也可以通过其他事件而获得。 <BR><BR>　　 需要说明的是，运行代码远离正规程序而通过事件与使用的应用程序会话的方法称为\"异步处理\"。通常当需要对e-mail或数据库作定期检查时，或当运行一个长的报表以及计算大的统计数据时，我们就需使用这种异步处理方式。 <BR><BR>　　 不怕你惊讶的话，我们可以将前面论述的内容总结成这样的一句话： <BR><BR>　　 \"ActiveX DLLs是在进程内运行，而ActiveX EXEs是在进程外运行\"。 <BR><BR>　　 好了，下一节将创建并测试一个自己的ActiveX EXE工程，并使用大家还不太熟悉的\"异步处理\"技巧。然后，提出一个称为\"实例\"的有意义的概念，最后指明怎样获得更多的COM知识使自己达到一个新的水平。              <a href="/mypdf/15094.pdf" title="查看 vbactivex:VB COM基本的讲座之ActiveX EXEs 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>VB教程</category>
			<pubDate>2008-09-25</pubDate>
			<guid>http://CrazyCoder.cn/VisualBasic/Article15094.html</guid>
		</item>
		<item>
			<title><![CDATA[vbactivex:VB COM基础讲座之测试ActiveX EXEs]]></title>
			<link>http://CrazyCoder.cn/VisualBasic/Article14920.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
          本节将创建并测试自己<img src='/icons/89555de.gif' />activex exe<img src='/icons/89555chengxu.gif' /><img src='/icons/89555dou2.gif' /> <br/><br/>　　 举例中将使用这样<img src='/icons/89555yi.gif' />个组件<img src='/icons/89555dou.gif' />它是<img src='/icons/89555yi.gif' />个有效<img src='/icons/89555de.gif' />文件探测器<img src='/icons/89555dou2.gif' />大约每隔60秒检测指定文件<img src='/icons/89555de.gif' />存在性<img src='/icons/89555dou2.gif' />如何该文件存在<img src='/icons/89555dou.gif' />该组件激发<img src='/icons/89555yi.gif' />个事件来<img src='/icons/89555diaoyong.gif' />应用<img src='/icons/89555chengxu.gif' /><img src='/icons/89555dou.gif' />如果不存在<img src='/icons/89555dou.gif' />则另作处理<img src='/icons/89555dou2.gif' /> <br/><br/>　　 当然<img src='/icons/89555dou.gif' />如果将所有代码写到activex dll工程<img src='/icons/89555dou.gif' />则运行时<img src='/icons/89555chengxu.gif' />代码将被挂起直到文件检测代码运行完毕为止<img src='/icons/89555dou2.gif' />由于activex exe工程拥有自己<img src='/icons/89555de.gif' />进程空间<img src='/icons/89555dou.gif' />代码运行时会自我协调、异步处理<img src='/icons/89555dou.gif' />从而不会使其他<img src='/icons/89555chengxu.gif' />代码停顿<img src='/icons/89555dou2.gif' /> <br/><br/>　　 下面就来创建: <br/><br/>　　 新建<img src='/icons/89555yi.gif' />个\"activex exe\"工程； <br/><br/>　　 工程名设为\"file\"； <br/><br/>　　 添加<img src='/icons/89555de.gif' />类名为\"filecheck\"； <br/><br/>　　 下<img src='/icons/89555yi.gif' />步<img src='/icons/89555dou.gif' />我们需要构造<img src='/icons/89555yi.gif' />些用于每隔1分钟左右检测文件<img src='/icons/89555de.gif' />代码<img src='/icons/89555dou2.gif' />这里将在activex exe工程插入<img src='/icons/89555yi.gif' />个带有计时器<img src='/icons/89555de.gif' />表单<img src='/icons/89555dou2.gif' />但该表单不会被显示<img src='/icons/89555dou.gif' /><img src='/icons/89555yinwei.gif' />我们只是使用上面<img src='/icons/89555de.gif' />计时器Control控件每隔1分钟左右来检测文件<img src='/icons/89555dou.gif' />如果相应<img src='/icons/89555de.gif' />文件被检测到<img src='/icons/89555dou.gif' />则激发<img src='/icons/89555yi.gif' />个事件<img src='/icons/89555dou2.gif' /> <br/><br/>　　 选择\"project\"-&gt;\"add form\"； <br/><br/>　　 在表单form1中添加<img src='/icons/89555yi.gif' />个计时器； <br/><br/>　　 在表单代码中添加下列变量<img src='/icons/89555de.gif' />声明: <br/><br/>public filename as <img src='/icons/89555string.gif' /> <br/>　　 该变量用于保存被监视<img src='/icons/89555de.gif' />文件名<img src='/icons/89555dou2.gif' /> <br/><br/>　　 在表单代码中添加下列事件<img src='/icons/89555de.gif' />声明: <br/><br/>public event filefound<img src='/icons/89555kh.gif' /> <br/>　　 该事件只有当前面<img src='/icons/89555de.gif' />文件发现后才被激发<img src='/icons/89555dou2.gif' /> <br/><br/>　　 在timer1代码中添加下列语句: <br/><br/>　　private sub timer1_timer<img src='/icons/89555kh.gif' /> <br/><br/>　　　 <img src='/icons/89555if.gif' /> dir(filename) &lt;&gt; \"\" then <br/><br/>　　　　 raiseevent filefound <br/><br/>　　　　 timer1.<img src='/icons/89555int.gif' />erval = 0 <br/><br/>　　　 end <img src='/icons/89555if.gif' /> <br/><br/>　　 end sub <br/>　　 代码中<img src='/icons/89555dou.gif' />首先简单地检测文件<img src='/icons/89555dou.gif' />若存在则激发filefound事件<img src='/icons/89555dou.gif' />然后将timer1<img src='/icons/89555de.gif' />时间间隔设为0<img src='/icons/89555dou.gif' />停止以后<img src='/icons/89555de.gif' />检测<img src='/icons/89555dou2.gif' /> <br/><br/>　　 打开filecheck类； <br/><br/>　　 在通用声明处添加下列对象<img src='/icons/89555de.gif' />声明: <br/><br/>dim withevents objfilecheck as form1 <br/>　　 这就是form1<img src='/icons/89555de.gif' />代码<img src='/icons/89555dou.gif' />它通知visual basic上述定义<img src='/icons/89555de.gif' />对象是用来保存表单<img src='/icons/89555de.gif' /><img src='/icons/89555dou2.gif' />关键词withevents表示该类可以接收传送来<img src='/icons/89555de.gif' />事件<img src='/icons/89555dou.gif' />如前面<img src='/icons/89555de.gif' />filefound等<img src='/icons/89555dou2.gif' /> <br/><br/>　　 本节将创建并测试自己<img src='/icons/89555de.gif' />activex exe<img src='/icons/89555chengxu.gif' /><img src='/icons/89555dou2.gif' /> <br/><br/>　　 举例中将使用这样<img src='/icons/89555yi.gif' />个组件<img src='/icons/89555dou.gif' />它是<img src='/icons/89555yi.gif' />个有效<img src='/icons/89555de.gif' />文件探测器<img src='/icons/89555dou2.gif' />大约每隔60秒检测指定文件<img src='/icons/89555de.gif' />存在性<img src='/icons/89555dou2.gif' />如何该文件存在<img src='/icons/89555dou.gif' />该组件激发<img src='/icons/89555yi.gif' />个事件来<img src='/icons/89555diaoyong.gif' />应用<img src='/icons/89555chengxu.gif' /><img src='/icons/89555dou.gif' />如果不存在<img src='/icons/89555dou.gif' />则另作处理<img src='/icons/89555dou2.gif' /> <br/><br/>　　 当然<img src='/icons/89555dou.gif' />如果将所有代码写到activex dll工程<img src='/icons/89555dou.gif' />则运行时<img src='/icons/89555chengxu.gif' />代码将被挂起直到文件检测代码运行完毕为止<img src='/icons/89555dou2.gif' />由于activex exe工程拥有自己<img src='/icons/89555de.gif' />进程空间<img src='/icons/89555dou.gif' />代码运行时会自我协调、异步处理<img src='/icons/89555dou.gif' />从而不会使其他<img src='/icons/89555chengxu.gif' />代码停顿<img src='/icons/89555dou2.gif' /> <br/><br/>　　 下面就来创建: <br/><br/>　　 新建<img src='/icons/89555yi.gif' />个\"activex exe\"工程； <br/><br/>　　 工程名设为\"file\"； <br/><br/>　　 添加<img src='/icons/89555de.gif' />类名为\"filecheck\"； <br/><br/>　　 下<img src='/icons/89555yi.gif' />步<img src='/icons/89555dou.gif' />我们需要构造<img src='/icons/89555yi.gif' />些用于每隔1分钟左右检测文件<img src='/icons/89555de.gif' />代码<img src='/icons/89555dou2.gif' />这里将在activex exe工程插入<img src='/icons/89555yi.gif' />个带有计时器<img src='/icons/89555de.gif' />表单<img src='/icons/89555dou2.gif' />但该表单不会被显示<img src='/icons/89555dou.gif' /><img src='/icons/89555yinwei.gif' />我们只是使用上面<img src='/icons/89555de.gif' />计时器Control控件每隔1分钟左右来检测文件<img src='/icons/89555dou.gif' />如果相应<img src='/icons/89555de.gif' />文件被检测到<img src='/icons/89555dou.gif' />则激发<img src='/icons/89555yi.gif' />个事件<img src='/icons/89555dou2.gif' /> <br/><br/>　　 选择\"project\"-&gt;\"add form\"； <br/><br/>　　 在表单form1中添加<img src='/icons/89555yi.gif' />个计时器； <br/><br/>　　 在表单代码中添加下列变量<img src='/icons/89555de.gif' />声明: <br/><br/>public filename as <img src='/icons/89555string.gif' /> <br/>　　 该变量用于保存被监视<img src='/icons/89555de.gif' />文件名<img src='/icons/89555dou2.gif' /> <br/><br/>　　 在表单代码中添加下列事件<img src='/icons/89555de.gif' />声明: <br/><br/>　　 public event filefound<img src='/icons/89555kh.gif' /> <br/><br/>　　 该事件只有当前面<img src='/icons/89555de.gif' />文件发现后才被激发<img src='/icons/89555dou2.gif' /> <br/><br/>　　 在timer1代码中添加下列语句: <br/><br/>　　private sub timer1_timer<img src='/icons/89555kh.gif' /> <br/><br/>　　　 <img src='/icons/89555if.gif' /> dir(filename) &lt;&gt; \"\" then <br/><br/>　　　　 raiseevent filefound <br/><br/>　　　　 timer1.<img src='/icons/89555int.gif' />erval = 0 <br/><br/>　　　 end <img src='/icons/89555if.gif' /> <br/><br/>　　 end sub <br/>　　 代码中<img src='/icons/89555dou.gif' />首先简单地检测文件<img src='/icons/89555dou.gif' />若存在则激发filefound事件<img src='/icons/89555dou.gif' />然后将timer1<img src='/icons/89555de.gif' />时间间隔设为0<img src='/icons/89555dou.gif' />停止以后<img src='/icons/89555de.gif' />检测<img src='/icons/89555dou2.gif' /> <br/><br/>　　 打开filecheck类； <br/><br/>　　 在通用声明处添加下列对象<img src='/icons/89555de.gif' />声明: <br/><br/>dim withevents objfilecheck as form1 <br/>　　 这就是form1<img src='/icons/89555de.gif' />代码<img src='/icons/89555dou.gif' />它通知visual basic上述定义<img src='/icons/89555de.gif' />对象是用来保存表单<img src='/icons/89555de.gif' /><img src='/icons/89555dou2.gif' />关键词withevents表示该类可以接收传送来<img src='/icons/89555de.gif' />事件<img src='/icons/89555dou.gif' />如前面<img src='/icons/89555de.gif' />filefound等<img src='/icons/89555dou2.gif' /> <br/>从\"object\"下拉列表框中选择\"<img src='/icons/89555class.gif' />\"； <br/><br/>　　 再从\"procedure\"下拉列表框中选择\"initialize\"； <br/><br/>　　 在<img src='/icons/89555class.gif' />_initialize事件中添加下列代码: <br/><br/>　　private sub <img src='/icons/89555class.gif' />_initialize<img src='/icons/89555kh.gif' /> <br/><br/>　　　 <img src='/icons/89555set.gif' /> objfilecheck = <img src='/icons/89555new.gif' /> form1 <br/><br/>　　 end sub <br/>　　 该代码简单地使objfilecheck等于form1<img src='/icons/89555de.gif' />新<img src='/icons/89555de.gif' /><img src='/icons/89555yi.gif' />个例子<img src='/icons/89555dou2.gif' />的后<img src='/icons/89555dou.gif' />我们将使用在form1中添加<img src='/icons/89555de.gif' />功能<img src='/icons/89555dou2.gif' />接下来<img src='/icons/89555dou.gif' />我们编写<img src='/icons/89555yi.gif' />个子过程用来监视<img src='/icons/89555yi.gif' />个文件<img src='/icons/89555dou2.gif' /> <br/><br/>　　 在filecheck中添加下列代码: <br/><br/>　　public sub monitorfile(filename as <img src='/icons/89555string.gif' />) <br/><br/>　　　 objfilecheck.filename = filename <br/><br/>　　　 objfilecheck.timer1.<img src='/icons/89555int.gif' />erval = 60000 <br/><br/>　　 end sub <br/>　　 当我们<img src='/icons/89555diaoyong.gif' />此过程时<img src='/icons/89555dou.gif' />需要给出文件名参数<img src='/icons/89555dou2.gif' />这时<img src='/icons/89555dou.gif' />表单<img src='/icons/89555de.gif' />filename变量保存该文件名<img src='/icons/89555dou.gif' />然后将计时器<img src='/icons/89555de.gif' />时间间隔属性设置为60,000毫秒并激活该计时器<img src='/icons/89555dou2.gif' /> <br/><br/>　　 至此<img src='/icons/89555dou.gif' />我们构造了用于监视文件<img src='/icons/89555de.gif' />所有代码<img src='/icons/89555dou2.gif' />但是当文件检测到时<img src='/icons/89555dou.gif' />我们需要通过激发filefound事件通知<img src='/icons/89555chengxu.gif' />正在使用activex exe<img src='/icons/89555dou2.gif' /> <br/><br/>　　 在通用声明部分添加下列事件声明: <br/><br/>public event filefound(filename as <img src='/icons/89555string.gif' />) <br/>　　 该代码只是简单地定义<img src='/icons/89555yi.gif' />个filefound事件<img src='/icons/89555dou.gif' />下<img src='/icons/89555yi.gif' />步该事件<img src='/icons/89555de.gif' />相应代码<img src='/icons/89555dou2.gif' /> <br/><br/>　　 从\"object\"下拉列表框中选择\"objfilecheck\"； <br/><br/>　　 再从\"procedure\"下拉列表框中选择\"filefound\"； <br/><br/>　　private sub objfilecheck_filefound ( ) <br/><br/>　　　 raiseevent filefound ( objfilecheck.filename) <br/><br/>　　 end sub <br/>　　 显然<img src='/icons/89555dou.gif' />当文件检测到时<img src='/icons/89555dou.gif' />这里<img src='/icons/89555de.gif' />filefound事件就被激发<img src='/icons/89555dou2.gif' />但我们还需要在使用exe<img src='/icons/89555chengxu.gif' />中添加这个事件<img src='/icons/89555de.gif' />添加代码<img src='/icons/89555dou2.gif' /> <br/><br/>　　 在objfilecheck_filefound事件中添加下列代码: <br/><br/>　　 raiseevent filefound(objfilecheck.filename) <br/> 
		
          
              
          <br/>
        <br/>
          <br/>　　 这就是我们<img src='/icons/89555de.gif' />全部代码<img src='/icons/89555dou2.gif' /> <br/><br/>　　 当<img src='/icons/89555chengxu.gif' />员使用该类时<img src='/icons/89555dou.gif' />都可以文件名为参数<img src='/icons/89555diaoyong.gif' />monitorfile思路方法<img src='/icons/89555dou.gif' />然后表单中<img src='/icons/89555de.gif' />计时器被引发<img src='/icons/89555dou.gif' />每隔60秒钟检测<img src='/icons/89555yi.gif' />下文件<img src='/icons/89555dou.gif' />若该文件被查找到<img src='/icons/89555dou.gif' />则激发filecheck类中<img src='/icons/89555de.gif' />事件<img src='/icons/89555dou.gif' />该事件又激发相关<img src='/icons/89555de.gif' />应用<img src='/icons/89555chengxu.gif' />中<img src='/icons/89555de.gif' />另<img src='/icons/89555yi.gif' />个事件<img src='/icons/89555dou.gif' />用来通知<img src='/icons/89555chengxu.gif' />员<img src='/icons/89555dou.gif' />该文件已被找到<img src='/icons/89555dou2.gif' /> <br/><br/>　　 明白了吗？让我们试试看吧！  <a href="/mypdf/14920.pdf" title="查看 vbactivex:VB COM基础讲座之测试ActiveX EXEs 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>VB教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/VisualBasic/Article14920.html</guid>
		</item>
		<item>
			<title><![CDATA[vbactivex:VB COM基础讲座之ActiveX EXEs]]></title>
			<link>http://CrazyCoder.cn/VisualBasic/Article14919.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
          到现在为止<img src='/icons/51535dou.gif' />本教程<img src='/icons/51535yi.gif' />直讨论基于activex dlls中<img src='/icons/51535de.gif' />类<img src='/icons/51535de.gif' />内容<img src='/icons/51535dou.gif' />但是没有<img src='/icons/51535yi.gif' />本教程不介绍说明和dll相似<img src='/icons/51535de.gif' />activex exes<img src='/icons/51535dou2.gif' /> <br/><br/>　　 所以<img src='/icons/51535dou.gif' />想在这里实际编写<img src='/icons/51535yi.gif' />个activex exe工程<img src='/icons/51535dou2.gif' />事实上<img src='/icons/51535dou.gif' />它和activex dll没有太大<img src='/icons/51535de.gif' />区别<img src='/icons/51535dou.gif' />甚至没有区别<img src='/icons/51535dou2.gif' />在启动visual basic后选择\"activex exe\"就可创建<img src='/icons/51535dou.gif' />然后像以前<img src='/icons/51535yi.gif' />样构造自己<img src='/icons/51535de.gif' />类<img src='/icons/51535dou2.gif' /> <br/><br/>　　 但这里不想再作更详细<img src='/icons/51535de.gif' />讨论<img src='/icons/51535dou.gif' /><img src='/icons/51535yinwei.gif' />activex exe和activex dll除了在运行时有<img src='/icons/51535yi.gif' />些微小区别外<img src='/icons/51535dou.gif' />其他都相同<img src='/icons/51535dou2.gif' /> <br/><br/>　　 它们<img src='/icons/51535de.gif' />区别首先表现在它们<img src='/icons/51535de.gif' />\"进程空间\"<img src='/icons/51535de.gif' />区别<img src='/icons/51535dou2.gif' />所谓\"进程空间\"是用于运行、处理和存取<img src='/icons/51535de.gif' /><img src='/icons/51535yi.gif' />块计算机内存<img src='/icons/51535dou2.gif' />任何windows<img src='/icons/51535chengxu.gif' /><img src='/icons/51535dou.gif' />如microsoft word等<img src='/icons/51535dou.gif' />都有自己<img src='/icons/51535de.gif' />\"进程空间\"<img src='/icons/51535dou.gif' />它很像<img src='/icons/51535chengxu.gif' /><img src='/icons/51535de.gif' />桌面那样<img src='/icons/51535dou2.gif' /> <br/><br/>　　 当使用activex dlls工程运行时<img src='/icons/51535dou.gif' />dll是在使用它<img src='/icons/51535de.gif' /><img src='/icons/51535chengxu.gif' /><img src='/icons/51535de.gif' />进程空间中运行<img src='/icons/51535de.gif' /><img src='/icons/51535dou.gif' />而activex exe是在进程空间外面工作<img src='/icons/51535de.gif' /><img src='/icons/51535dou2.gif' />但是<img src='/icons/51535dou.gif' />activex exe还有自己<img src='/icons/51535de.gif' />\"桌面\"<img src='/icons/51535dou2.gif' />这究竟如何理解呢？ <br/><br/>　　 假如<img src='/icons/51535dou.gif' />activex dll变得不稳定或意外受损时<img src='/icons/51535dou.gif' />使用它<img src='/icons/51535de.gif' />应用<img src='/icons/51535chengxu.gif' />常常出现蓝屏<img src='/icons/51535de.gif' />死机现象<img src='/icons/51535dou.gif' />而在exes中却不会发生<img src='/icons/51535dou.gif' /><img src='/icons/51535yinwei.gif' />它有自己<img src='/icons/51535de.gif' />\"进程空间\"<img src='/icons/51535dou.gif' />即使被破坏<img src='/icons/51535dou.gif' />也仅仅是桌面受损<img src='/icons/51535dou.gif' />当然用户<img src='/icons/51535chengxu.gif' />应该很好地去修复它<img src='/icons/51535dou2.gif' /> <br/><br/>　　 其次<img src='/icons/51535dou.gif' />它们<img src='/icons/51535de.gif' />区别还表现在装载<img src='/icons/51535de.gif' />速度上<img src='/icons/51535dou2.gif' />由于dll是直接装载到已存在<img src='/icons/51535de.gif' />进程空间<img src='/icons/51535dou.gif' />所以它<img src='/icons/51535de.gif' />速度非常快<img src='/icons/51535dou2.gif' />而exes由于还要分配自己<img src='/icons/51535de.gif' />进程空间<img src='/icons/51535dou.gif' />所以速度上相对慢<img src='/icons/51535yi.gif' />点<img src='/icons/51535dou2.gif' /> <br/><br/>　　 上述两点区别可以说是它们真正<img src='/icons/51535de.gif' />区别<img src='/icons/51535dou2.gif' /> <br/><br/>　　 总的<img src='/icons/51535dou.gif' />如果使用区别<img src='/icons/51535de.gif' />windows工具来实现相应<img src='/icons/51535de.gif' />activex组件<img src='/icons/51535dou.gif' />那么相应<img src='/icons/51535de.gif' />工程类型就应该有所区别<img src='/icons/51535dou2.gif' />例如<img src='/icons/51535dou.gif' />若使用mts<img src='/icons/51535dou.gif' />则应创建dll工程<img src='/icons/51535dou.gif' />若使用dcom<img src='/icons/51535dou.gif' />则应创建exe工程<img src='/icons/51535dou2.gif' />当然<img src='/icons/51535dou.gif' />即使现在不理解这此缩写字母<img src='/icons/51535de.gif' />含义<img src='/icons/51535dou.gif' />我们也不必担心<img src='/icons/51535dou2.gif' /><img src='/icons/51535yinwei.gif' />它们是针对高级用户<img src='/icons/51535de.gif' /><img src='/icons/51535dou.gif' />并用于com远程<img src='/icons/51535de.gif' />工具组件<img src='/icons/51535dou2.gif' />以后有机会再来给出相应<img src='/icons/51535de.gif' />教程<img src='/icons/51535dou2.gif' /> <br/><br/>　　 这里再来分析第 2点<img src='/icons/51535de.gif' />区别<img src='/icons/51535dou2.gif' /> <br/><br/>　　 如果现在需要创建这样<img src='/icons/51535de.gif' /><img src='/icons/51535yi.gif' />个<img src='/icons/51535chengxu.gif' /><img src='/icons/51535dou.gif' />它不断地检测<img src='/icons/51535yi.gif' />个数据库是否有什么改变<img src='/icons/51535dou2.gif' />那么我们想到<img src='/icons/51535de.gif' />是在<img src='/icons/51535chengxu.gif' />中使用<img src='/icons/51535yi.gif' />些\"timer\"(计时器)<img src='/icons/51535dou.gif' />每隔10分钟激发<img src='/icons/51535yi.gif' />次并检测该数据库<img src='/icons/51535dou2.gif' />但问题来了<img src='/icons/51535dou.gif' />在该进程空间<img src='/icons/51535de.gif' />其他所有代码都要被停止运行直至数据库检测完毕<img src='/icons/51535dou2.gif' /> <br/><br/>　　 而activex exes伟大的处<img src='/icons/51535dou.gif' />就在于它有自己<img src='/icons/51535de.gif' />进程空间<img src='/icons/51535dou2.gif' />所以在其中添加<img src='/icons/51535de.gif' />计时器也只会工作在自己<img src='/icons/51535de.gif' />进程空间中而不会影响其他使用它<img src='/icons/51535de.gif' /><img src='/icons/51535chengxu.gif' /><img src='/icons/51535dou2.gif' />也就是说<img src='/icons/51535dou.gif' />对于前面<img src='/icons/51535de.gif' />工程来说<img src='/icons/51535dou.gif' />若使用activex exe来检测数据库<img src='/icons/51535dou.gif' />则不会停止其他使用它<img src='/icons/51535de.gif' /><img src='/icons/51535chengxu.gif' /><img src='/icons/51535de.gif' />运行；即使需要从其他<img src='/icons/51535chengxu.gif' />中返回<img src='/icons/51535yi.gif' />个消息<img src='/icons/51535dou.gif' />也可以通过其他事件而获得<img src='/icons/51535dou2.gif' /> <br/><br/>　　 需要介绍说明<img src='/icons/51535de.gif' />是<img src='/icons/51535dou.gif' />运行代码远离正规<img src='/icons/51535chengxu.gif' />而通过事件和使用<img src='/icons/51535de.gif' />应用<img src='/icons/51535chengxu.gif' />会话<img src='/icons/51535de.gif' />思路方法称为\"异步处理\"<img src='/icons/51535dou2.gif' />通常当需要对e-mail或数据库作定期检查时<img src='/icons/51535dou.gif' />或当运行<img src='/icons/51535yi.gif' />个长<img src='/icons/51535de.gif' />报表以及计算大<img src='/icons/51535de.gif' />统计数据时<img src='/icons/51535dou.gif' />我们就需使用这种异步处理方式<img src='/icons/51535dou2.gif' /> <br/><br/>　　 不怕你惊讶<img src='/icons/51535de.gif' />话<img src='/icons/51535dou.gif' />我们可以将前面论述<img src='/icons/51535de.gif' />内容整理总结成这样<img src='/icons/51535de.gif' /><img src='/icons/51535yi.gif' />句话: <br/><br/>　　 \"activex dlls是在进程内运行<img src='/icons/51535dou.gif' />而activex exes是在进程外运行\"<img src='/icons/51535dou2.gif' /> <br/><br/>　　 好了<img src='/icons/51535dou.gif' />下<img src='/icons/51535yi.gif' />节将创建并测试<img src='/icons/51535yi.gif' />个自己<img src='/icons/51535de.gif' />activex exe工程<img src='/icons/51535dou.gif' />并使用大家还不太熟悉<img src='/icons/51535de.gif' />\"异步处理\"窍门技巧<img src='/icons/51535dou2.gif' />然后<img src='/icons/51535dou.gif' />提出<img src='/icons/51535yi.gif' />个称为\"例子\"<img src='/icons/51535de.gif' />有意义<img src='/icons/51535de.gif' />概念<img src='/icons/51535dou.gif' />最后指明怎样获得更多<img src='/icons/51535de.gif' />com知识使自己达到<img src='/icons/51535yi.gif' />个新<img src='/icons/51535de.gif' />水平<img src='/icons/51535dou2.gif' />  <a href="/mypdf/14919.pdf" title="查看 vbactivex:VB COM基础讲座之ActiveX EXEs 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>VB教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/VisualBasic/Article14919.html</guid>
		</item>
		<item>
			<title><![CDATA[vbactivex控件:Delphi使用VB编写的ActiveX控件全攻略]]></title>
			<link>http://CrazyCoder.cn/Delphi/Article12095.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
                <br/>      前言<br/>在最近几周<img src='/icons/13192de.gif' />工作里<img src='/icons/13192dou.gif' />始终被<img src='/icons/13192yi.gif' />个头疼<img src='/icons/13192de.gif' />问题所困扰<img src='/icons/13192dou.gif' />那就是VB6编写<img src='/icons/13192de.gif' />ActiveXControl控件在Delphi环境下存在着诸多稀奇古怪<img src='/icons/13192de.gif' />问题<img src='/icons/13192dou.gif' />几经周折<img src='/icons/13192dou.gif' />终于在搜索了几乎全部<img src='/icons/13192de.gif' />论坛、资料后<img src='/icons/13192dou.gif' />找到了针对区别Delphi版本发生<img src='/icons/13192de.gif' />问题<img src='/icons/13192de.gif' />解决办法<img src='/icons/13192dou2.gif' /><br/><br/><br/><br/>Delphi5莫名其妙<img src='/icons/13192de.gif' />致命异常的<img src='/icons/13192yi.gif' /><br/>首先<img src='/icons/13192dou.gif' />我们来看看VB写<img src='/icons/13192de.gif' />ActiveXControl控件在Delphi5下面<img src='/icons/13192de.gif' />奇怪表现<img src='/icons/13192dou2.gif' /><br/><br/>例如:我们用VB编写了<img src='/icons/13192yi.gif' />个Control控件UserTest(为简单起见<img src='/icons/13192dou.gif' />我们只导出<img src='/icons/13192yi.gif' />个类即用户Control控件)<img src='/icons/13192dou.gif' /><img src='/icons/13192yi.gif' />个属性TestName,<img src='/icons/13192yi.gif' />个思路方法TestMethod<img src='/icons/13192dou2.gif' />然后将其编译成<img src='/icons/13192yi.gif' />个ActiveXControl控件<img src='/icons/13192dou.gif' />注册并导入Delphi5<img src='/icons/13192de.gif' />开发环境(以上步骤如有未清楚的处<img src='/icons/13192dou.gif' />请查阅各类参考资料<img src='/icons/13192dou.gif' />肯定有标准答案)<img src='/icons/13192dou.gif' />到目前为止<img src='/icons/13192dou.gif' />看来<img src='/icons/13192yi.gif' />切正常<img src='/icons/13192dou2.gif' /><br/><br/>然后<img src='/icons/13192dou.gif' />我们习惯<img src='/icons/13192de.gif' />把Control控件拖放到窗体上<img src='/icons/13192dou.gif' />调整大小<img src='/icons/13192dou.gif' />在属性窗口中为属性赋值<img src='/icons/13192dou.gif' />或者在代码中也是<img src='/icons/13192yi.gif' />样<img src='/icons/13192dou.gif' />非常正常<img src='/icons/13192dou.gif' />好用<img src='/icons/13192de.gif' />很<img src='/icons/13192dou2.gif' />但是<img src='/icons/13192dou.gif' />下面问题来了<img src='/icons/13192dou.gif' />如果您兴致勃勃<img src='/icons/13192de.gif' />去<img src='/icons/13192diaoyong.gif' />了那个TestMethod<img src='/icons/13192dou.gif' />那么您将得到<img src='/icons/13192yi.gif' />个古怪<img src='/icons/13192de.gif' />异常“OleError800a01a9”<img src='/icons/13192dou.gif' />然后<img src='/icons/13192chengxu.gif' />退出<img src='/icons/13192dou.gif' />而且非常不幸<img src='/icons/13192de.gif' />是<img src='/icons/13192dou.gif' />您将无法跟踪到这个异常<img src='/icons/13192dou.gif' />在Delphi中或是VB中都是<img src='/icons/13192dou.gif' />当然如果您对汇编很在行<img src='/icons/13192de.gif' />话<img src='/icons/13192dou.gif' />您可以跟着Delphi<img src='/icons/13192de.gif' />调试窗口<img src='/icons/13192yi.gif' />步<img src='/icons/13192yi.gif' />步往下……<br/><br/>当我第<img src='/icons/13192yi.gif' />次碰到这个问题<img src='/icons/13192de.gif' />时候<img src='/icons/13192dou.gif' />我几乎是愤怒<img src='/icons/13192de.gif' /><img src='/icons/13192dou.gif' /><img src='/icons/13192yinwei.gif' />无论是MicroSoft或是Borland<img src='/icons/13192dou.gif' />对该<img src='/icons/13192cuowu.gif' />都没有任何解释<img src='/icons/13192dou.gif' />也没有任何可以查找<img src='/icons/13192de.gif' />资料<img src='/icons/13192dou2.gif' />我只好跑到常去<img src='/icons/13192de.gif' />几个论坛<img src='/icons/13192dou.gif' />当然最主要<img src='/icons/13192de.gif' />还是CSDN<img src='/icons/13192dou.gif' />在VB版和Delphi版中 4处搜索类似<img src='/icons/13192de.gif' />问题<img src='/icons/13192dou.gif' />然后非常遗憾<img src='/icons/13192de.gif' />是<img src='/icons/13192dou.gif' />只有类似<img src='/icons/13192de.gif' />问题<img src='/icons/13192dou.gif' />而没有答案<img src='/icons/13192dou.gif' /><img src='/icons/13192yi.gif' />个大客户就用<img src='/icons/13192de.gif' />这个开发工具<img src='/icons/13192dou.gif' />我在测试了几乎所有Windows上<img src='/icons/13192de.gif' />开发工具和开发环境(包括桌面和WEB)后<img src='/icons/13192dou.gif' />惟独将Delphi忘记了<img src='/icons/13192dou2.gif' /><br/><br/>剩下<img src='/icons/13192de.gif' />两天里<img src='/icons/13192dou.gif' />我几乎是满世界乱跑<img src='/icons/13192dou.gif' />给所有<img src='/icons/13192de.gif' />朋友打电话<img src='/icons/13192dou.gif' />询问Delphi方面<img src='/icons/13192de.gif' />高手是否知道这个情况<img src='/icons/13192dou.gif' />最后<img src='/icons/13192dou.gif' />我从Google上搜到了<img src='/icons/13192yi.gif' />个链接<img src='/icons/13192dou.gif' />可惜<img src='/icons/13192de.gif' />是现在我忘记了那个链接<img src='/icons/13192de.gif' />具体位置<img src='/icons/13192dou.gif' />但是我得到了<img src='/icons/13192yi.gif' />个近乎Magic<img src='/icons/13192de.gif' />思路方法(发现者是这么称呼它<img src='/icons/13192de.gif' />):<br/><br/><br/><br/><img src='/icons/13192yi.gif' />个手工修改Delphi导入VBActiveXControl控件后产生<img src='/icons/13192de.gif' />代理类型库XXX_TLB.PAS(这里XXX指<img src='/icons/13192de.gif' />是Control控件<img src='/icons/13192de.gif' />类名)文件<img src='/icons/13192de.gif' />思路方法可以解决这<img src='/icons/13192yi.gif' />问题<img src='/icons/13192dou2.gif' />举例介绍说明:<br/><br/><br/><br/>有<img src='/icons/13192yi.gif' />个VB写<img src='/icons/13192de.gif' />Control控件UserControl1<img src='/icons/13192dou.gif' />在Delphi中导入后产生两个文件<img src='/icons/13192dou.gif' />其中<img src='/icons/13192yi.gif' />个UserControl1_TLB.PAS就是我们所要修改<img src='/icons/13192de.gif' />文件<img src='/icons/13192dou2.gif' /><br/><br/>在文件中查找类似<br/><br/><br/><br/>F<img src='/icons/13192int.gif' />F:_UserControl1;<br/><br/>FunctionGetControlInterface:_UserControl1;<br/><br/><br/><br/>和<br/><br/><br/><br/>propertyControlInterface:_UserControl1readGetControlInterface;<br/><br/><br/><br/>GetControlInterface;<br/><br/><br/><br/>以及<br/><br/><br/><br/>procedureTUserControl1.CreateControl;<br/><br/>procedureDoCreate;<br/><br/>begin<br/><br/>Finf:=IUnknown(OleObject)as_UserControl1;<br/><br/>End;<br/><br/>Begin<br/><br/>IfFinf=nilthenDoCreate;<br/><br/>End;<br/><br/><br/><br/>FunctionTUserControl1.GetControl1Interface:_UserControl1;<br/><br/><br/><br/>Begin<br/><br/>CreateControl;<br/><br/>Result:=Finfl;<br/><br/>End;<br/><br/><br/><br/>请注意:这里红色标出<img src='/icons/13192de.gif' />_UserControl1要全部换成_UserControl1Disp<img src='/icons/13192dou.gif' />如果编译不成功<img src='/icons/13192de.gif' />话<img src='/icons/13192dou.gif' />请将编译警告中报出<img src='/icons/13192de.gif' />_UserControl1全部换成_UserControl1Disp<img src='/icons/13192dou.gif' />编译即可<img src='/icons/13192dou.gif' />这样在<img src='/icons/13192diaoyong.gif' />Control控件<img src='/icons/13192de.gif' />思路方法时便不会出现上述<img src='/icons/13192de.gif' />致命<img src='/icons/13192cuowu.gif' /><img src='/icons/13192dou2.gif' /><br/><br/><br/><br/>感谢这个伟大<img src='/icons/13192de.gif' />发现<img src='/icons/13192dou.gif' />我只能这么形容它<img src='/icons/13192dou.gif' />否则可能到现在我还要在这个圈子里套不出来<img src='/icons/13192dou.gif' />或者就是使用另外<img src='/icons/13192de.gif' />工具重新开发这个Control控件(我难以想象这个工作量会有多大<img src='/icons/13192dou.gif' />又或者它可能还会存在其他<img src='/icons/13192de.gif' />兼容性问题)<img src='/icons/13192dou2.gif' /><br/><br/><br/><br/><br/><br/>Delphi5莫名其妙<img src='/icons/13192de.gif' />致命异常的 2<br/>但是<img src='/icons/13192dou.gif' />Delphi并没有在我绕开这个限制的后而放过我<img src='/icons/13192dou.gif' />很快<img src='/icons/13192dou.gif' />客户那边发现另<img src='/icons/13192yi.gif' />个麻烦<img src='/icons/13192de.gif' />问题<img src='/icons/13192dou.gif' />在开发环境下<img src='/icons/13192dou.gif' />每次运行时关闭载有Control控件<img src='/icons/13192de.gif' />窗体都会跳出<img src='/icons/13192yi.gif' />个异常<img src='/icons/13192cuowu.gif' /><img src='/icons/13192dou.gif' />但是在编译后<img src='/icons/13192de.gif' />应用<img src='/icons/13192chengxu.gif' />中则不会<img src='/icons/13192dou.gif' />虽然不会影响最终用户<img src='/icons/13192de.gif' />使用<img src='/icons/13192dou.gif' />但是这对开发人员来说是个不小<img src='/icons/13192de.gif' />困扰<img src='/icons/13192dou.gif' />然后我用了上述例子去试<img src='/icons/13192dou.gif' />发现并不会发生这个问题<img src='/icons/13192dou2.gif' />(我当时就疯了<img src='/icons/13192dou.gif' />这很可能是代码中<img src='/icons/13192yi.gif' />些不兼容<img src='/icons/13192de.gif' />使用方法所致<img src='/icons/13192dou.gif' />在<img src='/icons/13192yi.gif' />天时间里查找上万行代码是不是很正规是件极其恐怖<img src='/icons/13192de.gif' />事情)我<img src='/icons/13192yi.gif' />气的下<img src='/icons/13192dou.gif' />屏蔽了我<img src='/icons/13192de.gif' />Control控件中所有<img src='/icons/13192de.gif' />代码<img src='/icons/13192dou.gif' />只留下用户界面本身<img src='/icons/13192dou.gif' />然后奇怪<img src='/icons/13192de.gif' />事情发生了<img src='/icons/13192dou.gif' />我什么代码都没写<img src='/icons/13192dou.gif' />但是加载我<img src='/icons/13192de.gif' />Control控件还是会发生这个<img src='/icons/13192cuowu.gif' /><img src='/icons/13192dou.gif' />这使我又喜又惊<img src='/icons/13192dou.gif' />喜<img src='/icons/13192de.gif' />是这个问题和我<img src='/icons/13192de.gif' />代码无关<img src='/icons/13192dou.gif' />这样查找起来会方便<img src='/icons/13192de.gif' />多；惊<img src='/icons/13192de.gif' />是只是拖放几个VB中<img src='/icons/13192de.gif' />标准Control控件居然也会造成这种恐怖<img src='/icons/13192de.gif' /><img src='/icons/13192cuowu.gif' /><img src='/icons/13192dou.gif' />Delphi5和VB6的间<img src='/icons/13192de.gif' />矛盾还真不是<img src='/icons/13192yi.gif' />般<img src='/icons/13192de.gif' />深<img src='/icons/13192dou2.gif' />接下来<img src='/icons/13192de.gif' />2个小时里<img src='/icons/13192dou.gif' />我不断地删除界面上<img src='/icons/13192de.gif' />Control控件来测试到底是谁造成了这个致命<img src='/icons/13192de.gif' />异常<img src='/icons/13192dou2.gif' /><br/><br/><br/><br/>2个小时后<img src='/icons/13192dou.gif' />我舒了<img src='/icons/13192yi.gif' />口气<img src='/icons/13192dou.gif' />问题找到了<img src='/icons/13192dou.gif' />其根本问题是:<br/><br/><br/><br/>如果你在VB<img src='/icons/13192de.gif' />用户Control控件中使用类似Frame和PictureBox这样<img src='/icons/13192de.gif' />容器Control控件(其内部可以包含其他Control控件)时<img src='/icons/13192dou.gif' />那么您将不可以在这些Control控件中添加Label、Line、Image这样<img src='/icons/13192de.gif' />windowLessControl控件(也就是无窗口Control控件<img src='/icons/13192dou.gif' />它们在运行时是VB实时画出来<img src='/icons/13192de.gif' />)<img src='/icons/13192dou.gif' />否则您就会得到上面这样<img src='/icons/13192de.gif' /><img src='/icons/13192cuowu.gif' />报告<img src='/icons/13192dou2.gif' /><br/><br/><br/><br/><br/><br/>Delphi6、7隐蔽<img src='/icons/13192de.gif' />ActiveXControl控件 
		
          
              
          <br/>
        <br/>
          <br/>正是<img src='/icons/13192yinwei.gif' />有了Delphi5下面<img src='/icons/13192de.gif' />恐怖经历<img src='/icons/13192dou.gif' />我发现还是很有必要在Delphi6和7下面测试是不是也存在同样<img src='/icons/13192de.gif' />问题(的前<img src='/icons/13192de.gif' />版本<img src='/icons/13192yinwei.gif' />用户极少已无必要<img src='/icons/13192dou.gif' />Delphi8还没正式出<img src='/icons/13192dou.gif' />也暂不在考虑的列)<img src='/icons/13192dou2.gif' />结果是:……无论我加载多少次<img src='/icons/13192dou.gif' />我在ActiveX栏上始终没有发现那个期待已久<img src='/icons/13192de.gif' />小图标<img src='/icons/13192dou2.gif' />这样<img src='/icons/13192de.gif' />结果当然很滑稽<img src='/icons/13192dou.gif' />我连加载都做不到<img src='/icons/13192dou.gif' />更不要谈什么测试正常不正常了<img src='/icons/13192dou2.gif' /><br/><br/>同样<img src='/icons/13192de.gif' /><img src='/icons/13192dou.gif' />我搜索各类论坛和网站WebSite<img src='/icons/13192dou.gif' />CSDN里我也发现了更多<img src='/icons/13192de.gif' />类似问题<img src='/icons/13192de.gif' />提出者<img src='/icons/13192dou.gif' />但答案还是零<img src='/icons/13192dou.gif' />无奈的下<img src='/icons/13192dou.gif' />我只好对每个Delphi6、7中<img src='/icons/13192de.gif' />选项进行调整……<br/><br/>历时3小时15分54秒后<img src='/icons/13192dou.gif' />我找到了这个该死<img src='/icons/13192de.gif' />问题(请原谅我这么称呼它<img src='/icons/13192dou.gif' />我实在是忍无可忍)<img src='/icons/13192de.gif' />原因<img src='/icons/13192dou.gif' />或者说是解决办法<img src='/icons/13192dou.gif' />说起来其实很简单<img src='/icons/13192dou2.gif' /><br/><br/>现在请跟着我做:点击Tools菜单-&gt;EnvironmentOptions-&gt;TypeLibrary页,我们应该发现<img src='/icons/13192yi.gif' />项:IgnorespecialCoClassFlagsWhenImporting<img src='/icons/13192dou.gif' />选中它<img src='/icons/13192dou.gif' />然后再选中CanCreate那<img src='/icons/13192yi.gif' />项<img src='/icons/13192dou.gif' />那么现在<img src='/icons/13192dou.gif' />我们再尝试去导入那个可怜<img src='/icons/13192de.gif' />ActiveXControl控件吧(这里要注意<img src='/icons/13192dou.gif' />如果你已经导入过<img src='/icons/13192yi.gif' />次<img src='/icons/13192dou.gif' />那么请把产生<img src='/icons/13192de.gif' />那两个文件.dcr和.pas文件删除<img src='/icons/13192dou.gif' />否则将不会刷新)<img src='/icons/13192dou2.gif' />这次如果还是不能在ActiveX栏中发现那个Control控件<img src='/icons/13192de.gif' />话<img src='/icons/13192dou.gif' />那么只有致电Microsoft或是Borland<img src='/icons/13192dou.gif' />问问看什么时候它们能结成亲家<img src='/icons/13192dou.gif' />呵呵!<br/><br/><br/><br/>(另<img src='/icons/13192dou.gif' />在Delphi6和7中倒是没有发现Delphi5中出现<img src='/icons/13192de.gif' />上述<img src='/icons/13192cuowu.gif' />)<br/><br/><br/><br/>我<img src='/icons/13192de.gif' />测试环境是:<br/><br/>Win2K<br/><br/>Delphi5Update1<br/><br/>Delphi6Update2<br/><br/>Delphi7<br/><br/>        <a href="/mypdf/12095.pdf" title="查看 vbactivex控件:Delphi使用VB编写的ActiveX控件全攻略 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>Delphi教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/Delphi/Article12095.html</guid>
		</item>
		<item>
			<title><![CDATA[控件开发:讲述如何开发一个控件,很有价值(六)]]></title>
			<link>http://CrazyCoder.cn/Delphi/Article11916.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
                <br/>       ASH - Automatic Syntax highlight (Attempt 2) <br/><br/>[Please note: I have my Delphi Editor colors <img src='/icons/80501set.gif' />-to the [Ocean] colour speed <img src='/icons/80501set.gif' />tings for testing purposes. This <img src='/icons/80501set.gif' />ting works well _disibledevent=>Now put the following base code <img src='/icons/80501int.gif' />o the [OnChange] event of the RichEdit1 in Unit1.pas of Project1. Most of this code is just based _disibledevent=><CENTER>  procedure TForm1.RichEdit1Change(Sender: TObject); var <br/><br/><BLOCKQUOTE>WasSelStart,WasRow,Row,BeginSelStart,EndSelStart: Integer; <br/>MyRe: TRichEdit; <br/>MyPBuff: <img src='/icons/80501<img src='/icons/80501char.gif' />.gif' />[0..255] of char;<br/><br/></BLOCKQUOTE>begin <br/><br/><BLOCKQUOTE>MyRe := TRichEdit(Sender); <br/>WasSelStart := MyRE.SelStart; <br/>WasRow := MyRE.Perform(EM_LINEFROMCHAR, MyRE.SelStart, 0); <br/>BeginSelStart := MyRe.Perform(EM_LINEINDEX, Row, 0); <br/>EndSelStart := BeginSelStart + Length(MyRE.Lines.Strings[Row]); <br/>Row := WasRow;<br/><br/></BLOCKQUOTE>end;<br/><br/> <br/> <br/></CENTER><br/>Were going to use the GetToken<img src='/icons/80501kh.gif' /> function to do all the hard work. We\'ll need some extra variables to pass to the GetToken function, so add to the var section: <br/><br/><BLOCKQUOTE>MyTokenStr:<img src='/icons/80501string.gif' />; <br/>MyTokenState:TTokenState; <br/>MyRun:PChar; <br/>MySelStart: Integer;<br/><br/></BLOCKQUOTE>These are similar to the variables we used in the ConvertReadStream - in fact we want to do \"exactly\" the same thing, just _disibledevent=>MySelStart := BeginSelStart; <br/>MyRun := MyPBuff; <br/><br/>while(MyRun^ &lt;&gt; #0) do <br/>begin <br/><br/><BLOCKQUOTE>MyRun := PasCon.GetToken(MyRun,MyTokenState,MyTokenStr); <br/><br/>// <br/>// ScanForRtf; <br/>// SetRtf; <br/>// WriteBuffer(Prefix + TokenStr + Postfix); <br/>//<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE>end; <br/><br/>NB: As we will be using PasCon you\'ll have to move it from being a local variable of TForm1.Button1Click to be a global variable. This will mean you\'ll have to move all the initialising: <br/><br/>PasCon:=TPasConversion.Create; <br/>PasCon.UseDelphiHighlighting(3); <br/><br/>to a TForm1.Show, and the PasCon.Free to TForm1.Close procedure. It will still work <img src='/icons/80501if.gif' /> you _disibledevent=>
          
              
          <br/>
        <br/>
          <br/><br/>We did this back in the beginning remeber? When we <img src='/icons/80501set.gif' /> the &gt;10 character lines to the color red. But how do we do this now? Lets look at what we have in the variables at hand when we hit \"// SetRtf\" the first time: <br/> <br/><br/><br/><br/><br/>(these example uses Uni1.pas as the input file as its more <img src='/icons/80501int.gif' />eresting) <br/> <br/><br/><br/><br/> <br/><br/><CENTER>  VARIABLES <br/><br/>  01234567901234567890 <br/> Lines.Strings[R0]  unit Unit1; <br/> MyPBuff  unit Unit1; <br/> MyTokenState  tsIdent<img src='/icons/80501if.gif' />ier <br/> MyTokenStr  unit <br/> MyRun  Unit1; <br/> <br/></CENTER><br/>So what we need to do is select the word \'unit\' in the RichEdit control, and <img src='/icons/80501set.gif' /> its attributes. We do this by <img src='/icons/80501set.gif' />ting SelStart to the position of \'unit\' in the RichEdit control, and SelLength to the length of the word \'unit\'. And since \'unit\' is at the beginning of the current line - thats position is BeginSelStart (which I conveninently have stored in MySelStart - you\'ll see why). Lets replace the \"pseudo\" comment code with the following: <br/><br/><BLOCKQUOTE><BLOCKQUOTE>MyRe.SelStart := MySelStart; <br/>MyRe.SelLength := Length(MyTokenStr); <br/>MyRe.SelAttributes.Assign(PasCon.FParseFont[MyTokenState]);<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE>But remember we are in a loop - when we go around again we\'ll have the next token in the line, and the variables will look like this: <br/> <br/><br/><CENTER>  VARIABLES <br/><br/>  01234567901234567890 <br/> Lines.Strings[R0]  unit Unit1; <br/> MyPBuff  unit Unit1; <br/> MyTokenState  tsSpace <br/> MyTokenStr  (space character) <br/> MyRun  Unit1; <br/> <br/></CENTER><br/>But (space character) isn\'t at BeginSelStart (#0) in the RichEdit control. Its further along (at position #4). Which just happens to be BeginSelStart + Length(\'unit\'). We need to update MySelStart after we process the preceeding token, but before we go around the loop again: <br/><br/><BLOCKQUOTE><BLOCKQUOTE>MySelStart := MySelStart + Length(MyTokenStr);<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE>Okay - this is where we are standing at the moment: <br/> <br/> <br/><br/><CENTER>  procedure TForm1.RichEdit1Change(Sender: TObject); var <br/><br/><BLOCKQUOTE>WasSelStart,WasRow,Row,BeginSelStart,EndSelStart: Integer; <br/>MyRe : TRichEdit; <br/>MyPBuff: <img src='/icons/80501<img src='/icons/80501char.gif' />.gif' />[0..255] of char; <br/>MyTokenStr:<img src='/icons/80501string.gif' />; <br/>MyTokenState:TTokenState; <br/>MyRun:PChar; <br/>MySelStart: Integer;<br/><br/></BLOCKQUOTE>begin <br/><br/><BLOCKQUOTE>MyRe := TRichEdit(Sender); <br/><br/>WasSelStart := MyRE.SelStart; <br/>WasRow := MyRE.Perform(EM_LINEFROMCHAR, MyRE.SelStart, 0); <br/>Row := WasRow; <br/>BeginSelStart := MyRe.Perform(EM_LINEINDEX, Row, 0); <br/>EndSelStart := BeginSelStart + Length(MyRE.Lines.Strings[Row]); <br/><br/>StrPCopy(MyPBuff,MyRE.Lines.Strings[Row]); <br/>MyPBuff[Length(MyRE.Lines.Strings[Row])] := #0; <br/><br/>MySelStart := BeginSelStart; <br/>MyRun := MyPBuff; <br/><br/>while(MyRun^ &lt;&gt; #0) do <br/>begin<br/><br/></BLOCKQUOTE><BLOCKQUOTE><BLOCKQUOTE>MyRun := PasCon.GetToken(MyRun,MyTokenState,MyTokenStr); <br/>MyRe.SelStart := MySelStart; <br/>MyRe.SelLength := Length(MyTokenStr); <br/><br/>MyRe.SelAttributes.Assign(PasCon.FParseFont[MyTokenState]); <br/><br/>MySelStart := MySelStart + Length(MyTokenStr);<br/><br/></BLOCKQUOTE>end; <br/><br/>MyRE.SelStart := WasSelStart; <br/>MyRE.SelLength := 0;<br/><br/></BLOCKQUOTE>end;<br/><br/> <br/> <br/></CENTER><br/>Now: put the Debugging code _disibledevent=>
          
              
          <br/>
        <br/>
          <br/><br/>Somehow in our event we are triggering off another [OnChange] event. This call to the [OnChange] event code is stored in the message queue. When the event were currently in is finished, a <img src='/icons/80501new.gif' /> _disibledevent=>SaveOnChangeIn := MyRe.OnChange; <br/>MyRe.OnChange := nil; <br/><br/>~~~~~rest of code <br/><br/>MyRe.OnChange := SaveOnChangeIn;<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE>Try it out!!! <UL><LI>Compile and Run <LI>Open up Unit1.pas in the \"editor\" we have written <LI>Click in the RichEdit in the center of the first lines, in the middle of \"unit\". <LI>Press the [space bar] <LI>Press the [backspace key] <LI>Arrow to the end of the line <LI>Press [Enter] <LI>Press [BackSpace] <LI>[BackSpace] away the entire line <LI>Re-type the entire line </LI></UL>Result: \"functionally\" the Control should look that same as it did before we clicked in it. The line \"unit Unit1;\" should highlighted properly as per your Delphi 3.0 Editor (save the background colour). However its slow and flickers a great deal. Try opening up a <img src='/icons/80501new.gif' /> line and just type a long phrase - e.g \"<img src='/icons/80501if.gif' /> (RichEdit = Santa) then GetPresents(\'box of choclate\'); \" and you\'ll agree with me that: <OL><LI>GOOD - It is highlighting properly <LI>BAD - There is flickering <LI>BAD - The longer the line gets, the longer it takes to do the re-highlighting <LI>BAD - you get the \"someone is chasing me effect\" </LI></OL>The flickering is due to a number of components. We\'ll have to deal with each seperately. <br/><br/>The most obvious is the \"selecting\" of each Token. Visually the control is just repeating what we were able to do manually - when a piece of text is selected it becomes highlighted by the black stripe. We need to stop this from happening. Back to the helpfile(s) again. Have a search around, and come back after a snack <img src='/icons/80501break.gif' /> with some ideas... I\'m hungry :-) <br/> <br/> <br/><br/>Death to the black stripe <br/> <br/> <br/><br/>Marks: 5/10 <br/><br/>Most of you would have found the HideSelection property of the RichEdit control. When it is <img src='/icons/80501set.gif' /> to TRUE and the RichEdit looses the focus (the user clicks _disibledevent=>MyRe.Enabled := False; <br/><br/>~~~~~~ <br/><br/>MyRe.Enabled := True;<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE>Oops. I should have known. After all I said it: a disabled Control is not \"Focused\" - barely ten lines ago! When the RichEdit is enabled again, we also have to SetFocus back to it. Shees.. :-) <br/><br/><BLOCKQUOTE>begin <br/><br/><BLOCKQUOTE>MyRe := TRichEdit(Sender); <br/><br/>MyRe.Enabled := False; <br/><br/>~~~~~~ <br/><br/>MyRe.Enabled := True; <br/><br/>MyRe.SetFocus;<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE>Try it again. This time things are working better, and we\'re leaving poor old Edit1 Control alone. Thats good practice, as it may have had an [OnFocus] event that does wierder things than what we\'re trying to do. Maybe not now, but it could in the future!  
		
          
              
          <br/>
        <br/>
          <br/> <br/><br/>Marks: 10/10 <br/> <br/><br/>On the other kind, some of you may have found instead the EM_HIDESELECTION message in the Win32.HLP. If you had delved in, you would have found something very <img src='/icons/80501int.gif' />eresting. The Delphi HideSelection property _disibledevent=>MyRe.Perform(EM_HIDESELECTION,1,0); <br/><br/>~~~~~~ <br/><br/>MyRe.Perform(EM_HIDESELECTION,0,0);<br/><br/></BLOCKQUOTE>end<br/><br/></BLOCKQUOTE>Yummy. Nice clean coding: <br/> <br/> <br/><br/>Death to the FLICKER <br/> <br/> <br/><br/>The next major problem is this bloody flicker. You should pop back <img src='/icons/80501int.gif' />o Delphi for a second, and types some lines in its editor, to see <img src='/icons/80501if.gif' /> it flickers at all. It does. But _disibledevent=>In fact we don\'t need to do even that - we can just check whether the SelAttributes (which represents the current selection\'s attributes) is any d<img src='/icons/80501if.gif' />ferent from what we want to change it to i.e. FParseFont[MyTokenType]. This way <img src='/icons/80501if.gif' /> even the TokenType had changed, but the <img src='/icons/80501new.gif' /> and old TokenType shared the same display attributes, we would still conserve our drawing. <br/> <br/><br/><CENTER>  Actually the problems is that the RichEdit isn\'t doing the conserving. In the old text based system I used to use, <img src='/icons/80501if.gif' /> you pr<img src='/icons/80501int.gif' />ed something to the screen, and it was the same as something already _disibledevent=>If MyRe.SelAttributes.Color &lt;&gt; PasCon.FParseFont[MyTokenState].Color then <br/>MyRe.SelAttributes.Color := PasCon.FParseFont[MyTokenState].Color; <br/><br/><img src='/icons/80501if.gif' /> MyRe.SelAttributes.Style &lt;&gt; PasCon.FParseFont[MyTokenState].Style then <br/>MyRe.SelAttributes.Style := PasCon.FParseFont[MyTokenState].Style;<br/><br/></BLOCKQUOTE>And off you go and try it out... (PS. Yes the last bit of code is bad programming...) <br/><br/><br/><br/>        <a href="/mypdf/11916.pdf" title="查看 控件开发:讲述如何开发一个控件,很有价值(六) 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>Delphi教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/Delphi/Article11916.html</guid>
		</item>
		<item>
			<title><![CDATA[控件开发:讲述如何开发一个控件,很有价值(七)]]></title>
			<link>http://CrazyCoder.cn/Delphi/Article11915.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
                <br/>      <B><U>SUCCESS - (Nearly...)</U></B> <br/> <br/><br/>I think you\'ll agree we are pretty close. There is just a little bit of flicker. This flicker is the <B>SelStart</B> jumping the Cursor position around the text. We need to hide this. This \"Cursor\" is also known as a Caret. Looking throught <B>Win32.Hlp</B> again we find the lovely, and appropriately named, <B>HideCaret<img src='/icons/94836kh.gif' /></B> function. <br/><br/><B>Lets try this then</B>: everytime we change the value of <B>MyRe.SelStart</B> lets call <B>HideCaret(MyRe.Handle) </B>immediately before. <br/><br/>I\'ll be kind - that doesn\'t work. I tried 2 x <B>HideCaret(MyRe.Handle)</B>, and it still didn\'t work. Neither did three,four or 25x. So close - but yet - so far. I think its time for another Delphi Rule: <br/><br/><B>DELPHI RULE #5 - <I>If you bother to get your way through the atrocious index of the Win32.HLP file to find what you are looking for - make sure you <U>really</U> read what you found properly!</I></B> <br/><br/>The key was the last paragraph in the description of not <B>HideCaret</B> but <B>ShowCaret<I> </I></B>(which I had also read as I thought we were going to need it, especially to reverse my 25x <B>HideCaret<img src='/icons/94836kh.gif' /></B>). You also need another Delphi Rule to understand it: <br/> <br/><br/><CENTER>  <I>The caret is a shared resource; there is _disibledevent=>DELPHI RULE #6 - <I>Everything (basically) is a Window</I></B> <br/><br/>You see the RichEdit is a windows control and is also.. in a weird sense.. a window. It has a Handle, which is why HideCaret would accept it. So re-reading the last line again we get: <br/> <br/><br/><CENTER>  <I>The caret is a shared resource; there is _disibledevent=><B><U>ASH Version 0.9b</U></B> <br/> <br/> <br/><br/><CENTER>  <B>procedure TForm1.RichEdit1Change(Sender: TObject);</B> <B><U>var</U></B> <br/><br/><BLOCKQUOTE><B>SaveOnChangeIn: TNot<img src='/icons/94836if.gif' />yEvent;</B> <br/><B>WasSelStart,WasRow,Row,BeginSelStart,EndSelStart: Integer;</B> <br/><B>MyRe : TRichEdit;</B> <br/><B>MyPBuff: <img src='/icons/94836<img src='/icons/94836char.gif' />.gif' />[0..255] of char;</B> <br/><B>MyTokenStr:<img src='/icons/94836string.gif' />;</B> <br/><B>MyTokenState:TTokenState;</B> <br/><B>MyRun:PChar;</B> <br/><B>MySelStart: Integer;</B><br/><br/></BLOCKQUOTE><B><U>begin</U></B> <br/><br/><BLOCKQUOTE><B>MyRe := TRichEdit(Sender);</B> <br/><br/><B>SaveOnChangeIn := MyRe.OnChange;</B> <br/><B>MyRe.OnChange := nil;</B> <br/><br/><B>MyRe.Enabled := False;</B> <br/><br/><B>WasSelStart := MyRE.SelStart;</B> <br/><B>WasRow := MyRE.Perform(EM_LINEFROMCHAR, MyRE.SelStart, 0);</B> <br/><B>Row := WasRow;</B> <br/><B>BeginSelStart := MyRe.Perform(EM_LINEINDEX, Row, 0);</B> <br/><B>EndSelStart := BeginSelStart + Length(MyRE.Lines.Strings[Row]);</B> 
		
          
              
          <br/>
        <br/>
           <br/><br/><B>StrPCopy(MyPBuff,MyRE.Lines.Strings[Row]);</B> <br/><B>MYPBuff[Length(MyRE.Lines.Strings[Row])] := #0;</B> <br/><B>MySelStart := BeginSelStart;</B> <br/><B>MyRun := MyPBuff;</B> <br/><br/><B>while(MyRun^ &lt;&gt; #0) do</B> <br/><B><U>begin</U></B> <br/><br/><BLOCKQUOTE><B>MyRun := PasCon.GetToken(MyRun,MyTokenState,MyTokenStr);</B> <br/><br/><B>MyRE.SelStart := MySelStart;</B> <br/><B>MyRE.SelLength := Length(MyTokenStr);</B> <br/><br/><B>If MyRE.SelAttributes.Name &lt;&gt; PasCon.FParseFont[MyTokenState].Name then MyRE.SelAttributes.Name := PasCon.FParseFont[MyTokenState].Name;</B> <br/><br/><B>If MyRE.SelAttributes.Color &lt;&gt; PasCon.FParseFont[MyTokenState].Color then MyRE.SelAttributes.Color := PasCon.FParseFont[MyTokenState].Color;</B> <br/><br/><B><img src='/icons/94836if.gif' /> MyRE.SelAttributes.Style &lt;&gt; PasCon.FParseFont[MyTokenState].Style then MyRE.SelAttributes.Style := PasCon.FParseFont[MyTokenState].Style;</B> <br/><br/><B>MySelStart := MySelStart + Length(MyTokenStr);</B><br/><br/></BLOCKQUOTE><B><U>end;</U></B> <br/><br/><B>MyRE.SelStart := WasSelStart;</B> <br/><B>MyRE.SelLength := 0;</B> <br/><B>MyRe.OnChange := SaveOnChangeIn;</B> <br/><B>MyRe.Enabled := True;</B> <br/><br/><B>MyRe.SetFocus;</B><br/><br/></BLOCKQUOTE><B><U>end;</U></B><br/><br/> <br/> <br/></CENTER><br/><B><U>Towards - ASH Version 1.0b</U></B> <br/><br/>Couple of problems with the last version <img src='/icons/94836if.gif' /> you try it out for size: <OL><LI>Its slightly inefficient in that everytime <B>SelAttributes</B> is changed it forces a repa<img src='/icons/94836int.gif' /> of the same token in the control. We should instead use some variable (e.g <B>var DoFormat:Boolean</B>) to decided <img src='/icons/94836if.gif' /> we need to reformat, and then check the value of <B>DoFormat</B> at the end of this checking, and do it all then by a simple <B>SelAttribute.Assign(FParseFont[MyTokenState]). </B>This means we can also change the seperate \"<img src='/icons/94836if.gif' />\" statements to a single <B><img src='/icons/94836if.gif' /> ... then .. <img src='/icons/94836else.gif' /> .. <img src='/icons/94836if.gif' /> ... then .. <img src='/icons/94836else.gif' /></B> which should code faster - especially <img src='/icons/94836if.gif' /> you put the various test situations in the order of likeliness to occur (e.g font changes less frequently than the color, so should be further down the <B><img src='/icons/94836if.gif' />..<img src='/icons/94836else.gif' />..<img src='/icons/94836if.gif' /></B>) <LI><br/> <LI>For some reason <img src='/icons/94836if.gif' /> you type a <B><I>{style comment}</I></B> _disibledevent=>blue, <B>SelAttributes.Color</B> will equal clBlack. We must also examine <B>SelAttributes.ConsistentAttributes </B>to ensure that the entire selection is consistent in the way it is highlighted. If it isn\'t - then we want to force it to be rehighlighted - its obviously not in the correct format. <LI><br/> <LI>Multi-line comments are a big pain e.g <B><I>{ words &lt;CR&gt; word &lt;CR&gt; words }</I></B>. I don\'t have them in my 4GL so I didn\'t need to fix this sort of problem. However I do have muti-line <img src='/icons/94836string.gif' />s - so I need to be able to <img src='/icons/94836string.gif' /> <img src='/icons/94836string.gif' />s across many lines. The trouble is we have to code to program over a number of lines - but have a look at what happens in Delphi when you place a \"{\" anywhere in the code. The highlighting can force a repa<img src='/icons/94836int.gif' /> of the entire 2,000,000 lines of text in the control. We could catch that situation - ie <img src='/icons/94836if.gif' /> the last token _disibledevent=>
          
              
          <br/>
        <br/>
          <B><img src='/icons/94836if.gif' />...then..<img src='/icons/94836else.gif' />..list</B> didn\'t <img src='/icons/94836set.gif' /> <B>DoFormat := True</B>. But what happens <img src='/icons/94836if.gif' /> we\'re in a colour mode were Comment highlighting style = KeyWord highlighting style. We would stop prematurely. So this \"logic\" wont help in all situations. <br/> <br/><br/><LI>You can still get the \"someone is chasing you effect\" - except now its \"someone is fleeing from you\" effect. It happens when you have <B><I>(* This is a comment *)</I></B> and delete the first *-character. The control takes an appreciable time to rehighlight the text. <LI><br/> <LI>While looking for a fix for the last problem, I remembered the <B>Richedit.Lines.BeginUpdate</B> function. But that didn\'t help either. What we need is a <B>Richedit.BeginUpdate<I>.</I></B> What would that do? It would increase an <img src='/icons/94836int.gif' />ernal counter by _disibledevent=><br/> <LI>Fixing the mult-line comments: <LI><br/> <br/> <br/> <br/><br/>My current idea is to use the <B>RichEdit.Lines.Object</B> to store the TokenType of the first token on each line. This way we could easily know how far we need to go when re-hightlighting multi-line comments. Initially this would be <img src='/icons/94836set.gif' /> to <B>nil.</B> I think this will work. <br/><br/>[Editor update: This didn\'t actually work - as the RichEdit.Lines.Object isn\'t implemented in TRichEdit control. It is <br/>always nil regardless of what you assigned to it] <br/> <br/><br/><LI>Upgrading to RichEdit98: <LI><br/> <br/> <br/> <br/><br/>I\'m also in the process of updating to the <B>RichEdit98 components for Delphi 3.0-4.0. version 1.34 Author Alexander Obukhov, Minsk, Belarus.</B> This control has a number of advances on the standard RichEdit control that ships with Delphi. Included in this are: <UL><br/><br/><LI><B>BeginUpdate,EndUpdate</B> <LI><B>Independant background colours</B> <LI><B>Margins</B> <LI><B>Hotspots</B> <LI><B>(Source code in full)</B> </LI></UL></LI></OL>Anyway I hope you have enjoyed the adventure.I\'m sorry <img src='/icons/94836if.gif' /> not all the examples compile as written. They may need some fixing to compile <img src='/icons/94836if.gif' /> you copy straight from the Browser <img src='/icons/94836int.gif' />o the Delphi Editor. Please send any comments to jonhd@hotmail.com. <br/><br/>Jon HogDog <br/><br/><br/><br/>        <a href="/mypdf/11915.pdf" title="查看 控件开发:讲述如何开发一个控件,很有价值(七) 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>Delphi教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/Delphi/Article11915.html</guid>
		</item>
		<item>
			<title><![CDATA[控件开发:讲述如何开发一个控件,很有价值(五)]]></title>
			<link>http://CrazyCoder.cn/Delphi/Article11910.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
                <br/>      To start with I used the Edit1 Control to display the results of all these variables. I then tried manipulating text in the RichEdit to see what values I got. You should do the same. Type slowly in: <br/><br/><B>1234567890&lt;CR&gt;1234567890&lt;CR&gt;1234567890</B> <br/><br/>and see how the results are reflected in the Edit control as you do so. Then experiment - try adding stuff to the ends of lines, and in the beginning of the line, and middle of lines. You may have to refer back to the Code to work out which number represents which variable. <br/><br/>Okay, now using the variables we have, lets try selecting the text of the current line, and display it in a <img src='/icons/35062new.gif' /> Edit Control (Edit2). <br/><br/>Add the following code to see what happens (don’t forget to add the second edit control and make it as wide as possible): <br/><br/><BLOCKQUOTE><B> MyRe.SelStart := BeginSelStart;</B> <br/><B> MyRe.SelLength := EndSelStart - BeginSelStart;</B> <br/><B> Edit2.Text := MyRe.SelText;</B> <br/><B>end;</B><br/><br/></BLOCKQUOTE>Run the program and try it out. <br/><br/>OOPS - That doesn\'t work - the text re<img src='/icons/35062main.gif' />s selected and the original cursor position is lost. <br/>We need to re<img src='/icons/35062set.gif' /> <B>SelStart</B> and <B>SelLength</B> before we finish in the [OnChange] event. So let’s add at the end: <br/><br/><BLOCKQUOTE><B> MyRe.SelStart := WasSelStart;</B> <B>//back to were we started</B> <br/><B> MyRe.SelLength := 0; // nothing selected</B> <br/><B>end;</B><br/><br/></BLOCKQUOTE>While playing with text in the edit control I discovered something weird. <br/><br/>If you typed [1] then &lt;CR&gt; then [2] the Edit1 displayed [4-1-3-4]. <br/><br/>But there were _disibledevent=>, but before the \"re<img src='/icons/35062set.gif' />ting\" part, lets put some logic in to turn lines RED when they are longer than a certain length: <br/><br/><BLOCKQUOTE><B><img src='/icons/35062if.gif' /> (MyRe.SelLength &gt; 10) then MyRe.SelAttributes.Color := clRed;</B><br/><br/></BLOCKQUOTE>You\'ll notice two things <img src='/icons/35062if.gif' /> you test this out. First - it does work. Second however, is that <img src='/icons/35062if.gif' /> you type a line &gt; 10 characters, press <img src='/icons/35062return.gif' /> and type _disibledevent=>Red. This is because it inherits the Attributes of the preceding text. Just like <img src='/icons/35062if.gif' /> you have bold _disibledevent=><br/><br/></BLOCKQUOTE>That seems to work - except when you press <img src='/icons/35062return.gif' /> in the middle of a &gt; 10 character line you have already typed (which is already Red) to leave a stump &lt; 10 characters _disibledevent=>
          
              
          <br/>
        <br/>
          </I><br/><br/></BLOCKQUOTE></BLOCKQUOTE><B><I>8. Basically it all seems to kind-of work.. can\'t we do some <U>real</U> programming now?</I></B> <br/><br/>Okay, okay. But first we have a problem. Actually a rather big problem. The problem is <B>PasCon</B>. Why? <br/><br/><B>First:</B> It <img src='/icons/35062return.gif' />s RTF code. <br/><B>Problem:</B> We can\'t use RTF code. <br/><br/><B>Second:</B> its designed to work an entire stream, and then give it back to us again as a whole. <br/><B>Problem: </B>We actually want greater control over it than this \"all or nothing\" approach. <br/> <br/> <br/><br/><B><U>OOP to the Rescue</U></B> <br/> <br/><br/>When you have something that works in a situation, and needs to be applied in another situation were it has to do a similar, but subtly d<img src='/icons/35062if.gif' />ferent job - you have two choices: <OL><LI>copy the function, and re-write it for the <img src='/icons/35062new.gif' /> situation, or <LI>kludge around it (e.g use Pas2Rtf, and then write a RtfCodes2RtfControl procedure). </LI></OL>Modern languages however give you an option: OOP it. \"Object<img src='/icons/35062if.gif' />y\" it. This is more than just deriving something from an existing object. It is in a sense programming in a \"state of mind\". Controls should be created so they can be used in a variety of situations - father than situation spec<img src='/icons/35062if.gif' />ic. In this <img src='/icons/35062case.gif' /> all PasCon can deal with is tokenising the input stream and <img src='/icons/35062return.gif' />ing code RTF text. What we really need to do is divide it <img src='/icons/35062int.gif' />o two entitites. We need to separate the [Parsing/Recognise the Token and TokenType] from the [Encode it in RTF codes]. <br/><br/>So lets start with <B>ConvertReadStream</B>, editing it so it looks something like this: <br/> <br/><br/><CENTER>  function TPasConversion.ConvertReadStream: Integer; <br/>begin  FOutBuffSize := size+3; <br/> ReAllocMem(FOutBuff, FOutBuffSize); <br/> FTokenState := tsUnknown; <br/> FComment := csNo; <br/> FBuffPos := 0; <br/> FReadBuff := Memory; <br/><br/> {Write leading RTF} <br/><br/> WriteToBuffer(\'{ tf1ansideff0deftab720\'); <br/> WriteFontTable; <br/> WriteColorTable; <br/> WriteToBuffer(\'deflang1033pardplainf2fs20 \'); <br/><br/> Result:= Read(FReadBuff^, Size); <br/><br/> <img src='/icons/35062if.gif' /> Result &gt; 0 then <br/> begin <br/><br/> FReadBuff[Result] := #0; <br/> Run := FReadBuff; <br/><br/> while Run^ &lt;&gt; #0 do <br/> begin <br/><br/> Run := GetToken(Run,FTokenState,TokenStr); <br/> ScanForRTF; <br/> SetRTF; <br/> WriteToBuffer(PreFix + TokenStr + PostFix); <br/><br/> end; <br/><br/> {Write ending RTF} <br/><br/> WriteToBuffer(#13+#10+\'par }{\'+#13+#10); <br/><br/> end; <br/><br/> Clear; <br/><br/> SetPo<img src='/icons/35062int.gif' />er(FOutBuff, fBuffPos-1) ; <br/><br/>end; { ConvertReadStream }<br/><br/> <br/> <br/></CENTER><br/>The code for <B>ConvertReadStream</B> is now much smaller, and also easier to understand. We can then take all the code that used to be in  
		
          
              
          <br/>
        <br/>
          <B>ConvertReadStream</B> that did the tokenizing and create a <img src='/icons/35062new.gif' /> subroutine - the <B>GetToken</B> function that just does the recognizing and labelling of the individual tokens. In the process we also loose a huge number of repeated lines of code, as well as a number of sub-routines such as <B>HandleBorCom </B>and <B>HandleString</B>. <br/> <br/><br/><CENTER>  // <br/>// My Get Token routine <br/>// function TPasConversion.GetToken(Run: PChar; var aTokenState: TTokenState; <br/>var aTokenStr: <img src='/icons/35062string.gif' />):PChar; <br/>begin <br/><br/> aTokenState := tsUnknown; <br/> aTokenStr := \'; <br/> TokenPtr := Run; // Mark were we started <br/><br/> Case Run^ of <br/><br/><BLOCKQUOTE>#13: <br/><br/>begin <br/><br/><BLOCKQUOTE>aTokenState := tsCRLF; <br/>inc(Run, 2);<br/><br/></BLOCKQUOTE>end; <br/><br/>#1..#9, #11, #12, #14..#32: <br/><br/>begin <br/><br/><BLOCKQUOTE>while Run^ in [#1..#9, #11, #12, #14..#32] do inc(Run); <br/>aTokenState:= tsSpace;<br/><br/></BLOCKQUOTE>end; <br/><br/>\'A\'..\'Z\', \'a\'..\'z\', \'_\': <br/><br/>begin <br/><br/><BLOCKQUOTE>aTokenState:= tsIdent<img src='/icons/35062if.gif' />ier; <br/>inc(Run); <br/>while Run^ in [\'A\'..\'Z\', \'a\'..\'z\', \'0\'..\'9\', \'_\'] do inc(Run); <br/>TokenLen:= Run - TokenPtr; <br/>SetString(aTokenStr, TokenPtr, TokenLen);<br/><br/></BLOCKQUOTE><BLOCKQUOTE><img src='/icons/35062if.gif' /> IsKeyWord(aTokenStr) then <br/>begin <br/><br/><BLOCKQUOTE><img src='/icons/35062if.gif' /> IsDirective(aTokenStr) then aTokenState:= tsDirective <br/><img src='/icons/35062else.gif' /> aTokenState:= tsKeyWord;<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE>end; <br/><br/>\'0\'..\'9\': <br/><br/>begin <br/><br/><BLOCKQUOTE>inc(Run); <br/>aTokenState:= tsNumber; <br/>while Run^ in [\'0\'..\'9\', \'.\', \'e\', \'E\'] do inc(Run);<br/><br/></BLOCKQUOTE>end; <br/><br/>\'{\': <br/><br/>begin <br/><br/><BLOCKQUOTE>FComment := csBor; <br/>aTokenState := tsComment; <br/>while not ((Run^ = \'}\') or (Run^ = #0)) do inc(Run); <br/>inc(Run);<br/><br/></BLOCKQUOTE>end; <br/><br/>\'!\',\'\"\', \'%\', \'&amp;\', \'(\'..\'/\', \':\'..\'@\', \'[\'..\'^\', \'`\', \'~\' : <br/><br/>begin <br/><br/><BLOCKQUOTE>aTokenState:= tsUnknown; <br/>while Run^ in [\'!\',\'\"\', \'%\', \'&amp;\', \'(\'..\'/\', \':\'..\'@\', \'[\'..\'^\', <br/>\'`\', \'~\'] do <br/> 
		
          
              
          <br/>
        <br/>
          begin <br/><br/><BLOCKQUOTE>Case Run^ of<br/><br/></BLOCKQUOTE><BLOCKQUOTE><BLOCKQUOTE>\'/\': <br/><img src='/icons/35062if.gif' /> (Run + 1)^ = \'/\' then <br/>begin <br/><br/><BLOCKQUOTE><img src='/icons/35062if.gif' /> (aTokenState = tsUnknown) then <br/>begin <br/><br/><BLOCKQUOTE>while (Run^ &lt;&gt; #13) and (Run^ &lt;&gt; #0) do inc(Run); <br/>FComment:= csSlashes; <br/>aTokenState := tsComment; <br/><img src='/icons/35062break.gif' />;<br/><br/></BLOCKQUOTE>end<br/><br/></BLOCKQUOTE><BLOCKQUOTE><img src='/icons/35062else.gif' /><br/><br/></BLOCKQUOTE><BLOCKQUOTE>begin <br/><br/><BLOCKQUOTE>aTokenState := tsSymbol; <br/><img src='/icons/35062break.gif' />;<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE></BLOCKQUOTE><BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE><BLOCKQUOTE>\'(\': <br/><img src='/icons/35062if.gif' /> (Run + 1)^ = \'*\' then <br/>begin<br/><br/></BLOCKQUOTE><BLOCKQUOTE><BLOCKQUOTE><img src='/icons/35062if.gif' /> (aTokenState = tsUnknown) then <br/>begin <br/><br/><BLOCKQUOTE>while (Run^ &lt;&gt; #0) and not ( (Run^ = \')\') and ((Run - 1)^ = \'*\') ) do inc(Run); <br/><br/>FComment:= csAnsi; <br/>aTokenState := tsComment; <br/><br/>inc(Run); <br/><img src='/icons/35062break.gif' />;<br/><br/></BLOCKQUOTE>end<br/><br/></BLOCKQUOTE></BLOCKQUOTE><BLOCKQUOTE><BLOCKQUOTE><img src='/icons/35062else.gif' /><br/><br/></BLOCKQUOTE><BLOCKQUOTE>begin <br/><br/><BLOCKQUOTE>aTokenState := tsSymbol; <br/><img src='/icons/35062break.gif' />;<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE>end;<br/><br/></BLOCKQUOTE>end; <br/><br/>aTokenState := tsSymbol; inc(Run);<br/><br/></BLOCKQUOTE>end; <br/><br/><img src='/icons/35062if.gif' /> aTokenState = tsUnknown then aTokenState := tsSymbol;<br/><br/></BLOCKQUOTE>end; <br/><br/>#39: <br/><br/>begin <br/><br/><BLOCKQUOTE>aTokenState:= tsString; <br/>FComment:= csNo; <br/><br/>repeat <br/><br/><BLOCKQUOTE>Case Run^ of <br/> #0, #10, #13: raise exception.Create(\'Invalid <img src='/icons/35062string.gif' />\'); <br/>end;<br/><br/></BLOCKQUOTE><BLOCKQUOTE>inc(Run);<br/><br/></BLOCKQUOTE></BLOCKQUOTE><BLOCKQUOTE>until Run^ = #39; <br/><br/>inc(Run);<br/><br/></BLOCKQUOTE>end; <br/><br/>\'#\': <br/><br/>begin <br/><br/><BLOCKQUOTE>aTokenState:= tsString; <br/>while Run^ in [\'#\', \'0\'..\'9\'] do inc(Run);<br/><br/></BLOCKQUOTE>end; <br/><br/>\'$\': <br/><br/> 
		
          
              
          <br/>
        <br/>
          begin <br/><br/><BLOCKQUOTE>FTokenState:= tsNumber; <br/>while Run^ in [\'$\',\'0\'..\'9\', \'A\'..\'F\', \'a\'..\'f\'] do inc(Run);<br/><br/></BLOCKQUOTE>end; <br/><br/><img src='/icons/35062else.gif' /><br/><br/></BLOCKQUOTE><BLOCKQUOTE><BLOCKQUOTE><img src='/icons/35062if.gif' /> Run^ &lt;&gt; #0 then inc(Run);<br/><br/></BLOCKQUOTE></BLOCKQUOTE> end; <br/><br/> TokenLen := Run - TokenPtr; <br/> SetString(aTokenStr, TokenPtr, TokenLen); <br/> Result := Run <br/><br/>end; { ConvertReadStream }<br/><br/> <br/> <br/></CENTER><br/><br/>        <a href="/mypdf/11910.pdf" title="查看 控件开发:讲述如何开发一个控件,很有价值(五) 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>Delphi教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/Delphi/Article11910.html</guid>
		</item>
		<item>
			<title><![CDATA[控件开发:讲述如何开发一个控件,很有价值(二)]]></title>
			<link>http://CrazyCoder.cn/Delphi/Article11909.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
                <br/>      would be divided up <img src='/icons/36740int.gif' />o: <br/><br/><CENTER>  <B>procedure</B>  tsKeyWord <br/>   tsSpace <br/> TForm1  tsIdent<img src='/icons/36740if.gif' />ier <br/> .  tsSymbol <br/> FormCreate  tsIdent<img src='/icons/36740if.gif' />ier <br/> (  tsSymbol <br/> Sender  tsIdent<img src='/icons/36740if.gif' />ier <br/> :  tsSymbol <br/> TObject  tsIdent<img src='/icons/36740if.gif' />ier <br/> );  tsSymbol <br/>   tsSpace <br/> <I>{Create Form}</I>  tsComment <br/> &lt;CR&gt;&lt;LF&gt;  tsCRLF <br/> <br/></CENTER><br/><H2><U>How is it Done?</U></H2>The RichEdit control normally loads preformatted text from .RTF files by way of by of the <B>RichEdit.Lines.LoadFromFile<img src='/icons/36740kh.gif' /></B> function. YourPasEdit uses the <B>RichEdit.Lines.LoadFromStream<img src='/icons/36740kh.gif' /> </B>function to load the file from a <B>TPasConversion</B> - a custom TMemoryStream descendant. This stream takes the pla<img src='/icons/36740int.gif' /> text Pascal source file, loads it <img src='/icons/36740int.gif' />o its <img src='/icons/36740int.gif' />ernal memory buffe, and then converts it from plain text to a text impregnated with RTF codes. This way when it is loaded <img src='/icons/36740int.gif' />o the RichEdit control via <B>RichEdit.Lines.LoadFromStream </B>the Pascal source file appears in the control color-syntax highlighted. <br/><br/>To the <img src='/icons/36740main.gif' /> Editor, this process is transparent - the code looks something like this: <br/> <br/><br/><CENTER>  begin  NewRichEdit := TRichEdit.Create; <br/><br/> PasCon.Clear; // Prepare the TPasConversion <br/> PasCon.LoadFromFile(FName); // Load the File <img src='/icons/36740int.gif' />o the Memory Stream <br/> PasCon.ConvertReadStream; // Convert the stream to RTF format <br/><br/> NewRichEdit.Lines.BeginUpdate; <br/> NewRichEdit.Lines.LoadFromStream(PasCon); // Read from the TPasConversion <br/> NewRichEdit.Lines.EndUpdate <br/><br/> NewRichEdit.Show; <br/><br/> Result := NewRichEdit; <br/><br/>end<br/><br/> <br/> <B><I>EXAMPLE - snippet of code from the NewRichEditCreate(Fname) routine</I></B> <br/> <br/></CENTER><br/>As I said, it is the TMemoryStream derived <B>TPasConversion</B> which does all the hard work: <br/> <br/><br/><CENTER>  &lt;SOURCE PASCAL FILE&gt; <br/>| <br/>V <br/>Plain source loaded <img src='/icons/36740int.gif' />o memory <br/> (<B>TPasConversion.LoadFromFile)</B> <br/>| <br/>V <br/>Converted <img src='/icons/36740int.gif' />ernally by parsing the source file <br/>(<B>ConvertReadStream</B>) <br/>| <br/>V <br/>Result made available <br/>(<B>SetMemoryPo<img src='/icons/36740int.gif' />e</B>r) <br/>| <br/>V <br/><B>RichEdit.LoadFromStream</B> <br/><br/> <br/> <br/></CENTER><br/>Most of the work in TPasConversion is done by the  
		
          
              
          <br/>
        <br/>
          <B>ConvertReadStream</B> procedure. Its purpose is to split up each line of source code <img src='/icons/36740int.gif' />o tokens (as showed previously) and then depending _disibledevent=><CENTER>  // prepare the Outbuf to a certain default size FOutBuffSize:= size+3; <br/>ReAllocMem(FOutBuff, FOutBuffSize); <br/><br/>// Initialise the parser to its begining state <br/><br/>FTokenState := tsUnknown; <br/>FComment := csNo; <br/>FBuffPos := 0; <br/>FReadBuff := Memory; <br/><br/>// Write leading RTF Header <br/><br/>WriteToBuffer(\'{ tf1ansideff0deftab720{fonttbl{f0fswiss MS SansSer<img src='/icons/36740if.gif' />;} <br/>{f1fromanfchar<img src='/icons/36740set.gif' />2 Symbol;}{f2fmodern Courier New;}}\'+#13+#10); <br/>WriteToBuffer(\'{colortbl ed0green0lue0;}\'+#13+#10); <br/>WriteToBuffer(\'deflang1033pardplainf2fs20 \'); <br/><br/>// Create the INSTREAM (FReadBuff) and tokenize it <br/><br/>Result:= Read(FReadBuff^, Size); <br/>FReadBuff[Result] := #0; <br/><br/><img src='/icons/36740if.gif' /> Result &gt; 0 then <br/>begin <br/><br/> Run:= FReadBuff; <br/> TokenPtr:= Run; <br/><br/> while Run^ &lt;&gt; #0 do <br/> begin <br/><br/> Case Run^ of <br/><br/> #13: // Deal with CRLFs <br/> begin <br/> FComment:= csNo; <br/> HandleCRLF; <br/> end; <br/><br/> #1..#9, #11, #12, #14..#32: // Deal with various whitespaces, control codes <br/> begin <br/> while Run^ in [#1..#9, #11, #12, #14..#32] do inc(Run); <br/> FTokenState:= tsSpace; <br/> TokenLen:= Run - TokenPtr; <br/> SetString(TokenStr, TokenPtr, TokenLen); <br/> SetRTF; <br/> WriteToBuffer(Prefix + TokenStr + Postfix); <br/> TokenPtr:= Run; <br/> end; <br/><br/> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <br/> ~~~~~ much code removed ~~~~~~~~~~ <br/> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <br/><br/> end; <br/><br/>end<br/><br/> <br/> <B><I>EXAMPLE - snippet showing the while loop that <img src='/icons/36740break.gif' />s up the INSTREAM <img src='/icons/36740int.gif' />o recognised tokens</I></B> <br/> <br/></CENTER><br/>Most of the work is done by the<B> [<img src='/icons/36740case.gif' /> Run^ in ... end;]</B> section which \"<img src='/icons/36740break.gif' />s off\" a token from the INSTREAM (<B>FReadBuf</B>) based _disibledevent=>
          
              
          <br/>
        <br/>
          <B>TokenTypes</B> by examining each character in turn. Having worked out which tokentype it is, the actual encoding part is relatively easy: <br/> <br/><br/><CENTER>  FTokenState:= tsSpace; <br/>TokenLen:= Run - TokenPtr; <br/>SetString(TokenStr, TokenPtr, TokenLen); <br/>ScanForRTF; <br/>SetRTF; <br/>WriteToBuffer(Prefix + TokenStr + Postfix); <br/> <B><I> EXAMPLE - basic steps in encoding the output stream of the TPasConversion object</I></B> <br/> <br/></CENTER><br/>What’s happening here is the program: <UL><LI><img src='/icons/36740set.gif' />s <B>FTokenState</B> to what we believe it is (in this part of the code it is tsSpace which matches any <U>series</U> of Whitespaces) <LI>the length of the token is calculated by working out how far the current memory po<img src='/icons/36740int.gif' />er (<B>Run</B>) has moved since we finished with the last token (<B>TokenPtr</B>). <LI>the token is then copied from the Input buffer from the starting position of it in the memory buffer (<B>TokenPtr</B>) for the length of the token, <img src='/icons/36740int.gif' />o the variable <B>TokenStr</B>. <LI><B>ScanForRtf</B> just checks through the resultant <B>TokenStr</B> to ensure it doesn\'t have any funny characters that the RichEdit would confuse as RTF commands. If it finds any, it escapes them out. <LI><B>SetRTF</B> looks at the <B>FTokenState</B> to populate two global variables <B>Prefix</B> and <B>Postfix </B>with the appropriate RTF codes to give the token the right Color,Font,Boldness. <LI><B>WriteToBuffer</B> than simply puts the <B>TokenStr</B> with the <B>Prefix</B> and <B>Postfix</B> around it <img src='/icons/36740int.gif' />o the output buffer, and the loop then continues _disibledevent=>Back to the topic: Syntax Highlighting (on-the-fly)</U></B></H2>No source code is necessarily 100% applicable to your needs. I was fortunate in that most of the parser applied to my 4GL command syntax (e.g Strings were <img src='/icons/36740string.gif' />s, Numbers were numbers, similar Keywords). As well YourPasEditor had implemented most of the basic accessory tasks such as Pr<img src='/icons/36740int.gif' />ing, Find, Find and Replace, Multi-File editing. It was just a matter of adding in the extras I was after. <br/><br/><I>PROBLEM #1 - No colours or fonts</I> <br/><br/>One task the Parser didn\'t fully implement was Colors or D<img src='/icons/36740if.gif' />ferent Fonts, or even fonts sizes. The reason for this (after some trial and error) was that the <B>SetRTF</B> procedure <img src='/icons/36740new.gif' /> nothing about how to do this. It _disibledevent=>1. <B>procedure SetDelphiRTF(S: String; aTokenState: TTokenState);</B> <br/><br/> Add after the <B>try;</B> <br/><br/><B> Font.Color := StrToInt(Ed_List[0]);</B> <br/><br/>2. <B>procedure TPasConversion.SetPreAndPosFix</B> <br/><br/> Add after FPreFix[aTokenState] = \'; <br/><br/><B> FPreFixList[aTokenState] := ColorToRtf(aFont.Color);</B> <br/><br/>The ColorToRtf codes is already present, but hadn\'t been used for some reasone. If you try it out you\'ll understand why :-). You get absolutely no change except lots of \';\' in the wrong place.Change the \';\' to \'(space)\' in <B>ColorToRtf<img src='/icons/36740kh.gif' /></B>, and you get rid of the \';\' appearing in the RichEdit control, but no Colors anyway. <br/><br/>My first thought was that the value in <B>Ed_List[0] </B>didn\'t convert to a proper Font.Color. The easiest way to test this was to hard code <B>Font.Color := clGreen;</B> and see what happens. Again no luck. The format was consistent with the RTF codes I could see in the RTF header. What the $#%#$%# was wrong with it ? <br/><br/>It was about then that I realised I needed a crash course in RTF document structure. For this I rushed off to <U>www.microsoft.com</U> (please forgive me) and found a reference _disibledevent=>What did I do? I went <img src='/icons/36740int.gif' />o WordPad (which is just a glor<img src='/icons/36740if.gif' />ied RichEdit version 2.0 _disibledevent=>
          
              
          <br/>
        <br/>
          <I>Sorry Borland</I>. <br/><br/><br/><br/>        <a href="/mypdf/11909.pdf" title="查看 控件开发:讲述如何开发一个控件,很有价值(二) 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>Delphi教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/Delphi/Article11909.html</guid>
		</item>
		<item>
			<title><![CDATA[控件开发:讲述如何开发一个控件,很有价值]]></title>
			<link>http://CrazyCoder.cn/Delphi/Article11908.html</link>
			<description>
				<![CDATA[

		
          
              
          <br/>
        <br/>
                <br/>      The Unofficial Newsletter of Delphi Users <br/><br/><B>by Robert Vivrette</B> <br/><br/><br/><HR width=\"100%\"><B>Automatic Syntax Highlighting Using a RichEdit Control</B> (Updated with fixes) <br/><br/><B>Part 1 of \"A Tale of Two RichEdits\"</B> <br/><br/><B><I>by Jon Hogan-Doran - jonhd@hotmail.com</I></B> <br/><br/><B>Introduction</B> <br/><br/>As a <img src='/icons/76900new.gif' /> programmer to Delphi, with a history in C, C<img src='/icons/76900jiajia.gif' />, Unix shells and a little Awk and Perl, I came to it with a particular goal in mind. I wanted to implement an Editor for a Australian-4GL Databse language called cl4. Having little to no experience in Windows programming, except some dalliance in Powerbuilder and SQLExpress, it seemed a pretty imposing goal. <br/><br/>One is often taught when learning a <img src='/icons/76900new.gif' /> language to read a few books, tryout the samples and then start some simple coding. Unfortunately I\'m a bit of a sado-masochist, and love to jump in with all 10 fingers (and 10 toes) and try to implement the most d<img src='/icons/76900if.gif' />ficult parts first, and all at _disibledevent=>The Plan</U></B></H1>No-one wants to re-invent the wheel. The whole po<img src='/icons/76900int.gif' /> of OOP (Object oriented programming) is the reusability of objects. The whole po<img src='/icons/76900int.gif' /> of the Internet was the reusability of<B> <I>someone <img src='/icons/76900else.gif' />\'s</I></B> object. Luckily I had read enough about these component \"things\" to want to find some more. So I connected up to the Internet and went \"shopping\". <br/><br/>My shopping list: <OL><LI>Internet controls (telnet, remote shell, remote execute, ftp) <LI>Editor with multi-file capabilities <LI>Syntax highlighter or Parser <LI>Automatic Syntax highlighting</LI></OL>I shopped at: <UL><LI>Delphi Super Page <LI>Torri\'s page <LI>Borland <LI>RxLib\'s <LI>RzLib\'s <LI>QuickReport Homepage</LI></UL>Within 4 hour I was off the net with a number of goodies, 23 or so assorted controls, programs and Internet suites, (and plenty of stuff that had nothing to do with the current project, but I thought might be of use _disibledevent=><CENTER>  <B>YourPasEdit</B>  by D C AL CODA, Ken Hale and Coda Hale <br/> <B>PasToRTF</B>  by Martin Waldenburg (<img src='/icons/76900include.gif' />d in above) <br/> <B>TntClient</B>  by Francois Piette (and associated ICS suite) <br/> <B>RxTools</B>  by those great Russian dudes. <br/> <br/></CENTER><br/>YourPasEdit was a great find, and its description said it all: <br/> <br/><br/><CENTER>  <I>There are three <img src='/icons/76900main.gif' /> features in YourPasEdit. First is the PAS to RTF conversion unit, contained in mwPasToRtf.pas, by Martin Waldenburg. The second shows how to create TabSheets at run time, with a RichEdit. The third are the procedures written by Andrius Adamonis, which allow YourPasEdit to be associated with files and to open those files in the running instance of YourPasEdit, creating a <img src='/icons/76900new.gif' /> TabSheet and RichEdit for the <img src='/icons/76900new.gif' />ly opened file.</I> 
		
          
              
          <br/>
        <br/>
           <br/> <br/></CENTER><br/>Unfortunately it also told me: <br/> <br/><br/><CENTER>  <I>It is not <img src='/icons/76900int.gif' />ended to be a full Delphi file editor, because it does not highlight keywords _disibledevent=>YourPasEdit</U> so you can follow and (more importantly) program along. <br/> <br/><br/><H1><B><U>Syntax highlight (YourPasEdit)</U></B></H1>In YourPasEdit, syntax highlighting was done by parsing the plain text file, dividing each line of text <img src='/icons/76900int.gif' />o separate \"Tokens\", working out what TokenType each token was, and formatting them based _disibledevent=> <br/><br/>How these tokens were formatted (that is with what Color and Attributes) was determined by using the Delphi 3.0 Editors own <img src='/icons/76900set.gif' />tings as they are stored in the Windows Registry. Basically a line of Pascal source such as: <br/> <br/><br/><br/><br/><br/><I><B>procedure</B> TForm1.FormCreate(Sender: TObject); { Create the Form }</I> <br/><br/><br/>        <a href="/mypdf/11908.pdf" title="查看 控件开发:讲述如何开发一个控件,很有价值 的PDF电子文档">[查看PDF电子文档]</a>				]]>
			</description>
			<author></author>
			<category>Delphi教程</category>
			<pubDate>2009-02-12</pubDate>
			<guid>http://CrazyCoder.cn/Delphi/Article11908.html</guid>
		</item>
	</channel>
</rss>
