精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● VB和Basic>>● VB和Basic(1)>>文章连载>>VB邮件>>VB邮件(6.12)

主题:VB邮件(6.12)
发信人: aaaaaaaaa()
整理人: cobe(2000-02-12 23:55:37), 站内信件
                      编者的话
====================================================================
大家好!
    这是关于VB和ASP的免费邮件列表。
    如果您有问题或想回答别人的问题,请给我写信。
    如果您有好的作品或您发现了好的作品,不要忘
了让大家共享。
    热情欢迎您的参与!!!
                                版主   冯德平
                                [email protected]
=============================================
            VB邮件(6.12)
a VB中访问API函数之防错技巧

郭少越

    功能强大的API(应用程序接口)函数对于VB程序员来说,不愧是很好的编程


工具,然而使用API函数的程序员也许都遇到这样的现象。在VB集成环境下,程序


运行后,出现一错误信息对话框,按确定键后系统自动退出VB集成环境,此时如


果你的程序尚未存盘,那末很遗憾挽回损失已回天乏力。最后一次存盘之后的程


序都不复存在。这是你对API函数使用不当引起的一般保护故障(GPF)。

    当一个GPF错发生时,你应允许Windows关闭你的应用。有些情况下你可能需


要退出Windows或者重新引导系统。出错程度视哪里内存被破坏而定。DLL(动态


链接库)函数中的类型不一致等错误是GPF错的主要原因。这些错误会导致GPF甚


至使Windows系统完全崩溃(需要重新引导系统)。

    下面谈避免GPF的一些技巧。

    用别名来提供强类型检查是避免GPF的有效措施之一。有些情况下,DLL函数


可以接受多种类型,LoadCursor函数就是这样一个例子,其定义如下:

HCursor LoadCursor(hInstance,lpCursorName)

    这里HCursor是一个指向光标对象的16位句柄,hInstance是一个16位实


例句柄,lpCursorName是光标的名字或者是光标资源的32位整数ID。为了支持


两种类型的lpCursorName参数。VB有必要包含如下两个声明:

 

DeclareFunction LoadCursor Lib"USER"(ByVal hInstance As Integer,By


Val lpCursorName As String)As Integer



DeclareFunction LoadCursor Lib"USER"(ByVal hInstance As Integer,By


VallpCursorName As Long)As Integer

    但是,这两个声明不能在一个程序中同时存在,因为Visual Basic会报重复


声明错。我们知道,As Any声明可使得任何参数都可以传递给DLL函数,因此可以


如下声明:

DeclareFunction LoadCursor Lib"USER"(ByVal hInstance As Integer ,B


yVal lpCursorName As Any )As Integer

 

    上述声明意味着Visual Basic能支持一个参数可接受多种类型的DLL函数,然


而这就可能带来各种灾难性的后果,每当偶然情况下用不正确的参数调用该函数


时,都可以引发一个GPF,我们可以这样进行严格的类型检查并且帮助防止这类问


题。

    这种方法就是在函数的声明中使用Alias技巧,看看下面的两个声明:

DeclareFunction LoadCursorByName Lib"USER"Alias "LoadCursor"(ByVa


l hInstance As Integer,ByVal lpCursorName As String)As Integer

 

DeclareFunction LoadCursorByID Lib"USER"Alias "LoadCursor"(ByVal 


hInstance As Integer ,ByVallpCursorName As Long)As Integer

 

    LoadCursorByName用字符串做lpCursorName参数访问DLL函数LoadCursor, 


而LoadCursorByID访问同样的DLL函数LoadCursor,但是用长整型做lpCursorNam


e参数,这两个函数都对lpCursorName参数进行严格的类型检查,使Visual Basi


c能在调用DLL函数之前识别出不正确的变量类型,最大限度地减少引起GPF或者导


致系统崩溃的机会。

    除此之外,使用API函数时运行之前最好先存盘,仔细检查调用API函数的参


数与声明的类型是否一致,以及严格检查参数是否有效都能减少引发GPF或者系统


崩溃。


b VB中Grid控件的打印方法

  Grid控件是Visual Basic(以下简称VB)最常见控件之一,用它可以以表格的形


式显示、浏览数据。特别是在数据库应用中,直接绑定即可显示和浏览数据库信息


