分享
 
 
 

编程爱好者电子杂志 2001年第三期

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

编程爱好者电子杂志 2001年第三期

出版日期: 2001年6月10日

欢迎光临编程爱好者网站: http://www.programfan.com

http://www.pfan.net

杂志网站】【编辑信箱】【提问信箱】【过刊查询】【杂志订退

本 期 内 容

在“状态区”中建立图标

Winsock编程框架

VB下Add-Ins的编程

浅谈PB中动态DataWindow的技术应用

用PowerBuilder制作指示灯

得到CPU速度,单位MHz

用API函数Mcisendstring直接播放背景音乐

给MDI主窗口加背景

编程爱好者网站最新更动

编程爱好者网站自6月1日开始启用新的域名 http://www.programfan.com 本站将以全新的面貌来欢迎每一位编程爱好者的到来。

本站的建设离不开广大的编程爱好者的帮助,新版的网站将更侧重于互动交流,能为广大的编程爱好者提供资料解决问题是本站的目标。

本站尚有很多栏目尚在改版中,如果有不能访问的栏目的话,敬请等待一两天。

网站本周最新更动

本周更新文章70篇,下面是最新加入的文章

利用VFP的Filer管理磁盘文件 2001-6-10

下载和上载远程视图数据 2001-6-10

避免浮点操作的四舍五入错误 2001-6-10

两台机器间传输文件的函数 2001-6-10

测字符串长度函数 2001-6-10

不用图像组件的ASP图像计数器 2001-6-10

对于HOOK函数的一点认识 2001-6-10

如何制作PB安装程序 2001-6-10

让硬盘休眠-ParkDisk程序 2001-6-9

常用文件目录操作 2001-6-9

实现远程屏幕抓取 2001-6-9

监视Pop3信箱 2001-6-9

实现高速文件拷贝 2001-6-9

简单的文件解码单元 2001-6-9

得到CPU速度,单位MHz 2001-6-9

用PB开发多媒体数据库管理系统 2001-6-9

得到文件的版本信息程序 2001-6-9

Delphi中调用NetscapeNavigator 2001-6-8

在“状态区”中建立图标

Win95中如“音量”、“日期”、“屏幕”等可以在Win95的状态栏(Tray)上建立快捷图标。如果鼠标停留在图标上,会显示出相应的工具提示(ToolTip),当用户在图标上单击(或双击)鼠标左键时,软件会实现相应的功能,单击右键时会实现其简捷的功能。

Tray也称作SysTray、TrayIcon、NotifyIcon、Status Area等,它是Win95/NT的任务条上一个特殊区域,许多软件运行时在Tray中加入自己的图标,这个区域的另一个特殊之处在于你可以从资源管理器内拖文件然后放在这个区域。正是由于这些特性,Tray编程在Win95/NT中有特殊的地位。

Tray编程比较特殊,主要包括三个主要方面:图标、工具提示和消息。它属于Shell编程的一部分,主要是利用Shell API中的Shell_NotifyIcon函数完成的。Shell_NotifyIcon函数是这样声明的:

Type NOTIFYICONDATA

cbSize As Long 结构所占的字节数

hwnd As Long 接受TRAY托盘图标消息的窗口句柄

uID As Long 由应用程序定义的图标识别符

uFlags As Long 标志

uCallbackMessage As Long 由应用程序定义的消息

hIcon As Long TRAY图标句柄

szTip As String * 64 工具提示字符串

End Type

Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias " Shell_NotifyIconA" (ByVal dwMessage As Long,

lpData As NOTIFYICONDATA) As Long

这个结构中的uFlags很重要,它有三种取值:NIF_ICON、NIF_MESSAGE和NIF_TIP,分别表示

hIcon、uCallbackMessage和szTip参数有效,用来修改图标、消息和工具提示。这三个取值可以同时使用(三个参数相或),也可以单独使用。为了实现对用户鼠标操作的响应,需要在程序中处理uCallbackMessage所定义的消息,该消息的长参数lParam包含Win32所定义的鼠标消息,如果有多个图标,短参数wParam表示图标识别符。

在vb光盘中\TOOLS\UNSUPPRT\SYSTRAY目录下有SYSTRAY的工程,经编译后生成SYSTRAY.OCX控件。

现在我们应用SYSTRAY.OCX控件进行Tray编程。

首先建立一个“工程”,依次:“工程”——“部件”(或者在“工具箱”上单击鼠标右键选择“部件”),再复选SYSTEM TRAY CONTROL CSYSTRAY,CSYSTRAY控件即出现在“工具箱”中。

SYSTRAY.OCX控件拥有MouseDblClick、MouseDown、MouseMove、MouseUp四个事件,响应先

后为MouseMove、MouseDown、MouseUp、MouseDblClick。下面编程很清楚地说明他们的响应时间次序。

