﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-我的一片天-文章分类-DELPHI</title><link>http://www.cnitblog.com/xkz/category/6241.html</link><description>我的一片天</description><language>zh-cn</language><lastBuildDate>Mon, 26 Sep 2011 14:56:12 GMT</lastBuildDate><pubDate>Mon, 26 Sep 2011 14:56:12 GMT</pubDate><ttl>60</ttl><item><title>A星(A-Star)寻路算法</title><link>http://www.cnitblog.com/xkz/articles/38338.html</link><dc:creator>xyz</dc:creator><author>xyz</author><pubDate>Mon, 31 Dec 2007 13:19:00 GMT</pubDate><guid>http://www.cnitblog.com/xkz/articles/38338.html</guid><wfw:comment>http://www.cnitblog.com/xkz/comments/38338.html</wfw:comment><comments>http://www.cnitblog.com/xkz/articles/38338.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/xkz/comments/commentRss/38338.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xkz/services/trackbacks/38338.html</trackback:ping><description><![CDATA[<p>unit aStarSearchPath;</p>
<p>interface<br>&nbsp;uses Classes,SysUtils;<br>&nbsp;<br>type<br>&nbsp; pAStarPathNode=^tAStarPathNode;<br>&nbsp; tAStarPathNode=record<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x,y:word;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; F:word;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; G:word;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; H:word;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; father:pAStarPathNode; //地图方格的父方格<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prev&nbsp; :pAStarPathNode; //链表上的上个节点<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; next&nbsp; :pAStarPathNode; //链表上的下个节点<br>&nbsp; end;<br>&nbsp; tAStarMapBuf=array of byte;</p>
<p>&nbsp; pAStarArea=^tAStarArea; //区域<br>&nbsp; tAStarArea=record<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; headNode:pAStarPathNode;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; endNode:pAStarPathNode;<br>&nbsp; end;</p>
<p>var<br>&nbsp; mapWidth,mapHeight:integer;<br>&nbsp; mapToX,mapToY:integer;<br>&nbsp; AStarOpenArea:pAStarArea;<br>&nbsp; AStarCloseArea:pAStarArea;<br>&nbsp; pAStarMapBuf:pByte;<br>&nbsp; nearGBuf:array [0..2,0..2] of byte;<br>&nbsp; <br>&nbsp; function ArrayOf(buf:pByte;x,y,xSize:word):byte;<br>&nbsp; function AStarFindPath(var returnPath:tstringlist;fromX,fromY,toX,toY,mapW,mapH:word;mapBuf:pByte):boolean;<br>&nbsp; function AStarGetHValue(fX,fY:word):word;<br>&nbsp; function AStarGetGValue(fX,fY,tX,tY:word):word;<br>&nbsp; procedure AStarInitNearG(x,y:word);<br>&nbsp; procedure AStarInsertByF(pHead:pAStarArea;thisNode:pAStarPathNode);<br>&nbsp; function AStarSearchMinF(fatherNode:pAStarPathNode):pAStarPathNode;</p>
<p>implementation</p>
<p>&nbsp; //数组与地图XY的对应关系: ary[y,x] 这样就能对应到地图的(x,y)<br>&nbsp; //因此传入的地图数组数据，第1个是Y，第2个是X,要注意与数据的位置对应</p>
<p>&nbsp; function AStarFindPath(var returnPath:tstringlist;fromX,fromY,toX,toY,mapW,mapH:word;mapBuf:pByte):boolean;<br>&nbsp; var<br>&nbsp;&nbsp;&nbsp; p:pAStarPathNode;<br>&nbsp;&nbsp;&nbsp; i:integer;<br>&nbsp;&nbsp;&nbsp; s:string;<br>&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp; result:=false;<br>&nbsp;&nbsp;&nbsp;&nbsp; pAStarMapBuf:=mapBuf;<br>&nbsp;&nbsp;&nbsp;&nbsp; mapToX:=toX;<br>&nbsp;&nbsp;&nbsp;&nbsp; mapToY:=toY;<br>&nbsp;&nbsp;&nbsp;&nbsp; mapWidth:=mapW;<br>&nbsp;&nbsp;&nbsp;&nbsp; mapHeight:=mapH;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; new(AStarCloseArea);&nbsp;&nbsp;&nbsp; //建立开放区<br>&nbsp;&nbsp;&nbsp;&nbsp; AStarCloseArea.headNode:=nil;<br>&nbsp;&nbsp;&nbsp;&nbsp; AStarCloseArea.endNode:=nil;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; new(AStarOpenArea);&nbsp;&nbsp;&nbsp;&nbsp; //建立封闭区<br>&nbsp;&nbsp;&nbsp;&nbsp; AStarOpenArea.headNode:=nil;<br>&nbsp;&nbsp;&nbsp;&nbsp; AStarOpenArea.endNode:=nil;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; new(p);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //起点加入开放区<br>&nbsp;&nbsp;&nbsp;&nbsp; p.x:=fromX;<br>&nbsp;&nbsp;&nbsp;&nbsp; p.y:=fromY;<br>&nbsp;&nbsp;&nbsp;&nbsp; p.G:=0;<br>&nbsp;&nbsp;&nbsp;&nbsp; p.H:=AStarGetHValue(fromx,fromY);<br>&nbsp;&nbsp;&nbsp;&nbsp; p.F:=p.G+p.H;<br>&nbsp;&nbsp;&nbsp;&nbsp; p.next:=nil;<br>&nbsp;&nbsp;&nbsp;&nbsp; p.father:=nil;<br>&nbsp;&nbsp;&nbsp;&nbsp; AStarOpenArea.headNode:=p;<br>&nbsp;&nbsp;&nbsp;&nbsp; AStarOpenArea.endNode:=p;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; while true do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (p.x=tox) and (p.y=toy) then break; //找到终点就退出<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:=AStarSearchMinF(p);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if p=nil then exit;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp; result:=true;<br>&nbsp;&nbsp;&nbsp;&nbsp; while true do //从终点开始延者父节点返回到起点就是路径<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if p=nil then break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s:=inttostr(p.x)+','+inttostr(p.y);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; returnPath.Insert(0,s);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:=p.father;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp; end;</p>
<p>&nbsp; //计算到目标点的H值<br>&nbsp; function AStarGetHValue(fX,fY:word):word;<br>&nbsp; var<br>&nbsp;&nbsp;&nbsp; dx,dy:integer;<br>&nbsp; begin<br>&nbsp;&nbsp;&nbsp; dx:=abs(fX-mapToX);<br>&nbsp;&nbsp;&nbsp; dy:=abs(fY-mapToY);<br>&nbsp;&nbsp;&nbsp; result:=dx*10+dy*10;<br>&nbsp; end;</p>
<p>&nbsp; //计算周围8个方向的G值<br>&nbsp; function AStarGetGValue(fX,fY,tX,tY:word):word;<br>&nbsp; var<br>&nbsp;&nbsp;&nbsp; dx,dy:integer;<br>&nbsp; begin<br>&nbsp;&nbsp;&nbsp; dx:=abs(fX-tX);<br>&nbsp;&nbsp;&nbsp; dy:=abs(fY)-(tY);<br>&nbsp;&nbsp;&nbsp; if (dx=0) and (dy=0) then result:=0<br>&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if dx*dy=0 then result:=10 else result:=14;<br>&nbsp; end;</p>
<p>&nbsp; //通过指针访问数组<br>&nbsp; function ArrayOf(buf:pByte;x,y,xSize:word):byte;<br>&nbsp; var<br>&nbsp;&nbsp;&nbsp; j:integer;<br>&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp; j:=y*xSize+x;<br>&nbsp;&nbsp;&nbsp;&nbsp; inc(buf,j);<br>&nbsp;&nbsp;&nbsp;&nbsp; result:=buf^;<br>&nbsp; end;&nbsp; </p>
<p>&nbsp; //设置x,y周围8个各自的G值<br>&nbsp; procedure AStarInitNearG(x,y:word);<br>&nbsp; var<br>&nbsp;&nbsp; i,j,v,x1,y1:integer;<br>&nbsp;&nbsp; p:pbyte;<br>&nbsp; begin<br>&nbsp;&nbsp;&nbsp; p:=pAStarMapBuf; //全局地图指针<br>&nbsp;&nbsp;&nbsp; fillChar(nearGBuf,9,1);<br>&nbsp;&nbsp;&nbsp; for i:=-1 to 1 do&nbsp; //Y<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y1:=y+i;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for j:=-1 to 1 do //X<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if nearGBuf[i+1,j+1]=0 then continue; //由于路障被预先处理了<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x1:=x+j;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //中间的点,超出地图范围的点不可用<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ((i=0) and (j=0)) or (x1&lt;0) or (y1&lt;0) or (x1&gt;mapWidth) or (y1&gt;mapHeight) then v:=-1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v:=ArrayOf(p,x1,y1,mapWidth); //看地图数据里这格是否是路障<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v:=AStarGetGValue(x,y,x1,y1) * v; //计算临近的格G值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (v=0) and ((x1=x) or (y1=y))&nbsp; then //格子平行方向不可行或竖向不可行，上下或左右的也不可行<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if y1=y then&nbsp; //左右边右路障，因方格有角，路障下面和上面的格也不可过<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nearGBuf[i,j+1]:=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nearGBuf[i+1,j+1]:=v; //自己=0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nearGBuf[i+2,j+1]:=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if x1=x then<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nearGBuf[i+1,j]:=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nearGBuf[i+1,j+1]:=v;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nearGBuf[i+1,j+2]:=0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if v&lt;0 then v:=0; //非超出范围的位置<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nearGBuf[i+1,j+1]:=v;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp; end;</p>
<p>&nbsp; //根据thisNode进行F值降序调整链接节点位置或者插入<br>&nbsp; procedure AStarInsertByF(pHead:pAStarArea;thisNode:pAStarPathNode);<br>&nbsp; var<br>&nbsp;&nbsp;&nbsp; p,p2:pAStarPathNode;<br>&nbsp;&nbsp;&nbsp; F:word;<br>&nbsp; begin<br>&nbsp;&nbsp;&nbsp; p:=pHead.headNode;<br>&nbsp;&nbsp;&nbsp; while true do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if thisNode.F&lt;p.F then //找到F值比自己大的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p2:=p.prev; //上个节点<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if p2=nil then //这个节点是头节点<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thisNode.prev:=nil;//变成头属性<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pHead.headNode:=thisNode; //插入第一个节点作为头<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p2.next:=thisNode; //跟上一个点对接<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thisNode.prev:=p2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.prev:=thisNode; //插入后对接<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thisNode.next:=p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if p.next=nil then //末尾<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if p=thisNode then exit; //就是自己啦<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.next:=thisNode;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thisNode.prev:=p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thisNode.next:=nil;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pHead.endNode:=thisNode;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:=p.next;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp; end;</p>
<p>&nbsp; //从开发区中选出F值最小的点<br>&nbsp; //原理：以基点为中心通过周围8方向辐射的方式不断的添加新格子(以基点作为父节点)到开放区<br>&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (完成这个工作后这个辐射基点要加到封闭区)<br>&nbsp; // 在辐射的过程中，同时检测早先被加入开放区的格子的G值是不是最小的(从辐射基点到该格子的G值)<br>&nbsp; // 如果这个基点到该格子的G值更小，则变换这个格子的父节点为基点并重新计算F值<br>&nbsp; //，然后在开放区中选出最小F值的格子，再继续以选定的点往外辐射,直至辐射到目的点<br>&nbsp; function AStarSearchMinF(fatherNode:pAStarPathNode):pAStarPathNode;<br>&nbsp; var<br>&nbsp;&nbsp;&nbsp; x,y,x1,y1:integer;<br>&nbsp;&nbsp;&nbsp; p,p2:pAStarPathNode;<br>&nbsp;&nbsp;&nbsp; pX,pY:integer;<br>&nbsp;&nbsp;&nbsp; g,h,f:word;<br>&nbsp; begin<br>&nbsp;&nbsp;&nbsp; pX:=fatherNode.x;<br>&nbsp;&nbsp;&nbsp; pY:=fatherNode.y;<br>&nbsp;&nbsp;&nbsp; AStarInitNearG(pX,pY);//周围的G值如何，路障，原点排除</p>
<p>&nbsp;&nbsp;&nbsp; for y:=1 downto -1 do&nbsp; //Y的3行<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for x:=1 downto -1 do //X的3列<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x1:=x+pX;&nbsp;&nbsp;&nbsp; //尝试周围的坐标<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; y1:=y+pY;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g:=nearGBuf[y+1,x+1]; //有可能被预先清0了(路障在中间时)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if g=0 then continue ;//跳过没有G值的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:=AStarOpenArea.headNode;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while true do&nbsp; //搜索此点是否在开发区内<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if p=nil then break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (p.x=x1) and (p.y=y1) then break; //在开放区<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:=p.next;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if p&lt;&gt;nil then //在开放区<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g:=p.G+g;&nbsp; //起点经由选中点到此点的G值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if g&lt;p.g then&nbsp; //经过此点更近，早先设置的父节点需要更改<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.father:=fatherNode;&nbsp; //更新它的父节点<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.G:=g;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.F:=p.G+p.H;//重新计算F值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;//后面不用再搜索封闭区了<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:=AStarCloseArea.headNode;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while true do&nbsp; //搜索封闭区<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if p=nil then break;&nbsp; //没有在封闭区<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (p.x=x1) and (p.y=y1) then break; //在封闭区<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:=p.next;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if p=nil then&nbsp; //这是个新点,设定父节点<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new(p);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.prev:=AStarOpenArea.endNode ; //接到最后的开放节点上<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AStarOpenArea.endNode:=p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.next:=nil;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.x:=x1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.y:=y1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.G:=fatherNode.G+g;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.H:=AStarGetHValue(x1,y1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.F:=p.G+p.H;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.father:=fatherNode; //父节点，保存是谁把它加入开放区的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AStarInsertByF(AStarOpenArea,p);//插入开发区中<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end; // next x<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end; //next y;</p>
<p>&nbsp;&nbsp;&nbsp; //把此节点从开放区抽出来，做好开放区节点的重新连接<br>&nbsp;&nbsp;&nbsp; if fatherNode.prev=nil then&nbsp; //当前点是开放区的第一个<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:=fatherNode.next;//下一个接的准备变成头<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.prev:=nil;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //头属性<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AStarOpenArea.headNode:=p;//更新头<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br>&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p:=fatherNode.next;&nbsp;&nbsp;&nbsp; //下个节点<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.prev:=fatherNode.prev; //连到这个点的上个节点上<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fatherNode.prev.next:=p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;</p>
<p>&nbsp;&nbsp;&nbsp; //准备加到封闭区的末尾<br>&nbsp;&nbsp;&nbsp; p:=AStarCloseArea.endNode;&nbsp; //封闭区最末的点<br>&nbsp;&nbsp;&nbsp; if p=nil then AStarCloseArea.headNode:=fatherNode; //如果没有，那这个也是头也是未<br>&nbsp;&nbsp;&nbsp; AStarCloseArea.endNode:=fatherNode; //是未位<br>&nbsp;&nbsp;&nbsp; fatherNode.prev:=nil;<br>&nbsp;&nbsp;&nbsp; fatherNode.next:=nil;<br>&nbsp;&nbsp;&nbsp; if p&lt;&gt;nil then //有其他的末位<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p.next:=fatherNode; //连到尾巴上<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fatherNode.prev:=p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; AStarOpenArea.headNode.prev:=nil; //最小的F已经在首个,设置成首属性<br>&nbsp;&nbsp;&nbsp; result:=AStarOpenArea.headNode;//返回F值最小的<br>&nbsp; end;</p>
<p>end.<br><br>调用方法：&nbsp;AStarFindPath<br>地图数据为字节型的数组,大小为mapW x mapH,调用时传入该数组的地址(pByte)</p>
<p>&nbsp;</p>
<img src ="http://www.cnitblog.com/xkz/aggbug/38338.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xkz/" target="_blank">xyz</a> 2007-12-31 21:19 <a href="http://www.cnitblog.com/xkz/articles/38338.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]在DELPHI程序中自动设置ODBC数据源</title><link>http://www.cnitblog.com/xkz/articles/35052.html</link><dc:creator>xyz</dc:creator><author>xyz</author><pubDate>Thu, 18 Oct 2007 13:20:00 GMT</pubDate><guid>http://www.cnitblog.com/xkz/articles/35052.html</guid><wfw:comment>http://www.cnitblog.com/xkz/comments/35052.html</wfw:comment><comments>http://www.cnitblog.com/xkz/articles/35052.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/xkz/comments/commentRss/35052.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xkz/services/trackbacks/35052.html</trackback:ping><description><![CDATA[<p>在DELPHI程序中自动设置ODBC数据源 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DELPHI 2005-9-1 12:49 <br>　　在DELPHI数据库应用程序中，我们访问数据库通常有两种方法．一种是通过BDE数据库搜索引擎，即利用DELPHI自带的数据库驱动程序，这种方法的优点是速度快，但应用范围有限，当数据库版本更新时，有可能不能用于操作新的数据库；另一种方法是通过ODBC，这种方法的优点是可以随操作系统(如WINDOWS)提供，作为标准接口能适应多种数据库，缺点是速度慢．在编程时，我们可以根据需要选择其中的一种方法．</p>
<p>　　在利用ODBC访问数据库时，通常的方法时是在ODBC管理面板中设置一个ODBC系统数据源(系统DSN)，然后在DBD中或在程序中设置一个数据库别名(Alias)对应该DSN，这样就可以如愿以偿地操作数据库了．相信用DELPHI做过数据库应用的程序员对这方面已经很熟悉了，笔者就不多说了．在实际应用中，笔者曾遇到过这样的情况，我们的数据库应用程序是依靠ODBC系统数据源访问和操作数据库的，应用程序运行一直良好，直到某一天，一个对WINDOWS系统较为熟悉但又不太精通的用户不慎修改或删除了我们预先设置的系统DSN......</p>
<p>　　于是，笔者就开始研究怎么在程序中动态地设置ODBC系统DSN的内容，这样就可以增加自己程序的坚固性了．经过整整一天对WINDOWS注册表的研究，终于找到了ODBC管理程序设置DSN的秘密（＂天地自有公道，付出总会回报！＂，不是做广告！），现写出来与大家共享，也请高手指教．<br>　　ODBC管理程序设置DSN的秘密在注册表中，不信可以到HKEY_LOCAL_MACHINE\Software\ODBC去看看，肯定让你感觉已经成功了一半．<br>　　首先来看看系统中已安装的ODBC数据库驱动程序．在HKEY_LOCAL_MACHINE\Software\ODBC\ ODBCInst.INI中，存放着已经安装了的ODBC数据库驱动程序的信息，从这里可以查到已安装的ODBC数据库驱动程序对应的DLL文件等信息．在ODBCInst.INI\ODBC Drivers的各个键值中，键名是驱动程序名称(如Microsoft Access Driver(*.mdb))，键值为&#8220;Installed&#8221;，表示驱动程序已安装．在 ODBCInst.INI\DriverName(DriverName为一个驱动程序名称，如Microsoft Access Driver(*.mdb))中，有驱动程序的详细信息，我们主要从这里获得ODBC驱动程序对应的DLL文件的路径和文件名，即键名Driver的键值，一般为"C:\WINDOWS\SYSTEM\FileName.DLL"．</p>
<p>　　然后来看系统DSN的注册信息，在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI中，存放着系统DSN的注册信息，我们在ODBC管理面板设置的DSN参数就在这里．</p>
<p>　　下面来看看创建一个ODBC系统DSN的步骤，即我们在ODBC管理面板中完成参数设置后，ODBC管理程序是怎么在注册表中注册DSN信息的．以创建一个名称为MyAccess的Ms Access97类型的系统DSN为例，我们指定的参数主要有数据库类型(Microsoft Access Driver(*.mdb))、数据源名称(MyAccess)、数据源描述(我的ACCESS)、数据库路径(C:\Inetpub\wwwroot\Test.mdb)，其它参数如用户名称、用户密码、独占、只读、系统数据库、默认目录、缓冲区大小、扫描行数、页超时等采用系统缺省参数．这时，注册系统DSN一般应有以下几个步骤：</p>
<p>　　1．在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\ODBC Data Sources中增加一个字符串键值，为MyAccess = Microsoft Access Driver(*.mdb)，其中分别为数据源名称和数据库类型．这是在注册表中注册一个系统DSN名称．</p>
<p>　　2．在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI中创建一个子键(SubKey)MyAccess，即创建一个键为HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\MyAccess，然后在其下创建一些键值，详细描述一个系统DSN的配置信息，主要信息有([]中的内容为笔者注释)：<br>DBQ=C:\Inetpub\wwwroot\Test.mdb [字符串，表示数据库路径]<br>Description=我的ACCESS [字符串，表示数据库描述]<br>Driver=C:\PWIN98\System\odbcjt32.dll [字符串，表示驱动程序，可见ODBCINST.INI]<br>DriverId=0x00000019(25) [数字，表示驱动程序标识，不能改变]<br>FIL=Ms Access; [字符串，可能与过滤Filter有关]<br>SafeTransaction=0x00000000 [数字，可能表示支持事务性操作的个数]<br>UID="" [字符串，表示用户名称，此处为空字符串]</p>
<p>　　3．在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\MyAccess中创建一个子键(SubKey)Engines，再在其下创建子键(SubKey)Jet，即创建一个键为 <br>HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\MyAccess\Engines\Jet，然后在其下创建一些键值，详细描述一个系统DSN的数据库引擎配置信息，主要信息有([]中的内容为笔者注释)：<br>ImplicitCommitSync=Yes [字符串，可能表示是否立即反映数据修改]<br>MaxBufferSize=0x00000200(512) [数字，表示缓冲区大小]<br>PageTimeout=0x00000005(5) [数字，表示页超时]<br>Threads=0x00000003(3) [数字，可能表示支持的最大线程数目]<br>UserCommitSync=Yes [字符串，可能表示是否立即将数据修改反映到用户]</p>
<p>　　以上是建立一个系统DSN的基本信息(其它信息如选项或高级选项等信息也在这里设置，只不过因采用默认信息，注册表里没有列出)，我们在程序中按上述步骤操作注册表，同样也能增加一个系统DSN或修改其配置．<br></p>
<img src ="http://www.cnitblog.com/xkz/aggbug/35052.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xkz/" target="_blank">xyz</a> 2007-10-18 21:20 <a href="http://www.cnitblog.com/xkz/articles/35052.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在DELPHI中实现打印的预览</title><link>http://www.cnitblog.com/xkz/articles/34102.html</link><dc:creator>xyz</dc:creator><author>xyz</author><pubDate>Thu, 27 Sep 2007 09:14:00 GMT</pubDate><guid>http://www.cnitblog.com/xkz/articles/34102.html</guid><wfw:comment>http://www.cnitblog.com/xkz/comments/34102.html</wfw:comment><comments>http://www.cnitblog.com/xkz/articles/34102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/xkz/comments/commentRss/34102.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xkz/services/trackbacks/34102.html</trackback:ping><description><![CDATA[<p>在DELPHI中实现打印的预览 <br>PCPOP.COM 2005年10月18日 类型:转载 作者:《电脑报》 编辑:王琛 </p>
<p>&nbsp; <br>--------------------------------------------------------------------------------</p>
<p>&nbsp;&nbsp;&nbsp; 在很多应用程序中，都需要程序具有打印预览功能，以避免用户由于选择不当出现打印错误。预览实现方式为通过创建一个Tpanel的派生类并公开它的canvas属性比例尺或视区范围，使用较为不方便，笔者通过实践实现了用图元文件（Metafile）来实现打印预览的方法，这种方式不需要调整比例尺和视区范围。</p>
<p>基本原理和方法：</p>
<p>　　　　使用图元文件的好处在于图元文件也称作"绘图类型"的图形，是以图形对象（线、圆弧、多边形）方式而不是像素方式来储存图像。图元文件将图形定义为编码的确线段和图形。Windows系统下有两种类型的图元文件:标准型（WMF文件格式）和增强型（EMF文件格式）。</p>
<p>它能够任意大小缩放并且任能保持一定的逼真度，这是因为图元文件通常由一系列矢量图形的图元组成，图元是指线条、填充的区域以及轮廓字体等。扩大或缩小图像只是简单地缩放定义这些图元的所有坐标点，所以当调整图像大小时，图元文件对图像的保存比像素更精确，效果更好。</p>
<p>　　Delphi以Tmetafile对象对 Win32增强型图元文件进行了封装，通过设置Enhanced属性可以设定图元文件是以标准型或可增强型格式存储。<br>在Delphi中使用图元文件的基本方法是：</p>
<p>&nbsp; 　创建图元文件<br>&nbsp; 　使用参照设备的打印机句柄创建图元文件画布对象（Tmetafilecanvas）<br>&nbsp; 　如同在打印机画布上一样，在图元文件画布进行描<br>&nbsp; 　将图元文件在屏幕上显示出来</p>
<p>实现步骤：</p>
<p>　　首先建立一个窗体文件，在适当位置放上一个panel控件 (panel)，一个checkbok控件(chedkbox1),并设定checkbox的 caption为"打印预览"，在panel上放置一个image控件(image), 并设image的align属性为kckient.</p>
<p>&nbsp; 　在USES中添加打印程序单元（Printers）,尽管Delphi在生成窗体时会自动在USESB部分加入许多程序单元，但打印程序单元却不在此列，只能手工给它加上。</p>
<p>&nbsp; 　关键代码说明：用GetDevice (Printer.Handle,LOGPIXESX)获取当前打印机的水平分辨率。</p>
<p>&nbsp;&nbsp;&nbsp; 如果想让打印程序在任何打印机上都能正常的打印，你就必须改变你的度量单位。</p>
<p>Dpm:=trunc(dpi/25.4);<br>//算出每毫米的打印机点数。<br>MyMetafile :=Tmetafile.Create;<br>//创建图元文件<br>TmetafileCanvas.Create (MyMetafile,printer.Handle)<br>//以打印机句柄创建图元文件画布<br>textout(trunc(sx*dpm), trunc(sy*dpm),'我的打印')；//进行打印输入<br>imagel.Camvas.StretchDraw (imagel.canvas.cliprect, MyMetafile);<br>//显示图元文件</p>
<p>程序源代码：<br>unit u_print;<br>interface<br>uses<br>Windows,Messages,SysUtils,Classes,Graphics,Controls,Controls,Fr-ms,Dialogs,<br>StdCtr;d,Buttons,printers,ExtCtrls;<br>Type<br>TF_prin = class(Tform)<br>&#8230;&#8230;&#8230;<br>private<br>{Private declarations}<br>public<br>{Public declarations}<br>end;<br>var<br>F_print: TF_print;<br>Implementation<br>{$R*.DFM}</p>
<p>procedure TF_print.BitBtn1Click(Sender:Tobject);<br>brgin<br>&nbsp; close;<br>end;</p>
<p>//定义report过程，使真实打印和打印愈来愈览共用此过程<br>procedure TF_print.report (Acanvas:Tcanvas);<br>var<br>&nbsp;sx,sy,sy0,sx0:real;//开始位置<br>&nbsp;dpi,dpm:real; //每毫米的点数<br>&nbsp;Arect: Trect;<br>Begin<br>&nbsp; Dpi: =GetDeviceCaps (Printer.Handle,LogPixelsX);<br>&nbsp; Dpm:=trunc(dpi/25.4); //每毫米的点数<br>&nbsp; Sx:=100; sx0:=10; sy0:=10 sy:=sy0;<br>&nbsp; with Acanvas do<br>&nbsp;&nbsp;&nbsp; try<br>&nbsp;&nbsp;&nbsp;&nbsp; font.name:='宋体'；<br>&nbsp;&nbsp;&nbsp;&nbsp; font.size:=18;<br>&nbsp;&nbsp;&nbsp;&nbsp; textout(trunc (60*dpm),trunc (sy*dpm),'姓名')；<br>&nbsp;&nbsp;&nbsp;&nbsp; sy:=sy+10;<br>&nbsp;&nbsp;&nbsp;&nbsp; pen.Width:=5;<br>&nbsp;&nbsp;&nbsp;&nbsp; MoveTo(trunc(sx0*dpm),trunc(sy*spm));<br>&nbsp;&nbsp;&nbsp;&nbsp; LineTo(trunc((sX0+200)*dpm),trunc(sy*dpm));<br>&nbsp;&nbsp;&nbsp;&nbsp; font.size:=12;<br>&nbsp;&nbsp;&nbsp;&nbsp; sy::=sy+5;<br>&nbsp;&nbsp;&nbsp;&nbsp; textout(trunc(sx0*dpm),trunc(ay*dpm),'内容')；<br>&nbsp;&nbsp;&nbsp;&nbsp; sy:=sy+5<br>&nbsp;&nbsp;&nbsp;&nbsp; MoveTo(trunc(sx0*dpm),trunc(sy*dpm));<br>&nbsp;&nbsp;&nbsp;&nbsp; LineTo(trunc((sX0+200)*dpm),trunc(sy*dpm));<br>&nbsp;&nbsp; finally<br>&nbsp;&nbsp;&nbsp;&nbsp; Free;<br>&nbsp; End;<br>End;</p>
<p>Procedure TF_print,BitBtn2Click（Sender:Tobject）;<br>Var<br>&nbsp; mymetafile:Tmetafile;<br>&nbsp; Ifprt:Boolean;<br>Begin<br>&nbsp; Ifprt:=not checkbok1.checked;<br>&nbsp; //是false则打印预览，true则打印<br>&nbsp; if ifprt then<br>&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp; printer.BeginDoc;<br>&nbsp;&nbsp;&nbsp;&nbsp; report(printer.canvas);<br>&nbsp;&nbsp;&nbsp;&nbsp; //将打印机画布对象传给report过程<br>&nbsp;&nbsp;&nbsp; end<br>&nbsp; else<br>&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp; MyMetafile: =Tmetafile.Create<br>&nbsp;&nbsp;&nbsp;&nbsp; //创建图元文件<br>&nbsp;&nbsp;&nbsp;&nbsp; //以打印机句柄创建图元文件画布对象（Tmetafilecanvas）,并调用report过程 <br>&nbsp;&nbsp;&nbsp;&nbsp; report (TmetagileCanvas.Create(MyMetafile, printer.Handle));<br>&nbsp;&nbsp; end;<br>&nbsp; //如果是打印则结束打印<br>&nbsp; if ifprt then printer.enddoc;<br>&nbsp;&nbsp; //如果是打印预览，则在image1上显示出来<br>&nbsp; if not ifprt then image1.Canvas.StretchDraw (image1.canvas.cliprect,MyMetafile);<br>end;<br>end.</p>
<br>
<img src ="http://www.cnitblog.com/xkz/aggbug/34102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xkz/" target="_blank">xyz</a> 2007-09-27 17:14 <a href="http://www.cnitblog.com/xkz/articles/34102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XMLDocument的用法</title><link>http://www.cnitblog.com/xkz/articles/34101.html</link><dc:creator>xyz</dc:creator><author>xyz</author><pubDate>Thu, 27 Sep 2007 09:13:00 GMT</pubDate><guid>http://www.cnitblog.com/xkz/articles/34101.html</guid><wfw:comment>http://www.cnitblog.com/xkz/comments/34101.html</wfw:comment><comments>http://www.cnitblog.com/xkz/articles/34101.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/xkz/comments/commentRss/34101.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xkz/services/trackbacks/34101.html</trackback:ping><description><![CDATA[<p>直接设置XML内容：<br>&nbsp;xml1.XML.Text:='&lt;option&gt;&lt;sql&gt;select * from abc&lt;/sql&gt;&lt;count&gt;2&lt;/count&gt;&lt;/option&gt;';&nbsp;<br>&nbsp;xml1.Active:=true;<br>&nbsp;aNode := XML1.DocumentElement;<br>&nbsp;showmessage(aNode.NodeName);</p>
<p>&nbsp;</p>
<p>逐节点加入：<br>var<br>XDoc :TXMLDocument;<br>Root :IXMLNode;<br>Node :IXMLNode;<br><br>begin<br>&nbsp;&nbsp;&nbsp; XDoc.Active := true;<br>&nbsp;&nbsp;&nbsp; Root := XDoc.AddChild('Root');<br>&nbsp;&nbsp;&nbsp; Node := Root.AddChild('Node');<br>&nbsp;&nbsp;&nbsp; Node.Attributes['Attrib'] := 'Attrib';<br>end;</p>
<p>读取XML节点:<br>var<br>XDoc :TXMLDocument;<br>sXML,sName,sAttr :AnsiString;<br>Root :IXMLNode;<br>Node :IXMLNode;<br>begin<br>&nbsp;&nbsp;&nbsp; XDoc.Active := false;<br>&nbsp;&nbsp;&nbsp; XDoc.XML.Text := sXML;<br>&nbsp;&nbsp;&nbsp; XDoc.Active := true;<br>&nbsp;&nbsp;&nbsp; Root = XDoc.DocumentElement;<br>&nbsp;&nbsp;&nbsp; if (Root.NodeName = 'Root')<br>&nbsp;&nbsp;&nbsp; begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Node := Root.ChildNodes.Nodes[0];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //或者Node := Root.ChildNodes['sql'];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sName := Node.NodeName;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sAttr := Node.GetAttribute(A_Folder);<br>&nbsp;&nbsp;&nbsp; end<br>&nbsp;&nbsp;&nbsp; XDoc.Active := false;<br>end;<br></p>
<img src ="http://www.cnitblog.com/xkz/aggbug/34101.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xkz/" target="_blank">xyz</a> 2007-09-27 17:13 <a href="http://www.cnitblog.com/xkz/articles/34101.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在onExit中使用setFocus时出现无光标的问题</title><link>http://www.cnitblog.com/xkz/articles/34100.html</link><dc:creator>xyz</dc:creator><author>xyz</author><pubDate>Thu, 27 Sep 2007 09:12:00 GMT</pubDate><guid>http://www.cnitblog.com/xkz/articles/34100.html</guid><wfw:comment>http://www.cnitblog.com/xkz/comments/34100.html</wfw:comment><comments>http://www.cnitblog.com/xkz/articles/34100.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/xkz/comments/commentRss/34100.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/xkz/services/trackbacks/34100.html</trackback:ping><description><![CDATA[<p>最近遇到一个问题,在edit1的onExit中设置edit2的焦点，虽然焦点成功转移到了edit2,但是在edit2上却没有光标显示，设置的有焦点自动变背景色的事件也无法触发。</p>
<p>问题代码如下：</p>
<p>procedure Tdbd.Edit1onExit(Sender: TObject);</p>
<p>&nbsp;&nbsp; edit2.setFocus</p>
<p>end;&nbsp;</p>
<p>估计是EDIT2的获焦点消息被EDIT1的离开焦点覆盖掉了。</p>
<p>后来手动给EDIT2再发一次获焦点的消息后能触发变色事件，但是却无法输入东西，需要用setFocus命令才正常。</p>
<p>procedure Tdbd.Edit1onExit(Sender: TObject);</p>
<p>&nbsp; postmessage(edit2.Handle,WM_SETFOCUS,0,0);</p>
<p>&nbsp;edit2.setFocus</p>
<p>end;</p>
<br>
<img src ="http://www.cnitblog.com/xkz/aggbug/34100.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/xkz/" target="_blank">xyz</a> 2007-09-27 17:12 <a href="http://www.cnitblog.com/xkz/articles/34100.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>