在VisualFoxPro中实现表单的输出

说在前面

VB、Delphi 都为 Form 对象封装了 PrintForm 方法,允许用户方便的将 Form 转换成为 BMP。这是一个不错的功能,在实际开发过程中是经常有这种需求的,比如把统计图表作为图片保存下来……

然而很不幸的是 Visual FoxPro(包括即将登场的 7.0) 并没有为我们封装此种功能。这个问题一定困扰着不少狐友吧,包括我。虽然我们知道使用 Win API 就可以解决问题,实际编程却又谈何容易?

很高兴得到了 George Tasker 编写的“OBJ2BMP”工具,并得到了所有原始代码。George Tasker 为我们提供了一个 Visual FoxPro 版的抓图工具,但我认为这个工具不见得实用——总不能在我们的应用程序中老是要调用一个工具才能完成 PrintFrom 的工作吧,这样既不专业也不美观。于是我利用 George Tasker 提供的源代码作了简单的二次开发,重新封装了部分功能,希望能这个很棒的工具更合适开发人员使用。

原始代码版权属于 George Tasker,本文及二次开发的版权属于 BOE 数据网络工作室。该软件属于免费软件,您可以随意使用,但如果造成什么不良后果,我们不承担任何责任。 

 以下所有讨论均以“象素”为单位!!!

使用 OBJ2BMP 工具

先让我们来看看怎样使用 George Tasker 为我们提供的 OBJ2BMP 工具吧!

编译项目成为 obj2bmp.app

使用 obj2bmp.app 工具

新建一个表单,设定表单的 alwaysOnTop属性为 .t.或者设定 alwaysOnBottom 属性为.t.,运行表单。

在“命令窗口”中键入如下命令,并执行:

oObjPicker=.null.DO Obj2Bmp.app WITH oObjPicker

如下图:

右面的表单就是抓图工具,请注意它下方的按下拉式列表框中列示了两个对象:“抓图”和“Select Object”(目的表单的Caption 属性)。“抓图”是指左面的表单,“Select Object”就是它自己。由于我们在下拉式列表框中选择了“抓图”表单,所以列表框中就列示了“抓图”中的所有可视控件:表单、Olecontrol、Command,您可以选择要抓拍的控件的名称,按下“Capture”按钮,您将得到该控件的当前模样的图片。

对于画面的质量您也可以控制,24 Bit Color 质量最好。

FormPrint 类的使用详解

从开发人员的角度看“obj2bmp”工具,好像实用性不大,于是我对源代码进行了简单的封装。

必备的支持文件

类文件:Obj2bmp.vcx、Obj2bmp.vct 类引用的头文件:rgb_256.h API 库:Foxtools.fll 其他的 API 库,我想这对 Windows 32 位系统是不成问题的

关于 Foxtools.fll 的说明。Foxtools.fll 是 Visual FoxPro 自带的 API 库,默认存放在 Home() 目录下。在建立 FormPrint 类实例时(init 事件)检测是否已对 Foxtools.fll 引用,如果没有则执行如下命令:

set library to (home()+"foxtools.fll") addi

请务必保证 Home() 目录下有此文件,如果您想把 Foxtools.fll放在其它地方,请修改以上语句。

引用 Foxtools.fll 的目地在于得到表单的句柄,在 Visual FoxPro 7 中每个表单都有句柄属性,就不用麻烦 Foxtools.fll 了。

FormPrint 类的用户接口

cFileName 属性:图片输出目录及名称。 makebitmap(pnhWnd, pnBPP, pnTop, pnLeft, pnHeight, pnWidth)方法:实现图片输出。

有关 cFileName 属性的说明。在使用 makebitmap 方法前设定此属性,可指定图片文件的名称及输出路径。如:

obj.cFileName="C:\BMP\abc.bmp" 将图片文件保存在C:\BMP目录下,文件名称是abc.bmp。

如果执行makebitmap方法时,目标文件已经存在,程序将在不通知的情况下覆盖它;如果执行 makebitmap 方法时文件不能建立(可能是目录不存在、路径无效、无法覆盖已存在的文件……),程序将重新设定图片文件的名称及保存目录,新文件名及目录是这样确定:

sys(5)+sys(2003)+"\"+left(sys(2015),8)+".bmp"

如果事先不设定 cFileName 属性,使其保持默认值 .null. 或设定 cFileName 为 .null. 值,程序也将使用“sys(5)+sys(2003)+"\"+left(sys(2015),8)+".bmp"”确定图片的名称及保存目录。

每次图片生成完毕,cFileName 属性自动设定为 .null. 值。