Private Sub cSysTray1_MouseDblClick(Button As Integer, Id As Long)

MsgBox "Hei!You have DblClick the mouse!"

End Sub

Private Sub cSysTray1_MouseDown(Button As Integer, Id As Long)

If Button = 2 Then

MsgBox "Hei!You have clicked me in right button!"

End If

End Sub

Private Sub cSysTray1_MouseMove(Id As Long)

MsgBox "Hello!I am here!"

End Sub

Private Sub cSysTray1_MouseUp(Button As Integer, Id As Long)

MsgBox "Hei!You clicked me just now!"

End Sub

Private Sub Form_Load()

cSysTray1.TrayTip = "Hello! I am the King of the world!"

cSysTray1.InTray = True

cSysTray1.TrayIcon = "c:\fittings\FACE.ico"

End Sub

SYSTRAY控件还拥有InTray、Name、TrayIcon、TrayTip、Parent、Index、Object、Tag属性。InTray设置是否在Win95的状态栏Tray上建立一个快捷图标;Name设置SYSTRAY控件的名称;TrayIcon设置在Tray上所建立快捷图标的外观;TrayTip设置如果鼠标停留在图标上所显示的工具提示(ToolTip)内容;Tag储存程序所需要的附加数据。

通过实践发现,在使用VB开发应用程序时,灵活使用API 函数,会更大地发挥VB 的作用,使开

发的软件更专业,功能更强大。本文仅仅是介绍了一下API函数在Win95中的使用方法,以作抛砖引玉之用。真正的应用API 函数,还需要更详尽的资料和读者更大的努力。

上述程序在中文Windows 98和 VB5.0中文企业版下调试通过。

回到目录

Winsock编程框架

米乐

Microsoft的Windows Sockets API是Windows下的网络应用程序接口,为了适用于

Windows下的消息机制和异步的I/O选择操作,Windows Sockets API在功能上扩充了将近

20个函数,其中扩充的部分均冠以前缀WSA(Windows Sockets Asynchronous),如

WSAStartup、WSAClean等,充分体现了Widnows的优越性。此外,Windows Sockets API有

16位版和32位版两种,16位版是单进程的,32位版则提供了多线程下的安全保护。

Microsoft Visual Basic提供了用于Windows Sockets编程的可用控件——Winsock控

件。该控件为用户提供了访问TCP和UDP网络的极其方便的途径。并且适用于Microsoft

Access、Visual Basic、Visual C++和Visual FoxPro等多种可视化环境。通过Winsock

控件编制C/S程序,程序员无须了解TCP或低级Winsock APIs调用实现的细节,如用户无

须考虑网络字节顺序与本机字接顺序便可直接进行数据的传送。用该控件实现网间进程通信

极其方便。

在TCP应用中,为了建立一个网络连接实例(Instance)的服务器端,只需设置本地服

务端口号,然后服务器调用方法Listen进入阻塞状态,等待来自客户的连接请求。与此对

应的客户端不但要将Winsock的属性RemoteHost置为服务器的名称(IP地址或网络代号),

还应设置服务器所监听的相应服务的端口号(RemotePort),如FTP服务在21号端口,HTTP

在81号端口等。然后调用方法Winsock.Connect向服务器发出请求。服务器接收到客户请

求时,事件ConnectionRequest将被触发。如服务器愿意提供服务,则可调用Accept方法

接受连接。

一旦连接建立,两端均可使用SendData或GetData进行数据的发送或接收。事件

DataArrival将在另一端数据准备就绪时被触发。

UDP协议的实现与TCP不同的是,调用Sockets的两端无需建立连接便可进行数据的传

输。因此,一个UDP应用可以同时担任服务器或客户的角色。

以下程序代码为Visual Basic Windows Sockets编程的基本框架。

注释:服务器方

Private Sub Command1.Click()

注释:设置本地服务端口号

Winsock1.localport=2048

注释:服务器进入监听状态

Winsock1.listen

End Sub

Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)

注释:收到客户连接请求

注释:检查Socket状态

If Winsock1.State <> sckClosed Then Winsock1.Close

注释:接受客户请求

Winsock1.Accept requestID

End Sub

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)

注释:对方数据已准备好

注释:可用GetData()/SendData()接收/发送数据

注释:处理客户数据

……

End Sub

Private Sub Form_Unload(Cancel As Integer)

Winsock1.Close

End Sub

注释:客户方

Private Sub Command1.Click()

注释:设置服务器网络名

Winsock1.RemoteHost=“193.168.1.40”

注释:设置服务器相应服务端口号

Winsock1.RemotePort=2048

注释:向服务器发出连接请求

Winsock1.Connect

End Sub

Private Sub Winsock1_Connect()