。然而,美中不足的是Grid没有编辑和打印功能,列与列的位置不能相互交换。笔


者曾尝试着给Grid增添了这些功能,使之功能更强大。下面给出改进方法及源程序


,读者可参考使用。该程序在HP5/100、Window 95环境下用VB5.0调试通过。 
  给Grid 控件增加打印方法有三种:一是直接打印控件,二是通过p rinter 来


实现打印功能,三是通过调用MS-Word及MS-Excel 来实现打印。 
  首先,打开一个应用,在FORM1中增加DATA控件DATA1,把DATA1的CO NNECT属性


设为dBA SEⅢ,再把DATABASENAME属性设为D:\PJXM.DBF。然后再在FORM1中增加M


SFLEXGRID控件GRID1,并把GRID1的DATASOURCE 属性设为DATA1。这样数据库PJXM


.DBF的信息就会在GRID1 中显示出来。下面分析介绍各种打印方法。 
  方法一:直接打印窗体 
  在FORM1中增加命令按钮(command),CAPTION属性设为直接打印, 再写入下列


代码: 
  Sub command_click 
  Form1.printform 
  End sub 
  这样即可通过打印窗体FORM1的方法把GRID1的数据打印出来。这种方法的缺


点是只能打印GRID1中显示的数据部分,显示不出来的则无法打印,而且这种打印方


法很像屏幕硬拷贝,而且不能灵活地控制字体等。 
  方法二:通过PRINTER实现打印 
  1. 加入打印命令按钮(command1)和函数(prnt1),写入下面代码, 读者稍加改


动可写成标准的函数或过程。Function prnt1 (x As Int eger, y As Integer,


 font As Sing le, txt As String) 
  printer.CurrentX = x 
  printer.CurrentY = y 
  printer.FontBold = False 
  printer.FontSize = font 
  printer.Print txt End Function Sub command1_click 
  Dim fnt As Single 
  Dim pp as integer 
  Pp=0 '设置开始页码0 
  Dim stry,strx,strx1,stry1,linw,page1,p As Integer 
  Static a(8) As Integer '定义打印的列数 
  ss$ = "内部结算存入款对帐单" '定义表头 
  kan = 0 
  For i = 0 To 8 
  a(i) = 1500' 定义每列宽 
  kan = kan + a(i) '计算表格总宽度 
  Next 
  page1 = 50 ’定义每页行数 
  strx = 200 
  strx1 = 200 ’定义X方向起始位置 
  stry = 1400 
  stry1 = 1400 ’定义Y方向起始位置 
  linw = 240 ’定义行宽 
  fnt = 8 ’定义字体大小 
  printer.fontname = "宋体" ’定义字体 
  dd = prnt1(4000, 700, 18, ss$) ’打印标题 
  printer.Line (strx - 50, stry - 30)-(strx + 
   kan - 10, stry - 30) 
  For j = 0 To gridrow - 1 
   ’gridrow为所要打印的行数 
   grid1.row = j 
   strx = strx1 
   printer.Line (strx - 50, stry - 30)-(strx + 
  kan - 10, stry - 30) 
   p = p + 1 
   For i = 0 To 8 
   grid1.col = i 
   dd = prnt1(strx, stry, fnt, grid1.text) 
   strx = strx + a(i) 
   Next 
  If p > page1 Then ’next page 
   p = 0 
   strx = strx1 
   printer.Line (strx - 50, stry + linw)-(strx + kan - 10, stry + li


nw) 
   stry = stry1 
   For n = 0 To 8 
   printer.Line (strx - 30, stry - 30)-(strx 
   - 30, stry + (page1 + 2) * linw) 
   strx = strx + a(n) 
   Next 
   printer.Line (strx - 30, stry - 30)-(strx - 
  30, stry + (page1 + 2) * linw) 
   pp=pp+1 
   foot$="第 "+cstr(pp)+" 页" 
   dd = prnt1(strx - 30-1000, stry + (page1 + 
  2) * linw+100, 10, foot$) ’打印页脚码 
   printer.NewPage ’next page 
   dd = prnt1(4000, 700, 18, ss$) ’打印标题 
   strx = strx1 
   stry = stry1 
   printer.Line (strx - 50, stry - 30)-(strx + 
  kan - 10, stry - 30) ’打印第一行 
  Else 
   stry = stry + linw 
  End If Next 
   st = stry 
  If p < page1 Then ’在最后页剩余划空行
  For o = p To page1 + 1
   strx = strx1
   printer.Line (strx - 50, stry - 30)-(strx +
  kan - 10, stry - 30)
   stry = stry + linw
  Next
  End If
  stry = stry1
  strx = strx1
  stry = stry1’line col
  For n = 0 To 8
   printer.Line (strx - 30, stry - 30)-(strx -
  30, stry + (page1 + 2) * linw)
   strx = strx + a(n)
  Next
  printer.Line (strx - 30, stry - 30)-(strx -
  30, stry + (page1 + 2) * linw)
   pp=pp+1
   foot$="第 "+cstr(pp)+" 页"
   dd = prnt1(strx - 30-1000, stry + (page1 +
  2) * linw+100, 10, foot$) ’打印页脚码
   printer.EndDoc ’打印结束
  End sub
  这种方法通过灵活的编程可以方便地调整字体、字型、线形、页面、纸张大


