为VFP可视类增添绘图功能

Author: Date: 2000年 第6期

  Visual Foxpro中提供了基于 _Screen和表单窗口的绘图方法,如用Pset、Line画点、线等。然而感到其方法较有限,如有时需绘制圆弧、扇形或想对多边形填充,却发现Visual Foxpro可视类未提供相应的方法。现笔者找到两种解决方法:
    解决方法之一,可用控件自身的Pset及Point方法根据图形学基本算法设计子程序,该方法速度慢得让人无法忍受且效果不好。解决方法二,调用Windows API函数。Windows执行过程中常常通过动态连接库(DLLs)支持其所需的许多功能。这些动态函数库加载在内存中根据需要与用户程序进行连接。API 库中有丰富的图形操作函数。调用API函数有许多优点:功能全、速度快、程序代码小。
  有关访问API函数的文章已不少,这里不再重复。然而使用API函数在窗口或设备中绘图时,必须得到该窗口或设备的句柄HDC。在Visual Foxpro参考函数中却找不到获得HDC的方法,虽然可用API中的GetDc函数获得某窗口的HDC。但该函数又需用到窗口句柄作参数。如何获得窗口句柄呢?API函数(如:GetActiveWindow,GetWindow等)直接返回的是整个应用程序窗口句柄,而用户窗口一般是VFP应用程序中的一个文档窗。其实在VFP中返回用户窗口一个很方便的方法是通过FOXTOOLS.FLL库中WOnTop和WhToHwnd函数。上述函数语法如下:
  WHANDLE WonTop()*  返回用户使用的活动窗口WHandle
  HWND WhToHwnd(WHandle)*  返回相应的窗口句柄hWnd。
  HDC GetDC(hWnd)*  返回指定窗口hWnd的设备句柄hDC
  有了设备句柄调用绘图函数则很容易,例如:画矩形的API函数语法如下:
  BOOL Rectangle(hDC,x1,y1,x2,y2)
  其中x1,y1,x2,y2为矩形对角线的x,y坐标
  使用这些API函数绘图需注意几点:
  1.API函数使用前需用declare声明,另外应注意函数名称大小写(具体用法见文后程序)。
  2.调用以上函数时,WHandle、hWnd、hDc、x1、y1、x2、y2参数及BOOL均可用Integer类型进行说明,以上函数返回值若为0,表示调用失败。
  3.Visual FoxPro设置前景色、填充色等属性设置不影响API函数中绘图方式。
  4.使用Visual FoxPro原类方法的绘图方法时,会清除API画的图形。因此,两者最好不要混合使用。
  5.API函数参数中若有复合数据结构或数组,则应将该数据结构转换成String型。如下例语句可在VFP中调用Polygon函数绘制多边形。
  declare integer Polygon in win32api integer,string,integer
  dime point(3,2)* point为三角形顶点坐标
  trangle=′′
  for i=1 to 3
  point(i,1)=100+100*rand()* I点X坐标为(100~200)随机数
  point(i,2)=100+100*rand()* I点Y坐标为(100~200)随机数
  以下两条语句将多边形顶点的数值转化为字符,并连入字符串
  trangle=trangle+chr(point(i,1))+chr(0)+chr(0)+chr(0)
  trangle=trangle+chr(point(i,2))+chr(0)+chr(0)+chr(0)
  endfor
  polygon(thisform.hdc,trangle,3)
  VPF中打开一个表单,在表单中新建属性并新建API函数编制的绘图方法,最后将其保存为新类库。这样一个集绘图与原表单各种功能的可视类就建好了。
  以下是Visual Foxpro中用API函数动态设计饼形图的简单实例。图为执行程序后屏幕输出。三个文本框中任一数据改变后,饼形图将立即重绘。
  程序:
  为Form对象增加新属性hDc和新方法Pie。
  Form1的Load 事件:
  declare integer GetDC in win32api integer
  declare integer Pie in win32api integer,integer,integer,integer,;
    integer,integer,integer,integer,integer
  declare integer CreateSolidBrush in win32api long
  declare integer SelectObject in win32api integer,integer
  declare integer CreatePen in win32api integer,integer,long
  set library to sys(2004)+″foxtools.fll″
  Form1的Activate事件
  whandle=_WOnTop()
  hwnd=_WhToHwnd(whandle)
  set library to
  thisform.hDC=GetDC(hwnd)
  Form1的Pie方法
  lparameters x1,y1,x2,y2,x3,y3,x4,y4
  hbrush=CreateSolidBrush(thisform.fillcolor)
  hpen=Createpen(thisform.drawstyle,thisform.drawwidth,thisform.forecolor)
  =selectobject(thisform.hdc,hbrush)
  =selectobject(thisform.hdc,hpen)
  =pie(thisform.hdc,x1,y1,x2,y2,x3,y3,x4,y4)
  Form1的Unload事件
  clear dlls
  将本表单保存为新的可视类FORMDRAW。
  创建一个Form(FORMDRAW为其可视类)、添加四个Label、三个Text(Value属性分别赋三个数值)和三个Shape对象,属性设置略(使其外观如^06020401a^),为FORM增加方法Drawchar。
  表单的Drawchart方法:
  x1=thisform.text1.value
  x2=thisform.text2.value
  x3=thisform.text3.value
  total=x1+x2+x3
  a1=2*pi()*x1/total
  a2=2*pi()*x2/total
  x1=250
  y1=50
  x2=350
  y2=150
  mx=(x1+x2)/2-1
  my=(y1+y2)/2-1
  thisform.fillcolor=255
  =thisform.pie(x1,y1,x2,y2,mx+10,my,mx+10*cos(a1),my-10*sin(a1))
  thisform.fillcolor=rgb(0,255,0)
  =thisform.pie(x1,y1,x2,y2,mx+10*cos(a1),my-10*sin(a1),mx+10*cos(a1+a2),my;
  -10*sin(a1+a2))
  thisform.fillcolor=rgb(0,0,255)
  =thisform.pie(x1,y1,x2,y2,mx+10*cos(a1+a2),my-10*sin(a1+a2),mx+10,my)
  Text1、Text2、Text3的Valid事件:
  Thisform.drawchart
  表单的Paint事件
  Thisform.drawchart
  用API函数绘图与Visual FoxPro自身方法相比,使用更灵活、绘图性能强且速度快。关于Windows API 函数功能及用法请查阅有关资料。本文所述方法亦可在能与API函数通讯的其它软件中使用。