注释:服务器响应连接

注释:可以进行GetData()/SendData()进行数据传输

……

End Sub

Private Sub Form1.Unload()

Winsock1.Close

End Sub

该段程序演示了用Visual Basic建立TCP连接的基本过程。因本文重在讲解Sockets

编程,故文中未涉及VB自己封装的故障处理函数Winsock1.Erroe(),读者可自行编制。以

上程序段可作为一般TCP应用的基本框架加以扩展使用。

Microsoft Visual C++实现过程与前述的VB实现类同。具体实例可见Microsoft

Visual C++ Samples中的chatsrv与chater程序。

随着Internet的逐步兴起,Sockets编程必将成为流行的网络编程接口之一。也许您

会发问:ISO的OSI模型又是何等地位呢?笔者的观点是:ISO的OSI模型必将成为网络应

用的统一界面,Sockets接口的广泛应用则为OSI模型开拓了更广泛的应用前景!

回到目录

VB下Add-Ins的编程

华工 姜新 汪秉文

摘要 :本文从一个具体例子出发阐述了在Visual Basic 5.0环境下进行外接程序(Add-Ins)开发的原理、关键技术和注意事项,并对其相关技术,如ActiveX、多态性与接口、事件变量等VB5新引进的编程概念也做了必要的分析和描述。

关键词:外接程序(Add-Ins),ActiveX,接口,多态,事件变量

一、 概述

Visual Basic下的Add-Ins,即外接程序,是扩展VB编程环境的非常有用的工具。作为一个开发者,我们发现在使用Visual Basic集成开发环境(IDE)时经常需要重复地干同一件简单的工作,如设置所有或一类控件的字体,前景及背景颜色,改变控件的Tab次序等。这些简单、单调而重复性的劳动如果由程序自动完成,将变得非常方便,而Add-Ins正为实现这一功能提供了可能。与Visual Basic的早期版本不同,Visual Basic5.0下的Add-Ins是一种模块化的ActiveX部件,可以作为ActiveX DLL或EXE文件进行编译。另外,跟以前的版本相比,VB5下Add-Ins无论从编程思想还是从其扩展模型的对象与结构来说,变化都比较大,因此VB5下编写Add-Ins程序与早期版本将会有很大不同。在这篇文章中,我们将从一个具体例子出发,阐述VB5下Add-Ins的编程。

二、 问题的提出

在Visual Basic下进行窗体设计时,我们一般希望自己的程序具有风格一致的界面,如同类控件具有相同的外观、相同的字体等。另外,我们在设计时还应该考虑到屏幕分辨率的变化对程序的影响,例如我们经常发现出现这样的问题:即在某一分辨率(如800*600)下看起来比较好的字体,当在另一分辨率下(如640*480)运行时将变得非常难看;或者在中文环境下看起来比较舒服,但在英文环境下却很不清晰。这种种原因都使得我们必须调整窗体控件的字体,以达到最佳效果。但如果表单或控件比较多时,手工调整将会非常繁琐,而且容易出错,因此编写一个Add-Ins以实现字体的自动调整将会非常实用。本文中的例子即是用来实现此功能的。

三、 编程方法

编写Add-Ins的最简单方法是首先利用VB5的编程模板生成一个Add-Ins的框架,然后在此框架上进一步实现自己的代码。具体方法是在VB5的“文件”菜单下选择“新建工程”,然后在弹出的窗口中选择“外接程序”(英文版中是“Add-Ins”)即可。这时VB5将生成一个名为MyAddin的工程,该工程中包括一个窗体frm AddIn,一个模块AddIn,以及一个类模块Connect。下面我们对这些部分分别做一简单分析。

1. 类模块Connect

整个类模块Connect的代码均是由模板自动生成的,大大方便了程序员编程,但其源代码中有一些比较重要的概念与方法,对我们理解VB Add-Ins甚至VB面向对象编程均有很大好处。下面我们对如下几点做一简单介绍(源代码由于是VB自动产生,这里就没有列出了)。

(1)实现IDTExtensibility接口

所有的VB外接程序都必须实现IDTExtensibility接口,该接口包含了当外接程序与Visual Basic连接时Visual Basic调用的一些方法,无论是通过外接程序管理器,还是其它一些手段。接口是VB5引入的新概念,是Visual Basic提供多态性的一种重要手段。我们知道,面向对象的语言一般都提供多态性。如C++语言,通过类的继承关系,子类重载父类的方法以实现其不同的特性,或父类仅提供方法框架,即无函数体的虚函数,而子类具体实现其代码。简单地说,多态意味着许多类可以提供同样的属性或者方法,而且调用者在调用这些属性或方法之前,不必知道某个对象属于什么类。严格来说,Visual Basic不是完整意义上的面向对象编程语言,但它也能实现多态性,不过这种多态性不是通过继承来实现的,而是通过多重ActiveX接口来提供的。多态性具体实现方法简单来说,首先是建立一个类模块,然后在该模块中声明一些子程序(Sub),但不实现其代码,这样该类模块可以说是一个抽象类,也即接口;然后建立其它的类模块,在这些类模块的声明部分中,使用Implements语句表明该类实现了上述接口,接下来就可以实现接口代码(也即接口的方法)了。这种用Implements语句的方法可以说与Java语言比较相似。至于这方面的详细信息,可参看VB的帮助或联机手册。