小等,可打印出比较满意的效果。
  如果计算机上装有Microsoft Word和Microsoft Excel,则可把GR ID的表格通


过VB发送到这些应用程序中去,生成Microsoft Word和Mic rosoft Excel表格。这


样可以充分利用它们的打印、编辑功能,打印出更理想的效果。下面逐一介绍。



  方法三:通过生成Word表格打印
  1. 在declaration 中写入:
  Dim msword As Object
  2. 加入打印命令按钮(command2),CAPTION设为"生成Word表格", 写入下面代


码:Pri vate Sub command2_Click()
  screen.MousePointer = 11
  Set msword = CreateObject("word.basic")
  Dim AppID, ReturnValue
  appID = Shell("d:\office97\office\WIN-
  WORD.EXE", 1)  ’运行Word
  msword.AppActivate "Microsoft Word"
  full
  Screen.MousePointer = 0 End Sub
  3. 写入以下过程full() Sub full()
  Dim i As Integer, j As Integer, col As Integer,
  row As Integer
  Dim cellcontent As String
  Me.Hide
  cols = 4 ’表格的列数
  row = gridrow ’打印表的行数
  msword.filenewdefault
  msword.MsgBox "正在建立MS_WORD报表,请稍候
  ……", "", -1
  msword.leftpara
  msword.screenupdating 0
  msword.tableinserttable , col, row, , , 16, 167
  msword.startofdocument
  for j=0 to gridrow ’表格的行数
   grid1.row=j
   For i = 1 To cols
   Gri1d.col=i
    If IsNull(grid1.text) Then
   cellcontent$ = ""
    Else
   cellcontent$ = grid1.text
    End If
    msword.Insert cellcontent$
    msword.nextcell
   Next i
  Next j
  msword.tabledeleterow
  msword.startofdocument
  msword.tableselectrow
  msword.tableheadings 1
  msword.centerpara
  ’msword.startdocument
  msword.screenrefresh
  msword.screenupdating 1
  msword.MsgBox "结束", "", -1
  Me.Show End Sub
  方法四:通过发送到Excel实现表格打印
  1. 加入打印命令按钮(command3),CAPTION设为"生成EXCEL表格" ,写入下面


代码: Private Sub command3_Click()
  Dim i As Integer
  Dim j As Integer
  Dim xlApp As Excel.Application
  Dim xlBook As Excel.Workbook
  Dim xlSheet As Excel.Worksheet
  Set xlApp = CreateObject("Excel.Application")
  xlApp.Visible = True
  Set xlBook = xlApp.Workbooks.Add
  Set xlSheet = xlBook.Worksheets(1)
  xlSheet.Cells(6, 1) = "i"
  For i = 0 To gridrow
   grid1.Row = i
   For j = 0 To 6
   Grid1.Col = j
   If IsNull(Grid1.Text) = False Then
  xlSheet.Cells(i + 5, j + 1) = Grid1.Text
   End If
   Next j
  Next i End Sub
  中原油田计算中心 武正伦 李俊海

c VB中的Unicode 和 Ansi 格式
 

Visual Basic 32-bit 版本的字串处理采用 Unicode,也就是说字串在 VB


内部是以Unicode 的格式来存放。

何谓 Unicode?简单的说,就是每一个字符都是以 2-byte 的形式表示,而


每个「实体字符」就是一个「字符」。因此,

Len("大家好")

Len("abc")

所返回的值都是 3,因为「大」和「a」都是一个字符。

但是这对一些中文字串处理,例如纯文字的数据文件,却是一个大灾难,因


为你必须以byte 来定位每个字符,可是 Unicode 却把一切的处理全搞砸了。例


如:

Len("Good Morning") 返回 12,而

Len("今天天气很好") 返回 6

对初学者而言,好不容易能使用 VB 来写程序已经是件了不起的事了,却马


上在中文处理上挨了一记闷棍,所受到的打击实在不小。但是不要怕,事实上只


要再多了解一些指令,就可以把中文处理的问题解决了。

是什么指令呢?最重要的莫过于 StrConv 了。StrConv 函数的语法为:Str


Conv(待转换字串, 转换格式)

其中转换格式在这里用到的是:

vbUnicode 将 Ansi 字串转换为 Unicode

vbFromUnicode 将 Unicode 字串转换为 Ansi

将字串转成 Ansi 之后,所有的字串处理指令都要加个 B,例如:LeftB, R


ightB,

MidB, ChrB, InstrB, LenB, InputB 等。例用这些指令来处理就行了。

当你处理完毕之后,你可以再将它再转回 Unicode,这样就可以使用一般的


字串处理指令了。

这样讲看得懂吗?如果还是不了解,看看下面的实例说明:

 

[●] 简易使用范例

看看下面的基本范例您应该就会对 VB 的字串处理方式有些概念。

 

Private Sub Command1_Click ()

Dim sUnicode As String

Dim sAnsi As String

 

' Unicode 运算

sUnicode = "王小明,A123456789,651023,上海市中山路100号,(02)2345678"

Debug.Print Len(sUnicode) ' 返回 44

Debug.Print Mid$(sUnicode, 5, 10) ' 返回 A123456789

Debug.Print Instr(sUnicode, "上海市") ' 返回 23

 

' 将 Unicode 字串转成 Ansi

sAnsi = StrConv(sUnicode, vbFromUnicode)

' Ansi 运算

Debug.Print LenB(sAnsi) ' 返回 54

Debug.Print MidB$(sAnsi, 8, 10) ' 返回 ?????,因为忘了转回 Unicode

Debug.Print StrConv(MidB$(sAnsi, 8, 10), vbUnicode) ' 返回 A123456789,


请注意转回 Unicode 的动作一定要做

Debug.Print InStrB(sAnsi, StrConv("上海市", vbFromUnicode)) ' 返回 23,


不要忘了要把"上海市"也转成 Ansi,否则会找不到

End Sub

 

[●] 读入文本文件

 

在 VB 的小技巧中,有一个是快速读文件法:

 

Private Sub Command1_Click ()

Dim sFile As String

 

Open "C:\filename.txt" For Input As #1

sFile = Input$(LOF(1), #1)

Close #1

End Sub

 

但是很不幸地,如果你读取的文件内含中文字,那上面这段程序会出现 Inp


ut pastend of file 的错误。因为 LOF 返回的是文件的 byte 数,而 Input 函


数读取的是字符数,由于文件内含中文,因此文件中的字符数将会小于 byte 数


,于是就发生错误了。

 

要解决这个问题,我们就要用到 StrConv 和 InputB 这两个函数了:

Private Sub Command1_Click ()

Dim sFile As String

 

Open "C:\filename.txt" For Input As #1

sFile = StrConv(InputB$(LOF(1), #1), vbUnicode)

Close #1

End Sub

 

上面修正程序先用 InputB 将文件读进来,不过使用 InputB 所读入的文件


是 Ansi格式的,所以要再用 StrConv 转成 Unicode 才行。

 

[●] 随机数据文件

 

许多文字数据文件是以固定字节的位置来加以区格,例如下面的数据格式:

 

王小民650110上海市中山路100号 (02)1234567

张大呆660824花莲县大甲镇广东街23号(03)9876543

......

 

像这种类型的文件要如何处理呢?这是就必须用到 Type 以及 byte array 了。




 

Private Type tagRecord

Username(5) As Byte ' 姓名 6 bytes

Birthday(5) As Byte ' 生日 6 bytes

Address(21) As Byte ' 地址 22 bytes

TEL(11) As Byte ' 电话 12 bytes

CrLf(1) As Byte ' 换行字符 2 bytes

End Type

 

Private Sub Command1_Click()

Dim uRecord As tagRecord

 

Open "C:\filename.dat" For Random As #1 Len = LenB(uRecord)

Get #1, 2, uRecord ' 取第二笔数据

 

With uRecord ' With ... End With 应该会用吧

Debug.Print .Username ' 返回 ???

Debug.Print StrConv(.Username, vbUnicode) ' 返回 "张大呆"

End With

 

Close #1

End Sub

 

在这个例子中,一定要用到 byte array,因为只有 byte array 才能正确地


定位到每个 byte 的位置。以前使用字串来定位的方法已经不适用了,千万要记


住!但是使用byte array 所读入的数据是 Ansi 格式,若要处理或是做运算的话


,记得还要转成Unicode 格式才行。

 

[●] 使用 Byte Array

 

除了上面必须使用 byte 精确定位的例子之外,纯文字的处理基本上是用不


到 bytearray 的。byte array 通常是用在处理 binary 数据。这方面的问题我


们将另文讨论。

看吧!只要熟悉使用 StrConv,你就可以在 Unicode 及 Ansi 格式之间自由


自在地变来变去,相信当您看完这篇文章之后,对处理中文应该不再烦恼了吧!






=============================================
问题征答(6.12)
a 我想用vb处理麦克风输入的语音音量,应怎么作,万望指教!
kenny
b 问题请教:

用VB6制作Active X 控件.
最后用Setup Wizard 制成 Web 发布的礖TML 文件 和 CAB 文件包.
HTML 的Souce Code 如下:

Main.htm

<HTML>
<HEAD>
<TITLE>Kiosk990521Ocx.CAB</TITLE>
</HEAD>

<OBJECT ID="Kiosk990521UC"
CLASSID="CLSID:2FEB808D-09E5-11D3-BFBF-0000F4903E24"
CODEBASE="Kiosk990521Ocx.CAB#version=1,0,0,1">
</OBJECT>
</BODY>
</HTML>

将HTML 文件 和 CAB 文件包
NT Server+Microsoft IIS 3.0 上
从Client端浏览main.htm是可以
自动下载并执行对应的Active X的,可是如果我
对原来的Active X有所修改,并新编译和用Setup Wizard
生成新的Html 和CAB,并重新Copy 至Server 上.从Client端
重新浏览该main.htm发现还是老的腁ctive X并没有自动更
新,这是为什么?

而且我发现VB6重新编译Active X 控件
其ID 永远是不变的,
如"CLSID:2FEB808D-09E5-11D3-BFBF-0000F4903E24"
而以前用VB5时每编译一次ID都会变的,
是否和这有关,还是VB6里另外有什么设置?请高手指教.

慧子([email protected])

c 你好,

      我在写一个Word Automation程序,需要动态地取Word中打开文件的内容,



      但在取图片内容时遇到了麻烦。 
      当选中Shape,copy到剪辑版时,查看剪辑版,每个机器拷贝的内容都不一


样,图

      片内容好象经过了不同的变换,不知道是??原因,请高手指教。 
      或者可以有不同的方法取word的图片内容。 

      请将指教发给我的email信箱,万分感谢!!! 

      [email protected] 
=============================================
                其它
====================================================================
欢迎订阅VB免费邮件:
订阅地址  http://server.com/WebApps/mail-list-subscribe.cgi?id=16852  



====================================================================  



如果您觉得这个邮件列表好的话,请告诉您的朋友。  
====================================================================
欢迎投稿  [email protected]  
====================================================================  



网易上的主页地址:http://www4.netease.com/~aaaaaaaaa 
本网站主页镜像地址:goodvbhome.yeah.net 
====================================================================



--
欢迎访问主页:goodvbhonme.yeah.net
或:http://www4.netease.com/~aaaaaaaaa
http://personal.gz168.gnet.gd.cn/vbok/

※ 修改:.aaaaaaaaa 于 Jun 13 14:03:15 修改本文.[FROM: 202.103.47.245]
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.103.47.245]

[关闭][返回]