[翻译]pb技巧、代码和实用工具
原文: http://www.softtreetech.com/hightech/tips.htm
pb技巧、代码和实用工具
内容列表:
1.ListView, PictureListBox, DropDownPictureListBox, TreeView和Application图标的秘密
2.克格勃间谍
3.DataWindow的属性页:General页面
4.动态函数调用
5.DataWindow的秘密——CPU和其他全局函数
6.DataWindow的秘密——Timer事件
7.重载系统函数
8.菜单的秘密——工具栏动画图标
9.Environment对象的秘密
10.DataWindow的行选中颜色
11.DataStore实现的秘密
12.性能测试:DataStore vs DataWindow
13.DataWindow的秘密——最小化DataWindow控件
14.PB资源文件(PBR)的秘密
15.pb日期和2000年问题兼容性
16.菜单的秘密——工具栏提示和文本
17.Table画板的秘密——Open Table对话框
18.菜单的秘密——动态添加新菜单项
19.最简单的统计TreeView项数的方法
20.pb可执行文件的秘密
21.GetChild()的秘密
22.DataWindow修复工具
23.DBMS/DataWindow列的依赖关系
24.带菜单的响应式窗口
25.没有菜单和工具栏的MDI框架
26.动态DataWindow的秘密
27.自定义的工具栏——其实很简单
28.PB中的异步处理
29.DataWindow导出到Excel(包含计算域、表头、脚注、分组、文本...)
30.另一个工具栏技巧
31.在PB程序之间交换信息
32.SQL异常处理
33.IsValid?
34.庞大的Windows API库(包括函数、结构和常量)
35.访问TopSpeed数据库
————————————————————————————————
ListView, PictureListBox, DropDownPictureListBox, TreeView和程序图标的秘密
下列枚举常量可以用作ListView, PictureListBox, DropDownPictureListBox, TreeView的图片名称,也可以用作Application对
象的图标名称.
Question!
Exclamation!
Hand!
StopSign!
Information!
ApplicationIcon!
Error!
WinLogo!
Rectangle!
例如,上述常量可以可以取代位图用在自定义的MessageBox窗口里.而且可以在代码里动态修改它们.这些图象跟操作系统一致,在
Windows 3.1和Windows 95/NT下有不同的外观.他们跟系统的MessageBox里的图象一模一样.要实现一个自定义的MessageBox:
1. 创建一个响应式窗口,放一个ListView控件.
2. 打开控件的属性对话框,在Large Picture页面的Picture Name列表里输入想要的图标名称,然后切换到Item页面,输入一项.切
换到General页面,不选中Enabled和Scrolling,Border选择None,关闭属性对话框.
3. 调整ListView控件的大小以适应图片.
4. 在窗口上放置一个MultiLineEdit控件以显示自定义的消息文本.完成其他的编码工作.
————————————————————————————————
如果你认为你的程序具有完美的安全系统,试试"克格勃间谍".
使用克格勃间谍可以"点击"禁用或隐藏的按钮和控件.自己看看吧.
在这里下载克格勃间谍.使用该程序测试你的软件的安全性.需要PB6开发环境来运行.
在这里下载克格勃间谍的源代码.
————————————————————————————————
DataWindow的属性页:General页面
PB帮助:"DataWindow property sheet, General tab, DataWindow Object Name - The name of the DataWindow object you
want to embed in the Window." 其实也可以指定需要嵌入到窗口的PSR文件名.虽然不能使用浏览按钮来选择PSR文件,你可以输
进去,或者粘贴.
————————————————————————————————
动态函数调用
PB帮助:"When you specify a dynamic call, the function or event does not have to exist when you compile the code.
You are saying to the compiler: trust me - there will be a suitable function or event available at execution
time."
也有这样的情况:编译时函数已经存在,但是由于编译器报"函数未找到"(实际上是"类型不匹配")错误而不能直接调用.使用DYNAM
IC通常能显著减少代码逻辑的分支判断.
考虑下例:
////////////////////////////////////////
// PB旧风格 //
////////////////////////////////////////
global function boolean f_zoom_out( powerobject apo_target )
DataWindow ldw_target
DataWindowChild ldwc_target
DataStore lds_target
CHOOSE CASE TypeOf( apo_target )
CASE DataWindow!
ldw_target = apo_target
ldw_target.Modify('DataWindow.Zoom=90')
CASE DataWindowChild!
ldwc_target = apo_target
ldwc_target.Modify('DataWindow.Zoom=90')
CASE DataStore!
lds_target = apo_target
lds_target.Modify('DataWindow.Zoom=90')
CASE ELSE
// invalid argument type
RETURN False
END CHOOSE
RETURN True
在PB5和6中可以使用更有效优美的代码:
//////////////////////////////////////////////////
// PB 5&6 新风格 //
/////////////////////////////////////////////////
global function boolean f_zoom_out( powerobject apo_target )
RETURN (apo_target.DYNAMIC Modify('DataWindow.Zoom=90') = '')
该技巧同样可以用于其他对象和函数.但是在PB5中,由于编译器的限制,某些重要的函数如Describe不能动态调用.
————————————————————————————————
DataWindow的秘密——CPU和其他全局函数
DataWindow画板没有完整地提供可用于DataWindow表达式的函数列表.例如,可以在表达式中使用CPU()函数,虽然它没有在"Modif
y Expression: Functions list box."中列出.
这个函数在处理比秒更小的时间段时可能有用.或许你希望在DataWindow里加点动画,使用Bitmap()函数构造一个表达式.该表达
式能告诉PB在没有DataWindow之外的干预时怎样改变图片.因此你希望编写如下的表达式:
Bitmap(CASE( mod( cpu(), 200 )
WHEN IS <= 50 THEN 'file1.bmp'
WHEN IS <= 100 THEN 'file2.bmp'
WHEN IS <= 150 THEN 'file3.bmp'
ELSE 'file4.bmp') )
设置DataWindow对象的Timer
INterval为50毫秒,PB将循环显示文件1至4,模拟出动画效果.注意,你还必须创建至少一个使用了Today()的表达式,否则PB会忽略
Timer Interval.不想显示该表达式的话,设置其visible属性为0.
计算DataWindow表达式时,PB对表达式中的函数进行三次查找.首先,检查专用于DataWindow画板的函数;然后,检查用户定义的全
局函数;最后,检查全局系统函数.这就是可以在DataWindow表达式中调用系统函数的原因.此外,懂得了这一点,可以在PB中创建某
种宏语言,它不需要编译,却能够在运行时被执行.例如,下述命令会显示一个消息框:
string ls_command
// ... some file operations to read a command from the script file. Perhaps it is
// MessageBox ("Dynamic Message", "Hello World")
dw_1.Describe("Evaluate(' " + ls_command + " ', 1)")
记住,DataWindow表达式必须下列数据类型之一:
Double
String
DateTime
Time
在表达式内部,函数可以返回其他数据类型(比如boolean,date,int),但表达式的最终结果被转变成上面四种类型之一.
点击这里下载使用CPU()模拟屏保的小例子.
————————————————————————————————
DataWindow的秘密——Timer事件
在DataWindow控件声明Timer事件,映射到pbm_timer事件.你的最初反应应该是不会有什么动静.但如果相关联的DataWindow对象
的Timer Interval属性设置为非0值,你会发现PB会触发DataWindow控件的timer事件.记住,关联的DataWindow对象必须含有调用
了Today()或Now()的表达式,pb才启动DataWindow的timer.另外,Timer Interval以毫秒为单位,而不是像Timer()函数那个以秒为
单位.现在在这个新的timer事件中编写代码,pb会维护它.本方法允许DataWindow控件拥有timer事件而不需要声明调用外部函数.
在16位和32位Windows下均有效.
————————————————————————————————
重载系统函数
或许以前你开发过一个漂亮的、用户友好的程序.现在老板要求你的程序更友好,显示消息框前要发声,例如,使用音效通知操作员
有错误发生了.
怎么办?一个办法是修改大量现有的代码,在MessageBox()之前插入Beep(1).另一种办法是定义同名的全局函数来重载系统的Mess
ageBox().作为有经验的程序员,你会问:"我怎样在这个函数里面调用系统的那个?PB会递归调用这个函数,陷入死循环,直到产生
栈溢出错误."下面是避免死循环的技巧:
global function integer messagebox (readonly string as_title, readonly string as_message)
systemfunctions lsf_PB
integer li_rc
beep(1)
lsf_PB = CREATE systemfunctions
li_rc = lsf_PB.MessageBox(as_title, as_message)
DESTROY lsf_PB
RETURN li_rc
你可能需要为使用到的所有参数类型重载此函数.如果计划重载若干系统函数,可以考虑声明一个SystemFunctions类型的全局变
量,在应用对象的Open事件里创建,Close事件里销毁.
警告:所描述的重载系统函数的方法只在PB5里有效.不幸的是,在PB6里会导致运行时错误;在后面的版本里甚至不能编译.
————————————————————————————————
菜单的秘密——工具栏动画图标
为了简化GUI开发,PB为每个菜单项提供了两个事件:Selected和Clicked.记住,菜单级的事件不是Windows自带的,它们是由PB产生
和触发的.实际上,Windows把所有消息发送给拥有菜单的窗口,然后PB把消息分派给合适的菜单项.
PB帮助: "Selected event occurs when the user highlights an item on the menu using the arrow keys or the mouse,
without choosing it to be executed." (当用户使用方向键或鼠标高亮菜单项但没有执行它时产生Selected事件)其实,用户把
鼠标放在工具栏图标上停留片刻,PB显示工具栏提示(PB将工具栏文本作为提示)时也会产生Selected事件.这项特性允许我们在Se
lected事件中编写代码,实现更改对应菜单项的工具栏图标,并在图标失去焦点时还原原始的图片.技巧在于区分该事件是在高亮
菜单项时产生的还是在显示工具栏提示时产生的.
照下面的做:
1.声明菜单的实例变量
menu im_last_selected
2.声明两个菜单函数:
public subroutine mf_select(menu am_menuitem)
public subroutine mf_unselect()
3.对每个拥有工具栏图标的菜单项,在Selected事件写上mf_select(this)
4.确保为每个拥有工具栏图标的菜单项指定了两个图标:Toolbar Picture Name和Toolbar Down Picture Name.两个图标应该有
些差异,这样用户才能看到动画效果.
在父窗口或通用的祖先窗口中声明事件WM_MENUSELECT,映射PBM_MENUSELECT,在事件中写:
if Handle(this.MenuID) = hmenu then this.MenuID.DYNAMIC mf_unselect()
下面是上述函数的代码:
public subroutine mf_unselect ()
if isValid(im_last_selected) then
if im_last_selected.tag <> "" then
im_last_selected.ToolBarItemName = im_last_selected.tag
end if
end if
public subroutine mf_select (menu am_menuitem)
// 首先找出Selected事件产生的原因:选择了菜单项还是工具栏提示
uint lui_flags, MF_HILITE = 128
lui_flags = IntHigh(Message.WordParm)
// 由于PB不支持lui_flags = lui_flags AND MF_HILITE这样的位操作
// 我们必须用另一种方法判断高亮标志位
lui_flags -= mod(lui_flags, MF_HILITE)
if mod(lui_flags, MF_HILITE * 2) > 0 then return // 选择了菜单项文本
if am_menuitem.ToolBarItemDown then return // 忽略处于按下状态的图标
if am_menuitem.tag = "" then
am_menuitem.tag = am_menuitem.ToolBarItemName
end if
im_last_selected = am_menuitem
am_menuitem.ToolBarItemName = am_menuitem.ToolBarItemDownName
注意本例中使用了菜单项的tag临时存储Picture Name.如果你的程序已经使用了tag,需要另外声明一个菜单实例变量来代替.
点击此处下载实现动画图标的PB6例程.
————————————————————————————————
Environment对象的秘密
PB6的Environment对象有一个未公开的属性Language,属于LanguageID枚举类型.这个对多语言应用程序有用.要得到可用的ID清
单,打开对象浏览器,选择Enumerated页面,在左边的面板里找到并选中LanguageID,在右边的面板里展开其属性.
————————————————————————————————
DataWindow的行选中颜色
函数SelectRow(long Row,boolean State)用于高亮DataWindow中的行.高亮前PB调用Windows API检索系统定义的活动选择颜色.
如果想知道选中的行会使用哪种颜色,可以调用API函数GetSysColor.下面是函数声明:
// GetSysColor函数检索指定显示元素的当前颜色
// 对于"活动选择"元素, COLOR_HIGHLIGHT = 13
FUNCTION long GetSysColor(long color_element) LIBRARY "user32"
对于16位的环境,color_element的类型改成integer,library改成"user".传递参数13来获取行选中颜色.
顺便提一下,像SelectRow()这样的某些函数可以接受非法的行号.例如,SelectRow(-1, FALSE)跟SelectRow(0,FALSE)的作用一样
,取消所有选中的行.
————————————————————————————————
DataStore实现的秘密
PB帮助:"A DataStore is a non-visual DataWindow control. DataStores act just like DataWindow controls except that
many of the visual properties associated with DataWindow controls do not apply to DataStores. However, because
you can print DataStores, PowerBuilder provides some events and functions for DataStores that pertain to the
visual presentation of the data. "
(DataStore是不可视的DataWindow控件.除了不具有许多可视的属性之外,DataStoreg跟DataWindow的行为类似.但由于可以打印D
ataStore,PB为DataStore提供了一些跟数据的可视展现相关的事件和函数)
既然DataStore实际上是一个隐藏的DataWindow控件,我不明白为什么PB文档说它是不可视对象.我们来证实一下:DataStore是普
通的DataWindow控件,用隐藏的弹出式窗口来实现的.需要两个外部函数:
FUNCTION boolean SetWindowPos( &
long hwnd, /* 窗口句柄 */
long hWndInsertAfter, /* 摆放顺序句柄 */
int x, /* 水平位置 */
int y, /* 垂直位置 */
int cx, /* 宽度 */
int cy, /* 高度 */
uint uFlag /* 定位标志 */ ) LIBRARY "user32"
FUNCTION ulong FindWindowA(REF string class, REF string name) LIBRARY "user32"
我们将使用SetWindowPos函数显示DataStore并改变其大小;最初它是隐藏起来的,尺寸为0.PB编译器很可能将DataStore作为一个
纯不可视对象,所以不允许我们直接得到其句柄.因此我们使用FindWindowA查找DataStore.为简单起见,这个函数我只调用一次.
它返回最先找到的DataStore的句柄.下面的代码演示怎样显示DataStore.注意不同的PB版本使用不同的类名创建内部使用的窗口
.PB5中DataStore和DataWindow的类名是PBDW050,在PB6中是PBDW60.
ulong ll_handle
string ls_class, ls_title
DataStore lds_test
ls_class = "PBDW050" // PBDW60 for PB6
// 创建测试用的DataStore
lds_test = CREATE datastore
lds_test.DataObject = "d_test"
// 获取DataStore的句柄
ll_handle = FindWindowA(ls_class, ls_title)
IF ll_handle = 0 THEN
beep(2)
MessageBox("Warning", "Not found!", Exclamation!)
RETURN
END IF
// 显示,调整尺寸
SetWindowPos(ll_handle, 0, 0, 0, 300, 300, 64)
MessageBox("DataStore", "Now you can see non-visual datastore!", Exclamation!)
DESTROY lds_test
PB5中的DataStore甚至可以变成可编辑的.怎么样? 哈哈!
也可以使用Windows SPY程序搜索DataStore.SPY程序通常是任何C++编译器包的标准组成部分.可以在PB企业版提供的Watcom C++
类编译器中找到一个.
通过调用API函数SetParent,可以将DataStore窗口转变成普通的DataWindow控件.细节参见API文档.
PB6的DataStore与以前版本相比有若干改进.其中一项——禁用DataStore绘制(也许应该说成DataWindow绘制?),显著提高了性能
,特别是进行多项数据操作时.
不明白为什么DataWindow不从DataStore继承? 这样不仅合乎逻辑,而且通过消除编写DataWindow和DataStore服务时不必要的重
复编码,能显著提升PB开发者的效率.
————————————————————————————————
DataWindow的秘密——最小化DataWindow控件
大家知道,DataWindow控件可以拥有标题栏(带有最小化、最大化按钮和含控制菜单的控制按钮).与普通窗口相反,用户最小化Dat
aWindow控件时,它完全消失了,而不是显示为一个图标.并不真是这样.PB捕获了Resize事件,将DataWindow隐藏了.用户使用控制
菜单关闭DataWindow时也是这样.要重新显示DataWindow,恢复其visible属性即可.
my_dw.visible = True
————————————————————————————————
PB资源文件(PBR)的秘密
PB提供的文档没有全部列出所支持的资源.对资源条目没有确切的定义.多数情况下我们看到类似这样的定义:
"Resource File Name - Specify a PowerBuilder resource file for the dynamic library if it uses resources, such as
bitmaps and icons, and you want the resources included in the dynamic library."
(资源文件名 - 为使用资源(位图,图标等)的动态库指定资源文件,如果希望资源包含在该动态库中)
据我所知,资源文件可以包含图象文件(bmp,rle,wmf,cur,ico,等等)和动态引用的对象(UserObject,Window,Menu和DataWindow)
的名字.编译成动态库(无论PBD还是DLL)时并不需要包含动态引用的对象.但是编译成单独的EXE时需要.在资源文件中指定对象的
格式是mylibrary.pbl(myobject),例如:reports.pbl(w_cash_balance).资源名不区分大小写.
————————————————————————————————
pb日期和2000年问题兼容性
很多公司正在确保其产品能兼容2000年问题.pb中将DataWindow的数据保存为文本文件时,通常是只包含两位年份的短日期格式.
有一种改变格式的办法,让日期保存时采用四位年份.pb在注册表中取日期格式.改变日期格式需要修改HKEY_CURRENT_USER/Contr
ol Panel/International下sShortDate的设置.那里也能找到短时间的格式.要让pb使用四位年份,只需将sShortDate的值改成任
何想让DataWindow保存的格式,然后还原旧格式.可以使用pb的注册表函数在程序中执行该任务.
————————————————————————————————
菜单的秘密——工具栏提示和文本
帮助中这样定义菜单项的ToolbarItemText属性:
"ToolbarItemText - Specifies the text that displays in the toolbar item when the display text option is on for
toolbars."
pb的工具栏提示也使用这个属性.你一定很希望提示长些而文本短些.有一个极简单而未公开的方法:在ToolbarItemText属性中,
使用逗号隔开图标文本和提示.如:"Excel,将报表保存为MS Excel格式."
————————————————————————————————
Table画板的秘密——Open Table对话框
要在Select Table对话框中迅速定位需要的表,可以直接敲入表名,pb会自动滚动到最近的匹配项.当表清单很长时,该特性很有用
.
————————————————————————————————
菜单的秘密——动态添加新菜单项
菜单的Item[]属性并不像许多人认为的那样是固定的数组.你完全可以向其中添加新元素.技巧在于要强制pb重画更新后的菜单.
下例演示了怎么做.
1.新建一个窗口,指定一个已有菜单.
2.放置一个按钮.
3.按钮的Clicked事件里写:
MenuID.Item[UpperBound(MenuID.Item[]) + 1] = CREATE menu
MenuID.Item[UpperBound(MenuID.Item[])].text = "&New Menu Item"
MenuID.Item[UpperBound(MenuID.Item[])].ToolBarItemName = "Save!"
MenuID.Item[UpperBound(MenuID.Item[])].ToolBarItemVisible = True
// 强制pb重画带有新增菜单项的菜单
Hide(MenuID.Item[1])
Show(MenuID.Item[1])
4.运行新窗口,单击按钮.
————————————————————————————————
最简单的统计TreeView项数的方法
使用下面的代码快速统计TreeView控件的项数:
li_count = Send(handle(treeview_control), 4357, 0, 0)
统计TreeView控件中完全可见的项数:
li_count = Send(handle(treeview_control), 4368, 0, 0)
————————————————————————————————
pb可执行文件的秘密
你是否知道,你用pb创建的任何程序都是Sybase公司的财产?真的,不是你所想的那样属于你.证据:
1. 打开资源管理器
2.找到你的EXE文件,右击.
3.选择属性菜单,转到版本属性页.
4.检查公司名和版权公告.
如果你强烈认为工作成果属于你而不是Sybase公司,可以使用C++程序包的资源编辑器修改EXE文件头.
不幸的是每次编译可执行文件时都必须这样修改.你或许知道,其他开发工具(例如VB)中,用户可以自定义EXE文件头(通过项目属
性),正确的信息会被编译到EXE中.
GetChild()的秘密
帮助对GetChild()提供如下定义:
Provides a reference to a child DataWindow or to a report in a composite DataWindow, which you can use in
DataWindow functions to manipulate that DataWindow or report.A child DataWindow is a DropDownDataWindow in a
DataWindow object. A report is a DataWindow that is part of a composite DataWindow.
(提供对子DataWindow或复合DataWindow中报表的引用,以便使用DataWindow函数操纵它们.子DataWindow指DataWindow对象中的
下拉DataWindow.报表指复合DataWindow中的DataWindow)
根据以上定义,调用GetChild()来获取tabular风格的DataWindow的嵌套报表会失败.因此,没有办法取得非复合DataWindow中嵌套
的事件窗口的引用.并非如此.要知道,除了Grid,所有的DataWindow风格是等同的.因此可以这样解决GetChild()问题:
1.导出Tabular、Freeform、Graph(或其他)风格的DataWindow
2.导出文件的第三行,"processing=0"(或其他)改成"processing=5"
3.导入
4.可以使用GetChild()了.
————————————————————————————————
DataWindow修复工具
本工具可以修复datawindow定义中非法的列ID.
设计期间(DataWindow画板),从一个datawindow复制列,粘贴到另一个datawindow中时,经常会产生非法的ID.当源datawindow和目
标datawindow列名相同而顺序不同,或者列数不等时,会产生这种错误.
点击此处下载DW_FIX.EXE.需要pb6的配置环境来运行.
————————————————————————————————
带菜单的响应式窗口
让响应式窗口带有菜单?这虽然不是标准的GUI,但是有时候会很便利.在open事件里使用ChangeMenu()给窗口指定一个菜单.
————————————————————————————————
不带菜单和工具栏的MDI框架
给MDI框架指定这样一个菜单:只有一个菜单项,而且是禁用和不可见的.
————————————————————————————————
动态DataWindow的秘密
大家知道可以使用SyntaxFromSQL根据SQL
SELECT语句生成DataWindow源代码,然后传递给Create函数来动态创建新的datawindow.帮助中说SyntaxFromSQL的参数必须是合
法的SQL SELECT语句.其实在pb6.0及以上版本中也可以使用EXEC <存储过程名><参数>,其中要把<存储过程名>替换为实际的存储
过程名称,<参数>替换为实际的参数值.例如可以将NULL作为每个参数的值.创建datawindow之后,可以使用Modify修正参数名.
————————————————————————————————
自定义工具栏——很简单的说
在响应式窗口上放一个工具栏? 或者想在MDI sheet窗口上放置第二个第三个工具栏?
虽然pb不直接支持该功能,但有时候会很便利.而且很简单,便于移植.我是说你的窗口、代码、菜单和工具栏稍做改动即可重用.
在这里下载例程.
————————————————————————————————
datawindow导出到Excel(包含计算域、表头、脚注、分组、文本...)
你可能已经知道,SaveAs函数可以将datawindow的内容保存为MS Excel格式.但是....不幸的是,它只保存原始数据,遗漏了计算域
、格式、分组表头和脚注.很少有人对此有解决办法.不过,办法很简单:
1.datawindow另存为HTMLTable!格式.
2.使用OLE连接Excel,将HTML文件转换成Excel格式.
本方法对于grid风格的报表和其他风格的datawindow工作良好.它跟datawindow转换为html的效果一样好.
在这里查看代码.
————————————————————————————————
PB中的异步处理
本文有助于创建需要异步调用函数的pb应用.一个例子是执行存储过程时不希望程序出于锁定状态.点击此处下载zip文件,内含文
章和可用于你的程序的例程.
————————————————————————————————
另一个工具栏技巧
让MDI框架和MDI sheet共用一个工具栏,最简单有效的方法是给它们相同的名字.可以在应用对象的open事件中写:
this.ToolBarFrameTitle = "Toolbar"
this.ToolBarSheetTitle = "Toolbar"
————————————————————————————————
pb应用程序之间交换信息
该技巧用于需要从一个程序中触发另一个程序的事件时.
基本上,这个技巧是关于Send()函数的.参数:
handle:目标应用的句柄
#message:1023 + XX,其中XX消息pbm_customXX的数字
longword: 可选的long型参数
long: 可选long型参数,此时不能将string作为long
点击此处下载zip文件,里面包含的两个应用演示了该技巧:源应用发送消息,目标应用接收消息.版本:pb6.5
————————————————————————————————
SQL异常处理
该技巧演示了怎样捕获处理SQL错误.
该技巧以其他语言(比如Delphi,C++或者Java)中的异常处理方法为基础.pb8也有了异常处理,但是,迁移到pb8的时候....
该方法可用于所有pb版本(我希望).
点击此处下载zip文件,内含源代码完整的例程(pb6.5).
————————————————————————————————
window my_window
SetNull(my_window)
isValid(my_window) -->如你所料,返回False
到现在为止, 一直都还不错....现在,看看datawindow事件中的dwo对象.考虑这样一种情况:在datawindow的clicked事件中有代
码,我们单击了datawindow,但不在任何对象上.
isValid(dwo) -->出乎意料,返回True
isNull(dow) -->返回True
惊奇吗?bug还是特性?
注意:原先的GetObjectAtPointer()工作正常,同时GetClickedColumn()和GetRow()也比这些事件参数可靠得多.
————————————————————————————————
Windows API库
该库文件包含了大多数Windows API函数、结构和常量的声明,可以直接复制粘贴.你可以找到一切,从处理标准控件需要的函数声
明到Winsock接口.帮一下自己,下载吧.如果你今天不需要它,你明天会需要.
————————————————————————————————
访问TopSpeed数据库
<这个——是什么东东哦? 不管了,收工....>
第 4 楼
文中附带例程打包下载:
点击浏览该文件
第 5 楼
第 6 楼
呵呵,厉害,谢谢
象你的声音 自远而近 我是分外入神
逝去的光阴 又在重温 故事段段动人
难忘是当天你 在无风的秋季
别去的一刹 留低的一切
但这一封信 无声的飘到
象往昔一切 回忆的洗礼
这感觉是最珍贵
第 7 楼
12.性能测试:datastore vs datawindow 在单独一个网页里(http://www.softtreetech.com/hightech/ds_vs_dw.htm),得出的结论是禁止重画的datawindow要快于datastore.
第 8 楼
测试了一下,如果是检索的话,那么还是DATASTORE比较快点
Borland传奇改变了我,向不世出的Anders Hejlsberg和首席科学家Blake Stone学习
第 9 楼
第 10 楼
QQ