在类模块Connect中,使用Implements IDTExtensibility语句声明该类实现了IDTExtensibility接口。因此类模块Connect中实现了该接口包括的四个方法:OnAddInsUpdate,OnConnection,OnDisconnection,OnStartupComplete的代码,例如一条语句、过程调用、注释等等。如果过程是空的话,它会被编译器删掉。如果实在没有代码可往这些过程里加的话,就插入注释。这是因为既然实现了接口,就必须提供接口的所有方法的代码。这四种方法中,比较关键的是OnConnection和OnDisconnection方法,其中OnConnection方法当一个外接程序通过“外接程序管理器”对话框或另一个个接程序与Visual BasicIDE连接时被调用。我们一般在该方法中保存当前Visual Basic会话期实例,挂接VB菜单,工具栏,或显示初始窗口,以便用户使用该外接程序。而OnDisconnection方法当外接程序通过编程或“外接程序管理器”对话框与Visual BasicIDE分离时被调用。我们一般在该方法中卸掉菜单、工具栏、程序窗体,以及做保存设置等工作。

(2)挂接Visual BasicIDE菜单

在接口IDTExtensibility的OnConnection方法代码中,一般来说大多数情况下需要挂接Visual BasicIDE菜单(当然也可以是工具栏),以便用户可随时使用该程序。挂接菜单的代码如下:

Set MCBmenuCommandBar = AddToAddinCommandBar ("My Addin")

'sink the event

Set Me.MenuHandler=

VBinst.Events.CommandBarEvents (mcbMenuCommandBar)

其中AddToAddInCommandBar 函数的代码如下:

Function AddToAddInCommandBar (sCaption As String)As-Office.CommandBarControl

Dim cbMenuCommandBar As Office.CommandBarControl

Dim cbMenu As Object

On Error Go To AddToAddInCommandBarErr

'see if we can find the Add-ins menu

Set cbMenu=Vbinstance.CommandBars ("Add-ins")

If cbMenu is Nothing Then

'not available so we fail

Exit Function

End if

'add it to the command bar

Set cbMenuCommandBar=cbMenu.Controls.Add(1)

'set the caption

cbMenuCommandBar.Caption =sCaption

Set AddToAddInCommandBar = cbMenuCommandBar

Exit Function

AddToAddInCommandBarErr:

End Function

写上面的代码中,mcbMenuCommandBar变量定义为:

Dim mcbMenuCommandBar As Office.CommandBarControl

MenuHandler变量定义为:

Public WithEvents MenuHandler As CommandBarEvents

这里需要指出的是,MenuHandler是WithEvents变量,凡是WithEvents变量均表明该变量是一个用来响应由ActiveX对象触发的事件的对象变更。也就是说,该变量是拥有事件的,因此可以编写该变量的事件代码。在上述代码中将事件对象VBInst.Events.Comman-dBarEvents(mcbMenuCommandBar)赋予MenuHandler变量,则表示当发生有关mcbMenuC-ommandBar菜单项的事件时,由该变量的代码进行处理。在类模块中,我们发现,就存在MenuHandler-Click事件代码,该代码用以显示窗体对话。

在AddToAddInCommandBar函数中,VBInstance是在OnConnection方法保存的会话期实例,所有Add-Ins的调用都需要此实例。使用VBInstance. CommandBars(“Add-Ins”)将获得Add-Ins菜单条对象(在中文VB5下是“外接程序”菜单条),请注意:该“Add-Ins”是不会本地化的,因此无论是在中文还是英文VB5下抱歉获得上菜单条对象。代码Set cbMenuCommandBar=cbMenu.Controls.Add(1)在该菜单下添加一新的菜单项“My AddIn”,使用了cbMenu.Controls的Add方法。关于菜单条的层次关系及相应的属性及方法,可以参看VB关于外接程序的帮助或联机手册。但通过笔者的实践认为,最好的方法是使用F2打开VB的浏览器,其类之间的层次关系以及对象事件,方法,属性一目了然。

关于类Connect中的其它方面的代码,一般来说比较容易理解,这里就不叙述了。

3. 模块AddIn

模块AddIn比较简单,仅包含一个子程序:

Sub AddToINI ()

Dim ErrCode As Long

ErrCode=WritePrivateProfileString ("Add-Ins32","My AddIn.Connect","0","vbaddin.ini")

End Sub

该程序可以在立即窗口中运行,以便将关于此外接程序的信息添加到Windows目录下的vbaddin.ini文件中去,这样VB的外接程序管理器就可以认识该程序,并可将其挂接到VB的IDE环境中。该程序所做的工作很简单,只是在vbaddin.ini文件的[Add-Ins32]下添加一行My AddIn.Connect=0,表明My AddIn没有挂接到IDE环境中,若My AddIn.Connect=1,则VB启动时自动挂接该程序。

4. 窗体frm AddIn

窗体frm AddIn中的代码是由用户编写的,模板仅给出了一个框架。针对我们上面提出的具体问题,我们设计了一个简单的用户界面,包括如下控件:

(1)标签Label1:Caption="All controls In SelectedForm:"

(2)列表框List1:用于显示表单中的所有控制。

(3)命令按钮fontButton (0):Caption ="&Select Font",用于将选中的窗体上所有控制的字体设为缺省字体。(注:缺省字体为宋体9号字,这种字体在中文环境不同分辨率下效果都比较好)。

(4)命令按钮fontButton (1):Caption ="&Select Font",选择该按钮后将弹出选择字体,然后程序将选中的窗体上所有控制的字体均设为用户选择的字体。

(5)命令按钮ExitButton:Caption="&Exit",用于退出此程序,实际上的工作只是隐藏了窗体frm AddIn。外接程序的真正退出还是需要外接程序管理器中删去。

(6)通用对话框CommonDialog1:用于弹出选择字体的通用对话框,便于用户从中选择所需字体。

下面是窗体代码:

Public VBInstance As vbide.VBE

Public Connect As Connect

Dim mcmpCurrentForm As VBComponent

Option Explicit

Private Sub ChangeFont (NewFontName As String,NewFontSize As Integer,NewFontBold As Boolean,NewFontltalic As Boolean)

Dim control As VBControl

On Error Resume Next

List1.Clear

Set mcmpCurrentForm =VBInstance.SelectedVBComponent

If (mcmpCurrentForm.Type<>vbext-ct-VBForm) And-

(mcmpCurrentForm.Type<>vbext-ct-UseControl) And-

(mcmpCurrentForm.Type<>vbext-ct-DocObject) And-

(mcmpCurrentForm.Type<>vbext-ct-PropPage) Then

Exit Sub

End if

For Each control in mcmpCurrentForm.Designer.VBControls

List.AddItem control.ControlObject.Name

control.ControlObject.FontName= NewFontName

control.ControlObject.FontSize= NewFontSize

control.ControlObject.FontBole= NewFontBole

control.ControlObject.FontItalic= NewFontItalic

Next

End Sub

Private Sub ExitButton-Click (Index As Integer)

Connect.Hide

End Sub

Private Sub FontButton-Click (Index As Integer)

Select Case Index

Case 0

ChangeFont "宋体",9,False,False

Case 1

With CommonDialog1

.Flags = cdlCFBoth

.ShowFont

ChangeFont.FontName,.FontSize,.FontBold,.FontItalic

End With

End Select

End Sub

上面的代码比较简单,关键的代码在于获取屏幕上的所有控制,在Visual Basic5.0下,与早期版本不同,它利用了VBComponent对象的Designer属性获取屏幕上的设计器,它可以是窗体,也可以是ActiveX控件或ActiveX文档等,然后通过该设计器来获得设计器上的用户控制。上述代码中,首先将mcmpCurrenForm变量被设为当前选中的构件,然后判断它是否是窗体,用户控件,ActiveX文档或属性页,如果是,则获取其设计器即Designer对象,然后通过Designer对象的VBControls属性获得其上所有控制的集合,这样就可以操作该集合中的每一个VBControls控制了。对每一个控制,通过其ControlObject 属性可以获得其相应的屏幕上的控制对象,然后就可以设置该对象的任意属性了。在上述代码中,也可以使用control.Properties!Fontname取代control.ControlObject.FontName,其结果是一样的。另外,为了防止对没有Font属性的控制进行该属性设置将导致错误发生,在程序的开头使用了On Error Resume Next语句以忽略这些错误。下面是该程序的用户界面:

四、 进一步的改进

对上述程序还可做进一步的改进,下面列出几种改进思想及编程方案。

1、 设置控制的其它属性

上述代码主要用来设置控制的字体,但基于同样的原理,我们只要对代码稍加改变就可以设置控制的其它属性,如前景色,背景色,可见或不可见等。

2、 为当前工程中的所有窗体设置控制属性

