PB中很实用的小技巧.docx
《PB中很实用的小技巧.docx》由会员分享,可在线阅读,更多相关《PB中很实用的小技巧.docx(18页珍藏版)》请在冰豆网上搜索。
![PB中很实用的小技巧.docx](https://file1.bdocx.com/fileroot1/2022-11/27/046085f5-15ee-4eba-91cf-53696c35f576/046085f5-15ee-4eba-91cf-53696c35f5761.gif)
PB中很实用的小技巧
1.RGB函数计算公式:
颜色值=(65536*Blue)+(256*Green)+(Red)
2.控件可拖动:
send(handle(this),274,61458,0)
3.如何用程序控制下拉子数据窗口的下拉和收起
用modify或者直接用dw_1.object.col1.dddw.showlist=true
4.检索参数有些不需要传入则传%.
5.如何屏蔽鼠标滚轮触发
在控件的other事件写
ifmessage.number=522thenreturn1
6.得到数据窗口的语法:
stringls_dwsyntax
ls_dwsyntax=dw_1.describe("datawindow.syntax")
7.得到数据窗口中各列及标题:
longll_count,i
stringls_value,ls_colname
ll_colnum=Long(dw_1.object.datawindow.column.count)
fori=1toll_colnum
//得到标题头的名字
ls_colname=dw_1.describe('#'+string(i)+".name")+"_t"
ls_value=dw_1.describe(ls_colname+".text")
next
8.在程序中动态设置初始值:
ex:
dw_contro.object.columnName.initial='xxxx'
9.如何在DataWindow的SQL语法中不使用SELECTDISTINCT实现删除重复的行
----起先对你要显示唯一值的列进行排序:
"cityA",然后增加如下过滤字符串:
"city<>city[-1]orGetRow()=1"
10.如何改变列的字体颜色,提醒用户此列已做修改
----在列的Color属性中,输入如下表达式IF(column_name<>column_name.Original,RGB(255,0,0),RGB(0,0,0))。
在这个条件中,如果此列已改变,则显示红色字体,否则显示黑色字体。
这个表达式主要用column_name<>column_name.Original比较当前列的值和原始列的值是否相同来达到判断的目的。
11.在数据窗口的clicked或doubleclicked事件中写上注释//可解决一些意外的bug!
12.如何屏蔽上下鍵触发
新建一个事件:
id为pbm_dwnkey
IFKeyDown(KeyDownArrow!
)ORKeyDown(KeyUpArrow!
)Then
Return1
EndIF
13.你注意到没有,数据窗口画板里面,在写表达式的时候,试着用一些用户自定义的全局变量和全局函数,你会发现在某些特殊的场合,这个小窍门还是很有用的。
14.有些程序员在窗口的右键pop菜单里面写了很多代码,在菜单里面有很多w_windowname.controlname等等引用,如果这个窗口被继承,很容易就会出毛病,别忘了在菜单里面可以引用parentwindow哦,有了它我的pop菜单里面的代码和具体窗口无关,随便继承。
当然强烈建议最好还是把所有和窗口相关的逻辑都转移到窗口的函数和事件中去,在pop菜单中触发调用。
15.whichdw.describe("evaluate('lookupdisplay("+colname+")',"+string(row)+")")
这个表达式可以得到指定列的显示值。
(这个知识点有滥竽充数之嫌,但是一时间我真是想不起来太多的东西)
16.在数据窗口画板里面我们如果想要比较当前行和上一行或者下一行的值,怎么比较呢,哈哈,看这个就知道了
if(yw_bc_circuit_dlcode=yw_bc_circuit_dlcode[-1]andyw_bc_circuit_dlname=yw_bc_circuit_dlname[-1]andyw_bc_circuit_xtno=yw_bc_circuit_xtno[-1],0,1)
这个表达式就是比较当前行和上一行是否相同的。
其他的依此类推就行了。
17.两个结构相同的数据窗口之间快速复制数据
dw_1.object.data=dw_2.object.data
18.根据条件改变记录颜色
if(Mod(getrow(),2)=0,rgb(0,255,255),rgb(255,255,255))//奇偶行不同色
if(currentRow()=getrow(),rgb(0,255,255),rgb(255,255,255))//当前行不同色
19.使窗口总位于所有打开窗口的最上面
w_main.SetPosition(Topmost!
)
20.取数据窗口中列的总数
stringls_count
ls_count=dw_1.describe("datawindow.column.count")
21.取数据窗口中可列新的表名。
stringls_table
ls_table=dw_1.describe("datawindow.updatetable.table")
22.取数据窗口对象中列的名称及类型
stringls_cols[],ls_types[]
intli_count,i
li_count=integer(ls_count)
fori=1toli_count
ls_cols[i]=dw_1.describe("#"+string(i)+".name")
ls_types[i]=dw_1.describe("#"+string(i)+".coltype")
next
23.Case(dealintypeWHEN0THENRGB(254,251,235)WHEN2THENrgb(254,251,235)ELSERGB(0,0,255))
写道字段的protect中不仅仅是颜色改变的问题看看
24.dw.Object.col[n]:
直接获得数据窗口的col列第n行的数据。
25.在做数据窗口时,我们有时候希望能够多一些字段来作一些特殊的用处,但是在数据窗口中又不能乱加字段,因为已有的字段必须是数据库中有的或者是他们的组合,呵呵,大家不妨看看这个sql用产生什么样的数据窗口
selectcolname1,colname2,1,''
fromtablename
是不是多出了两个字段阿,一个是字符串字段,一个是数字字段
别忘了要convertsyntax哦
26.清空数组
stringa[],b[]
a[1]='1';a[1]='2';a[1]='3'
a=b//即可以清空a
27.只允许修改第n行的name列:
dw_1.modify("name.protect='1~tif((getrow()=n),0,1)'")
28.让run程序和主程序一起关闭:
functionulongfindwindowA(...).."user32.dll"
functionlongsetparent(..."user32.dll"
handle=findwindowA(nul,win_title)
setparent(handle,handle(w_main))
29.取得某一天以前或以后n天的函数RelativeDate(date,n)
例:
取得当天前10天的日期
RelativeDate(Today(),10)
取得当天后10天的日期
RelativeDate(Today(),-10)
30.不想做排序窗口?
调用PB自身的好了。
stringls_null
SetNull(ls_null)
dw_1.SetSort(ls_null)
dw_1.Sort()
31.调用PB自身的过滤窗口:
dw_1.SetFilter(ls_null)
dw_1.Filter()
32.增量输入定位代码或名称记录位置:
定义一个窗口,放一个SLE_1,在它的MODIFY程序中写:
longll_find
stringvalue0
value0=sle_1.text
ifnot(isnull(sle_1.text)orsle_1.text='')then
ifleft(sle_1.text,1)='0'orinteger(sle_1.text)<>0then//输入的为代码
ll_find=jwl_dmxz.dw_1.find('dmlike"'+value0+'%"',1,jwl_dmxz.dw_1.rowcount())//jwl_dmxz为主窗口,dm为查询的字段名,这里是代码。
else//输入的为名称
ll_find=jwl_dmxz.dw_1.find('mclike"'+value0+'%"',1,jwl_dmxz.dw_1.rowcount())//
endif
ifll_find>0then
jwl_dmxz.dw_1.scrolltorow(ll_find)
//为了避免首次目标记录为第一条,无法选中。
ifll_find=ll_find0then
jwl_dmxz.dw_1.selectrow(ll_find,true)
elseifll_find<>ll_find0then
jwl_dmxz.dw_1.selectrow(ll_find,true)
jwl_dmxz.dw_1.selectrow(ll_find0,false)
ll_find0=ll_find
endif
endif
endif
33.然后在查询窗口中的TIMER事件中写:
timer(0.05)
sle_1.triggerevent(modified!
)
34.判断计算器是否存在:
stringis_fileExists
booleanis_Exists
is_fileExists='c:
\windows\calc.exe'
is_Exists=fileExists(is_fileExists)
ifis_Existsthen
run("c:
\windows\calc.exe")
else
messagebox("提示信息","本机的WINDOWS没有计算器!
",stopsign!
)
endif
35.得到硬盘序例号
Stringls_Rootpath,ls_volumnename,ls_return,softpath
GetCurrentDirectoryA(256,softpath)
softpath=left(softpath,2)
ifsoftpath='C:
'then
ls_Rootpath='D:
'//指定要得到序列号的硬盘,
//一般情况都是C盘,除非你能保证用户存在其它逻辑盘或物理盘
else
ls_Rootpath='C:
'
endif
ls_volumnename=Space(256)//分配足够的空间,下同
Ulonglul_VolumeNameSize
lul_VolumeNameSize=256
Ulonglul_VolumeSerialNumber,lul_MaximumComponentLength,lul_FileSystemFlags
lul_MaximumComponentLength=256
Stringls_FileSystemNameBuffer
ls_FileSystemNameBuffer=space(256)
Ulonglul_FileSystemNameSize
lul_FileSystemNameSize=256
inti
longls_num,ls_gnum,ls_dnum
i=GetVolumeInformation(ls_Rootpath,ls_volumnename,lul_VolumeNameSize,lul_VolumeSerialNumber,lul_MaximumComponentLength,lul_FileSystemFlags,ls_FileSystemNameBuffer,lul_FileSystemNameSize)
ls_return=string(lul_VolumeSerialNumber)
returnls_return
1.pb9应用xp风格
将PB9升级到7119后,编译时有一个NewVisualStyleControls选项,选中后,编译出来的文件在XP下就可以应用XP风格了
2.Yield()函数的作用
Yield()是一个不常用到的PowerBuilder函数。
可是,在一个大的循环过程中,如果用户想在执行到一半时通过单击按钮或菜单来退出的话,就一定要用到Yield()函数了,否则程序只会在执行完成整个循环后才会响应按钮或菜单的Click事件。
将Yield()函数放在循环体的中间。
那么在循环执行的过程中发现有新的事件消息在消息队列中就回立即去响应。
Yield()
功能将控制权转移给其它图形对象,包括非PowerBuilder对象。
该函数检测消息队列,如果有消息,就把消息取出。
利用该函数可以在执行耗时较长的操作时把控制权转让给其它应用。
语法Yield()
返回值Boolean。
如果在消息队列中提取到了消息,那么函数返回TRUE,否则返回FALSE。
用法正常情况下,PowerBuilder应用程序在执行一段代码(比如函数或事件处理程序)的过程中不响应用户的操作。
对耗时短暂的代码段来说,这种处理方式没有什么不妥的地方,但是,如果某个代码段的执行耗时较长,应用程序又希望为用户提供更多的控制权,那么需要在这段代码中插入Yield()函数,让用户能够进行其它操作,特别在循环执行的代码中更应该如此。
应用程序执行Yield()函数后,如果发现消息队列中存在消息,它将允许对象处理这些消息,处理之后,继续Yield()函数后面代码的执行。
因此,代码中插入Yield()函数将降低应用程序的运行效率。
3.sqlca.SQLCode与update()
在利用EmbeddedSQL的时候,每运行一次SQL指令就应该检查一次交易对象中的属性SQLCode,而不是等到
所有的SQL指令运行完毕后再去运行检查交易对象中的SQLCode属性.当我们使用数据窗口所提供的函数时,
要记住不要检查SQLCode来判断是否运行成功.而是要依照每一个函数运行后所返回的值来判断是否运行
成功.
updatetab_testsetcol1='test'
ifsqlca.sqlCode=-1then
rollbackusingsqlca;
ifsqlca.sqlCode=-1then
messageBox('错误','连接失败!
')
endif
messageBox('错误','连接失败!
')
else
commitusingsqlca;
endif
//确保数据保存的成功
ifdw_1.update()=-1then
RollBackUsingSQLCA;
MessageBox("警告!
","数据保存失败!
")
else
CommitUsingSQLCA;
Endif
4.读取网页内容:
sle_1.text=ole_1.object.Document.body.outertext
ole_1.object.Document.body.scroll="no"
mle_1.text=ole_1.object.document.body.outerhtml
5.tab_1.createondemand在需要时创建:
tab_1.createondemand:
在需要时创建。
提高在open事件时的效率,tab_1的某一tabpage里的内容在open时不创建,仅当选择该页时或selecttab才创建,不过,在未创建时,不能对其中的控件及属性引用。
6.如何在程序中对BLOB数据库进行写入
和后台数据库有关:
以SQLANYWAY为例:
一般用UPDATEBLOB和SELECTBLOB 两个SQL语句来实现。
建一个表TABLE1,一个字段是ID,另一个是BLOB,
SELECTBLOBBLOBFROMTABLE1WHEREID='xx';
UPDATEBLOBSETBLOB=:
BLB_XFROMTABLE1WHEREID='yy';
删除时删除ID为'mm'的记录即可,新增是先插入一条ID为'mm'的记录,然后用UPDATEBLOB将数据写入
表内。
其他的数据库可参照手册进行,其命令与上述差别不大!
7.API、系统消息及其它dll调用
1.控件可拖动:
send(handle(this),274,61458,0)
2.如何屏蔽鼠标滚轮触发
在控件的other事件写
ifmessage.number=522thenreturn1
3.隐藏任务栏的方法,
在OnCreate事件里利用WindowAPI函数SetWindowLong:
SetWindowLong(Application.Handle,GWL_EXSTYLE,WS_EX_TOOLWINDOW);
PB使用时首先声明函数FUNCTIONlongSetWindowLong(ulonghWnd,integernIndex,ulongdwNewLong)library"user32.dll"ALIASFOR"SetWindowLongA",
然后调用:
SetWindowLong(Handle(this),-20,128);
4.在PB中调用屏幕保护的方法:
send(handle(This),274,61760,0)
5.得到一个应用程序如Outlook的路径
RegistryGet("HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionAppPathsMSIMN.EXE",&
"Path",ls_outlook_path)
//Outlook的路径将保存在string型变量ls_outlook_path中。
6.得到程序运行时的路径
//在globalexternalfunctions声明:
FunctionuLongGetModuleFileNameA(longhinstModule,RefStringlpszPath,uLongcchPath)Library″kernel32.dll″
//程序路径保存在变量ls_AppPath中
stringls_AppPath
intli_ret
ls_AppPath=Space(128)
li_ret=GetModuleFileNameA(Handle(GetApplication()),ls_apppath,128)
//要编译成可执行文件.exe才可用,否则得到的是Powerbuilder的pb60.exe或PB050.exe的路径。
7.屏蔽窗口的ALT+F4键
//方法一:
1.在窗口的systemkey事件中增加以下代码:
IFKeyDown(KeyF4!
)THEN
Message.Processed=TRUE
ENDIF
2.在窗口的closequery事件中增加如下代码:
Longll_ret
IFKeyDown(keyF4!
)THEN
ll_ret=1
ENDIF
returnll_ret
//方法二:
建一实例变量,在你的关闭程序上赋一个True然后在closequery中判断该值,如为False则Return1
8.当程序中用到了动态加入的对象,如BMP资源文件、数据窗口对象,PB编译时是扫描不到的,解决方法:
1.将此对象写入到资源文件中:
用记事本创建资源文件dw_object.pbr,写入:
c:
myprogram.pbl(dw_sj)
编译时将此文件选入ResourceFileName处。
2.将应用编译成PBD、DLL文件。
9.如何在PB中实现延时:
subroutineSleep(longdwMilliseconds)library"kernel32.dll"
延时1秒则调用:
Sleep(1000)//单位是毫秒。
10.调用API函数步骤:
1、在适当的位置声明函数,如窗口内,Application内,UserObject内,
定义在LocalExternalFunction或GlobalExternalFunction中,如播放声音的:
FunctionbooleansndPlaySoundA(stringSoundName,uintFlags)Library"WINMM.DLL"
FunctionuintwaveOutGetNumDevs()Library"WINMM.DLL"
也可以创建一个UserObject,集中声明常用的API及函数本地化,如定义用户对象u_external_function:
DeclareLocalExternalFunction(定义外部函数):
FunctionbooleansndPlaySoundA(stringSoundName,uintFlags)Library"WINMM.DLL"
FunctionuintwaveOutGetNumDevs()Library"WINMM.DLL"
DeclareUserObjectFunction(定义用户对象函数):
uf_play_sound(stringas_wave_name,integerai_option)
函数内容如下:
//参数:
as_wave_name:
wav文件名ai_option:
同步或异步(1/0)
uintlui_numdevs
lui_numdevs=WaveOutGetNumDevs()
Iflui_numdevs>0Then
sndPlaySoundA(as_wave_name,ai_option)
return1
Else
return-1
EndIf
2、调用时在程序中定义一个实体并调用其函数:
u_external_functioniu_external_function
iu_external_function=createu_external_function
iu_external_function.uf_play_sound('c:
windowsmediading.wav',1)
试试看,如果有声卡,就会听到"叮”的一声。
其它API函数也是如此处理。
11.显示一个与Windows操作系统风格一致的About对话框。
首先声明如下外部函数:
functionintShellAboutA(ulongal_hWnd,stringas_szApp