有关 makebitmap(pnhWnd, pnBPP, pnTop, pnLeft, pnHeight, pnWidth)方法的说明。

所有六个参数均可省略,但我建议调用时不要省略前两个参数。

——pnhWnd 代表被输出表单的句柄。如果 PrintForm 实例化以后其父对象是被输出表单的话,传递 0 即代表打印当前表单;如果要打印其他表单的话,请使用如下代码得到它的句柄,并以此句柄作为 pnhwnd 传递:

_WhTohWnd(_WFindTitl(cCaption))  && cCaption 代表被输出表单的 Caption 属性。

 ——pnBPP 代表输出图片的质量。有三种选择:4,8,24,数字越大质量越好。

输出整个表单

新建表单(实例一),添加控件。别忘了把 PrintForm 类加入表单,使之成为表单的子对象。如图:

A.最简单的应用,在“输出”按钮的“Click”事件中加入如下代码:

?ThisForm.printform1.makebitmap(0,24)* 显示:F:\OBJ2BMP\_0CU0FYF.BMP。表明图面文件的名称和位置。

B.指定输出目的地,在“输出”按钮的“Click”事件中加入如下代码:

Thisform.printform1.cFileName="C:\ABC.BMP"?ThisForm.printform1.makebitmap(0,24)* 显示:C:\ABC.BMP。表明图面文件的名称和位置。Thisform.printform1.cFileName="Z:\ABC.BMP"?ThisForm.printform1.makebitmap(0,24)* 显示:F:\OBJ2BMP\_0CU0FYT.BMP。因为Z盘不存在,图片文件无法建立,改用默认目录及文件名称。

C.输出其他表单。

建立一新表单(实例二),加入控件,运行。

在“实例一”表单的“输出”按钮的“Click”事件中加入如下代码,运行:

ThisForm.printform1.makebitmap(_WhTohWnd(_WFindTitl("实例二")) ,24) *"实例二"是后一个建立的表单的caption属性值。

如图:

输出选定区域

行文至此,PrintForm 类提供的功能已经与 VB、Delphi 打平了。接着我们就开始讨论怎样输出一个特定的矩形区域。

前文我们介绍调用 makebitmap(pnhWnd, pnBPP, pnTop, pnLeft, pnHeight, pnWidth)方法时,后四个参数不传递,表示输出整个表单。现在对这四个参数传值,就可以帮助我们完成特定区域输出的任务了。

先让我们来分析一下怎样在表单中定位一个区域。这个问题看起来很简单,在计算机中确定一个矩形区域只要得到四个值就可以了:顶点坐标、高度、宽度。例如打印下图左边的图形(image1控件)只要得到关于它的这些值就行了,如下。

顶点坐标B点 :(thisform.image1.top,thisform.image1.left)高度:thisform.image1.height宽度:thisform.image1.width。

注意:上图中,表单的 BorderStyle 属性设定为“3-可调边框”。

如果要输出这一区域请在“输出”按钮的 Click 事件中写入如下代码:

ThisForm.printform1.makebitmap(0 ,24,thisform.image1.top,;thisform.image1.left,thisform.image1.height,thisform.image1.width)

输出的图片图下:

可见并没有达到我们的预期目的。这是为什么呢?原来在本程序认为图片的顶点 O 为坐标原点,而我们认为点 A 为坐标原点,原点都认错了,取得的矩形当然不对。

话说回来,认为点 A 为原点也是有根据的,点 A 是客户图形区域的原点。在示例图中,整个画面是有“客户区域”+“系统区域”构成的,“系统区域”包括四个“边框区域”(上、下、左、右)、一个“标题栏区域”,如果有菜单栏还要算上菜单区域。

知道了这些,问题就明朗了,客户区域的确定是:

顶点坐标 A:(边框高度+标题栏高度,边框宽度)高度:thisform.height宽度:thisform.width。

用 Visual FoxPro 的语言表达这一区域,写作:

顶点坐标 A:(SysMetric(4)+SysMetric(9),SysMetric(3))高度:thisform.height宽度:thisform.width。

这里出现了一个很有用的函数 SysMetric(nScreenElement),如下:

使用以上方法,我们写出示例图中有关区域,如下:

区域

顶点

高度

宽度

客户区域

 SysMetric(4)+SysMetric(9),SysMetric(3)

thisform.height 

thisform.width 

Image1 

SysMetric(4)+SysMetric(9)+thisform.Image1.top,SysMetric(3)+thisform.Image1.left

thisform.Image1.height

thisform.Image1.width 

Container1 

SysMetric(4)+SysMetric(9)+thisform.Container1.top,SysMetric(3)+thisform.Container1.left