在上述代码中,是对当前选中的窗体里的控制设置字体,但有时我们需要将工程中的所有窗体中的所有控制一次设置其属性,而不是每次选择一个窗体进行设置。这时可以采用如下方法:首先用VBE(即当前会话期实例)的ActiveVBProject属性获得当前的工程,然后通过其VBComponents属性获得当前工程中的所有组件集合,针对每一组件判断它是否为窗体或 ActiveX控件等,剩下的代码就和上面基本一样了。

3、 仅为选中的控制设置属性

若只是需要为选中的控制设置属性则可以利用VBForm 对象的SelectedVBControls属性获得当前选中的所有控制的集合,然后对其包含的控制设置属性即可。也可利用VBControl的InSelection属性判断该控制是否被选中,然后仅对选中的控制设置属性即可。

4、 当控件被添加到窗体时,自动为它设置属性

要实现当控件被添加到窗体时,自动为它设置属性的功能需要用到VBE的事件对象,即与上面提到的为菜单提供事件代码的方法一样。首先声明一个事件变量:Public WithEvents CtlHandler As VBControlsEvents,然后在接口IDTExtensibility的OnConnection方法代码中挂接控制事件处理:Set Me.CtlHandler=VBInstance.Events.VBControlsEvents (Nothing,Nothi-ng),这样就可以进行事件处理了。而进行事件处理的代码可写在CtlHandler变量的ItemAdded代码中,如下:

Private Sub CtlHandler-ItemAddec (ByVal VBControl As VBIDE.VBControl)

'这里可加入所需要的代码。

End Sub

当然,除上述改进外,我们还可以提出更多的改进方案,以丰富原程序的功能。总之,由于VB显露其IDE包括窗口、工程、控制,甚至事件、代码等各个部分的接口,使得我们能非常简单而有效地控制自己的编程活动和定制自己的界面,从而节省了编程时间,提高了工作效率,也减少了错误的发生。

参考文献

1、[美]鲍(Boyle,D)等著·Visual Basic 4 开发人员指南·薛万鹏等译·机械工业出版社

2、Visual Basic 5联机手册·Microsoft Corporation

回到目录

浅谈PB中动态DataWindow的技术应用

在PowerBuilder的应用程序开发过程中,对数据库中数据进行操作的对象是数据窗口对象(DataWindow),利用数据窗口对象,我们可以十分方便地完成对数据库中已经存在的表中数据进行检索、查询、插入、删除和更新。但是,在实际问题中,我们常常遇到数据库中的一些表是用户在程序运行期间动态生成的,若要对这样表中的数据进行操作,就要运用动态数据窗口对象,值得提到的一点是,在动态数据窗口对象生成时,其标题区(Header Band)中的文本不能直接显示成汉字,这的确是一点遗憾,不过这个问题可以通过映射的方法得到解决。

一、 问题的提出

设有如下两张表:

A表中的记录是用户可以在程序运行期间进行自由增加、修改、删除和更新的,B表中的属性(即:字段)由A表中的记录决定并动态创建,而且,能够方便地对B表中的数据提供汉化的操作界面。当然,将B表创建为下表

也是可以的,但是,在动态生成数据窗口对象时,其标题区(Header Band)中的文本不会显示成汉字,而是一些乱码,反而不利于问题的解决。

二、 问题的解决

1、 动态创建B表的解决

我们要动态创建B表,就要构建动态SQL语句。何谓动态SQL语句?数据库应用程序通常进行确定的工作,因此在编写和编译时,就可以确定完整的SQL语句,但当需要使用PowerBuilder不支持的嵌入SQL语句(如DDL语句),或者在编译时不知道语句的具体格式或参数,则在运行时构成SQL语句,这类语句被称为动态SQL语句。

动态SQL语句的格式:

EXECUTE IMMEDIATE SQL statement [Using Transation Object];

参数说明:

SQL statement 包含一条有SQL语句的字符串

Transation Object 事务对象

2、 动态数据窗口对象创建及标题区(Header Band)中文本汉化的解决

(1) 在程序运行时,我们可以调用Create函数动态生成数据窗口对象。格式如下:

DataWindowControl.Create(Syntax{,Errorbuffer})

参数说明:

DataWindowControl 将在其中创建数据窗口对象的数据窗口控件名

Syntax 数据窗口对象源代码

Errorbuffer 用于保存错误信息的字符串

(2) 由于标题区(Header Band)中文本框的名称是对应细目区(Detail Band)中相应列的名称加上"_t"构成的,而细目区(Detail Band)中列的名称又是相应表的属性的名称。因此,我们能够使用游标(Cursor)取出A表中的ywm和zwm的值,然后使用映射的方式替换标题区(Header Band)中文本框的文本(Text)属性,从而使标题区(Header Band)中文本框的文本显示为相应的汉字。

三、 一个简单的例子

在PowerBuilder 6.5和MS SQL Server 6.5的环境下,使用一个简单的例子实现上述的观点,限于篇幅,只列出主要界面及关键程序。

1、"动态创建B表"按钮对应的代码是:

int li_i=1,li_count

string ywm[],zdlx[],ls_temp,ls_sql

//使用游标(Cursor)从数据库的表中获取ywm和zdlx的值并存储于数组ywm[]和zdlx[]中

select count(*) into :li_count from a;

DECLARE a_cur CURSOR FOR SELECT ywm,zdlx FROM a order by ywm;

OPEN a_cur ;

FETCH a_cur INTO :ywm[li_i], :zdlx[li_i] ;

do while sqlca.sqlcode=0

ls_temp=trim(zdlx[li_i])

choose case ls_temp

case "1"

ls_temp="char(10)"

case "2"

ls_temp="numeric(7,2)"

end choose

zdlx[li_i]=ls_temp

ywm[li_i]=trim(ywm[li_i])

li_i++

FETCH a_cur INTO :ywm[li_i], :zdlx[li_i] ;

loop

close a_cur;

//创建B表和主键(Primary Key)

ls_sql="create table b"+"("+ywm[1]+" "+zdlx[1]+" not null,"&

+"constraint pk_b primary key ("+ywm[1]+"))"

execute immediate:ls_sql;

//增加B表的列

for li_i=2 to li_count

ls_sql="alter table b add "+ywm[li_i]+" "+zdlx[li_i]

execute immediate:ls_sql;

end for

2、"动态创建数据窗口对象"按钮对应的代码是:

string syntax,sqlselect,errmsg,ls_col1,ls_col2,ls_name,ls_b;

//动态创建数据窗口对象DataWindow

ls_b="b"

sqlselect="select * from "+ls_b;

syntax=sqlca.syntaxfromsql(sqlselect,"style(type=grid)",errmsg);

dw_1.create(syntax)

//汉化标题区(Header Band)文本

DECLARE v_cur CURSOR FOR SELECT ywm,zwm FROM a order by ywm;

OPEN v_cur ;

FETCH v_cur INTO :ls_col1, :ls_col2 ;

do while sqlca.sqlcode=0

ls_name=ls_col1+'_'+'t'+'.'+'text'+'='+'"'+ls_col2+'"'

dw_1.modify(ls_name)

FETCH v_cur INTO :ls_col1, :ls_col2 ;

loop

close v_cur;

dw_1.settransobject(sqlca);

dw_1.retrieve()

四、 结束语

利用PowerBuilder的动态数据窗口对象的技术应用,可以解决实际中数据库的动态数据处理问题,从而使应用程序具有更好的交互性和适应性,若稍加变动,用途是十分广泛的。

回到目录

用PowerBuilder制作指示灯

相信大家在安装各种软件或微软公司产品时都会注意到那直观可爱的条状指示灯,它总是以最直接的方式告诉我们工作的进程情况,在PowberBuilder 中也可以实现。

1. 创建一个应用程序(working-out)。

2. 创建一个窗口(w_01)。

3. 在应用程序的Open事件中最未尾Open()函数改为Open(w_01)。

4. 编辑w_01窗口。

5. 添加三个控件在 w_01窗口上,即两个Rectangle :r_1,r_2 和一个commandButton :cb_1。

6. 将 r_1的Fill Color:设为White 将Line Color:设为Black,将X设为243,Y设为645,Width设为1541,Height设为113。按Apply 或 OK即可。

7. 将 r_2的Fill Color:设为Blue 将Line Color:设为White,将X设为261,Y设为661,Width设为5,Height设为85。按“Apply” 或 “OK”即可。

8. 在cb_1的 clicked事件中添写:

r_1.visible= true

r_2.visible = true

int lock

lock=0

do while lock <100

lock = lock + 1

r_2.width=lock*15

loop

9. 按 “Run” 键运行此程序,就会看到一条从头走到尾的像安装Win98一样的指未灯出现在你的程序窗口上。

注*此程序只是作为一个指示灯,那什么时候指示灯该向前走,什么时候指示灯该停,只要想办法用变量给Lock赋值就可以了。

回到目录

得到CPU速度,单位MHz

function GetCpuSpeed: Comp;

{ function to return the CPU clock speed only.}

{ Usage: MessageDlg(Format('%.1f MHz', [GetCpuSpeed]),

mtConfirmation, [mbOk], 0); }

var

t: DWORD;

mhi, mlo, nhi, nlo: DWORD;

t0, t1, chi, clo, shr32: Comp;

begin

shr32 := 65536;

shr32 := shr32 * 65536;

t := GetTickCount;

while t = GetTickCount do begin end;