thisform.Container1.height 

thisform.Container1.width

Command1

SysMetric(4)+SysMetric(9)+thisform.Command1.top,SysMetric(3)+thisform.command1.left

thisform.Command1.height 

thisform.Command1.width 

如果要输出Image1所在区域,请在“输出”按钮的 Click 事件中写入如下代码:

ThisForm.printform1.makebitmap(0,24,SysMetric(4)+SysMetric(9)+thisform.Image1.top,;SysMetric(3)+thisform.Image1.left,thisform.image1.height,thisform.image1.width)

表单孙对象区域的输出

在示例图中的Container1对象中有一子对象Image1(thisform.container1.image1),如果用前文的计算方法我们是得不到正确的图形区域的(从略)。这是因为在 Visual FoxPro 中所有对象的TOP、LEFT属性均是相对于其父对象而言的,这个Image1的父对象是Container1对象而不是表单——新的问题产生了!

以下是正确的结果:

顶点坐标 A:(SysMetric(4)+SysMetric(9)+objtoclient(thisform.container1.image1,1),;SysMetric(3)+objtoclient(thisform.container1.image1,2)高度:thisform.container1.image1.height宽度:thisform.container1.image1.width。

objtoclient()有是一个很有用的函数,返回对象相对于表单的位置(客户区)。

具体用法是如下:OBJTOCLIENT(ObjectName, nPosition),

nPosition 

 位置

1

 顶边

2

 左边

猫猫的心里话

加菲猫的VFP|狐友会社群接收投稿啦

加菲猫的VFP,用VFP不局限VFP,用VFP混合一切。无论是VFP,还是JS,还是C,只要能混合起来,都可以发表。

商业模式,销售技巧、需求规划、产品设计的知识通通可以发表。

暂定千字50元红包,,优秀的文章红包更大,一经发表,红包到手。

如何帮助使用VFP的人?

用VFP的人,有专业的,有非专业了,很多人其实是小白,问出的问题是小白,如果问题不对,我们引导他们问正确的问题。无论如何请不要嘲笑他们说帮助都不看,这么简单的问题都不会,嘲笑别人不行,而无法提出建设性答案,是很low的。

我们无论工作需要,还是有自己的软件,都是是需要真正的知识,如何让更多人学习真正的VFP知识呢,只需要点赞,在看,能转发朋友圈就更好了。

加菲猫的vfp倡导用"VFP极简混合开发,少写代码、快速出活,用VFP,但不局限于VFP,各种语言混合开发"

我已经带领一百多名会员成功掌到VFP的黑科技,进入了移动互联网时代,接下来我们要进入物联网领域。

2026年狐友会社群会员继续招募中

社群会员获取的权益有:

祺佑三层开发框架商业版(猫框),终身免费升级,终身技术支持。

开放的录播课程有:

微信小程序,微信公众号开发,H5 APP开发,Extjs BS开发,VFP面向对象进阶,VFP中间层开发,VFP Layui 开发

源码类资源有:

支付组件源码,短信源码,权限组件源码,一些完整系统的源码。这个可以单独出售的,需要的可以联系我。

会员也可以实现群内资源对接,可以接分包,合作等各项商业或技术业务

内容概要:本文系统阐述了Python在数据分析与可视化领域的技术实践,涵盖数据分析基础、数据探索方法、可视化技术原理、高级可视化应用及实战案例五大方面。文章首先介绍NumPy和Pandas在数据处理与描述性统计中的核心作用,继而讲解相关性分析、分布分析和分组对比等探索性分析方法。随后深入剖析Matplotlib、Seaborn和Plotly三大可视化库的技术特点与应用场景,涵盖静态图表、统计图形到交互式可视化。最后通过交通数据的实战案例,演示从数据预处理、探索分析到多维度可视化呈现的完整流程。; 适合人群:具备Python基础、对数据处理与可视化感兴趣的初中级开发者,以及从事数据分析、运营分析、数据科学研究等相关工作的人员;尤其适合工作1-3年、希望提升数据实战能力的研发人员。; 使用场景及目标:①掌握Pandas进行数据清洗、分组聚合与描述性统计的方法;②熟练运用Matplotlib、Seaborn和Plotly实现多样化数据可视化;③通过真实案例理解探索性数据分析流程并构建交互式仪表盘;④应用于业务报表开发、数据洞察挖掘和决策支持系统建设。; 阅读建议:建议结合代码实践同步学习,重点理解不同可视化工具的适用边界,并在实战中尝试迁移应用文中案例逻辑,强化对数据分布识别、多维分析和交互设计的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值