asm

DB 0FH

DB 031H

mov mhi,edx

mov mlo,eax

end;

while GetTickCount <(t + 1000) do begin end;

asm

DB 0FH

DB 031H

mov nhi,edx

mov nlo,eax

end;

chi := mhi;

if mhi <0 then chi :=chi + shr32;

clo := mlo;

if mlo <0 then clo :=clo + shr32;

t0 := chi * shr32 + clo;

chi := nhi;

if nhi <0 then chi :=chi + shr32;

clo := nlo;

if nlo <0 then clo :=clo + shr32;

t1 := chi * shr32 + clo;

Result := (t1 - t0) / 1E6;

end;

回到目录

用API函数Mcisendstring直接播放背景音乐

作者:徐建波

源代码:

Private Sub Command1_Click()

Dim back

back = mciSendString&("CLOSE NN", 0, 0, 0)

End Sub

Private Sub Command2_Click()

Dim back

back = mciSendString&("OPEN " + App.Path + "\TEST.mid" + " TYPE SEQUENCER ALIAS NN", 0&, 0, 0)

back = mciSendString&("PLAY NN FROM 0", 0&, 0, 0)

R% = mciSendString&("CLOSE ANIMATION", 0&, 0, 0)

End Sub

Private Sub Form_Load()

Dim back

back = mciSendString&("OPEN " + App.Path + "\TEST.mid" + " TYPE WaveAudio ALIAS NN", 0&, 0, 0)

back = mciSendString&("PLAY NN FROM 0", 0&, 0, 0)

R% = mciSendString&("CLOSE ANIMATION", 0&, 0, 0)

End Sub

回到目录

给MDI主窗口加背景

在MDI程序中,由于MDI的主窗口一般的功能是提供子窗口显示的位置和提供菜单、工具条、状态条等,而窗口的客户区则一般不会有其它的用途,如果在这里画上一些软件的标志、公司的标志或者其它的背景图案的话,不仅可以使MDI的主窗口更加充实、美观,而且还可以更加突出公司的形象和增加公司标志在客户心中的地位。

由于MDI主窗口的特性,使用普通OnPaint和使用TImage等方法都不会产生作用。下面将用编写一个简单的MDI程序来介绍如何实现。

第一步:打开Delphi(Delphi 1,2,3都可以),创建一个新的工程。

第二步:将Form1的FormStyle设置为fsMDIForm,设置成MDI的主窗口。

第三步:在Form1上增加一个Image元件,并选择要设置的背景到Image的Picture中。

第四步:在Form1的Private中定义:

FClientInstance,

FPrevClientProc : TFarProc;

PROCEDURE ClientWndProc(VAR Message: TMessage);

第五步:在实现(implementation)中加入上述过程的具体内容:

PROCEDURE TForm1.ClientWndProc(VAR Message: TMessage);

VAR

MyDC : hDC;

Ro, Co : Word;

begin

with Message do

case Msg of

WM_ERASEBKGND:

begin

MyDC := TWMEraseBkGnd(Message).DC;

FOR Ro := 0 TO ClientHeight DIV Image1.Picture.Height DO

FOR Co := 0 TO ClientWIDTH DIV Image1.Picture.Width DO

BitBlt(MyDC, Co*Image1.Picture.Width, Ro*Image1.Picture.Height,

Image1.Picture.Width, Image1.Picture.Height,

Image1.Picture.Bitmap.Canvas.Handle, 0, 0, SRCCOPY);

Result := 1;

end;

else

Result := CallWindowProc(FPrevClientProc, ClientHandle, Msg, wParam, lParam);

end;

end;

第六步:在Form1的创建事件中加入:

FClientInstance := MakeObjectInstance(ClientWndProc);

FPrevClientProc := Pointer(GetWindowLong(ClientHandle, GWL_WNDPROC));

SetWindowLong(ClientHandle, GWL_WNDPROC, LongInt(FClientInstance));

上面的步骤已经完成了MDI主窗口背景图案的设置,下面可以增加一个MDIChild窗口,实现MDI程序。

第七步:新增加一个Form,并将FormStyle设置为fsMDIChild。

现在你可以编译运行这个程序,你会发现,Image元件并不会在Form上显示出来,但是整个Form的客户区域被Image中的图像所铺满。

回到目录

《编程爱好者》订退方法

请在下面的文本框内输入您订阅本刊的邮件地址,并按右面的订阅按钮即可。如果您觉得这份刊物还不错的话,欢迎把它推荐给您的朋友。

欢迎订阅

不知道您看了这期刊物有什么想法或者是意见,欢迎向我提出来。

本人感激不尽,我的联系方法如下:

Homepage: http://www.programfan.com

E-mail: pfan2000@163.net

OICQ: 15987743

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有