怎样做 AVI 文件
WIN 9X 中带的 avifil32.dll库中有:AVIFileRelease、AVIStreamRelease、AVIStreamWrite、AVIStreamSetFormat、AVIFileCreateStreamA、AVIFileOpenA、AVIFileExit、AVIFileInit,这些函数及过程可以处理生成 AVI 文件,
Refer to MSDN library:
Platform SDK \ Graphics and Multimedia Services \Windows Multimedia \ Video for Windows \ AVIFile Functions and Macros
I don't know if there are some Chinese books about this topic.
如何在放入CD碟时自动调入我的CD播放软件
修改HKEY_CLASSES_ROOT\AudioCD\shell\play\command键。该键的默认值为“C:\Windows\cdplayer.exe /play %1”
这里的%1是音轨文件。你可以把它修改为:
"C:\MyPath\MyPlayer.exe %1"
如何为用VB做的程序加上特定的图标
一般先设置主窗口的Icon属性为你自己的图标,然后选择菜单“工程|??? 属性”,选择“生成”(Make)选项卡,在其中为工程选定图标。这里的???是你的工程名。
如何得知wav文件所用时间
mci控件的length属性可取得当前的wav文件的时间。VB有一个MCI的例子演示了如何使用这个属性。
如何用VB5.0编程来播放VCD
微软有一个软件叫DirectMedia或者ActiveMovie,这个软件可以播放MPEG文件。如果你安装了IE 4.0x,那么这个软件已经在你机器上了(在System目录中,叫amovie.ocx)。如果没有安装IE 4.0x,也可以从微软的站点上(http://www.microsoft.com)单独下载这个软件的SDK或运行版本。
Xing MPEG Player支持MCI接口,可以在VB中利用MCI控件调用它来播放VCD。
超级解霸也提供了一个编程接口,不过这个接口是面向C语言的,需要改造一下才能在VB中使用。
怎样以“分:秒”的格式显示时间
假定你使用一个整数保存已经播放的秒数。你可以这样做:
Dim nSeconds As Integer
......
Print Format(nSeconds \ 60, "00") + ":" + Format(nSeconds Mod 60, "00")
编写多媒体播器时,怎样才能实现遁环播放
一个专用的API函数,SndPlaySound(), 此函数是一个可独立播放WAV 语音文件的函数, 使用相对来说较为简单,无需使用MMControl,下面的例子可直接播放TEST.WAV文件:
Private Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
i=SndPlaySound("test.wav",SND_LOOP),最后一个参数可设置。SND_LOOP表示遁环播放。更具体的说明可查阅MSDN,成功的话返回 true。
利用多媒体的mciSendString API 函数, 再搭配mci(multimedia control inteXXXce) 指令, 即可播放.wav 声音文件, 细节如下:
1. API 的声明:
Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
注:如果以上的声明放在「一般模块」底下, 应将Private 保留字去掉。
2. 程序范例:
'自定义过程PlaySound
Sub PlaySound(filename)
Dim cmd As String
Call mciSendString("close MyWav", 0, 0, 0) ' MyWav 这个名称可依需要来修改
cmd = "open " & filename & " type WAVEAudio alias MyWav"
Call mciSendString(cmd, 0, 0, 0)
Call mciSendString("play MyWav", 0, 0, 0)
End Sub
' 假设要播放"c:\windows\Tada.wav"
PlaySound "c:\windows\Tada.wav"
在表单上布置一个Timer 控制文件、将
Interval 属性设定成100(表示0.1 秒), 然后撰写
Timer1_Timer 事件程序,如下:
Private Sub Timer1_Timer()
Dim retStr As String * 80
Call mciSendString("status MyWav mode", retStr, 80, 0)
If Left(retStr, 7) = "stopped" Then ' 如果停止了
PlaySound "c:\windows\Tada.wav" ' 重复播放
End If
End Sub
主持人注:实际上有更简单的方法,只要使用API函数mciSendCommand时在命令后加上repeat就可以实现遁环播放。如
mciSendString "play mov notify repeat", 0, 0, hWnd
就可以实现重复放映电影。
VC编写的动态链接库,其返回的字符串在VB中怎样正确读取
在动态链接库中用函数返回,而不是参数返回。如:
char * cDate(int year,int month,int day)
{
……;
}
从网上查找了许多资料,均介绍的是VB向VC传递字符串,虽然挺麻烦,但还是可行的。为什么我们不能象调用API函数一样,用结构传输参数,或用于返回,而必需用结构数组?
直接返回char *是不行的,VB不支持这种做法。正如你在资料中看到,大多数都是在VB中先给字符串分配空间,再传递给VC,在DLL中可以修改字符串,但不能超过VB中分配的空间。如果你希望直接返回字符串,必须使用BSTR类型,这实际上就是VB中的字符串所使用的类型。下面是一个简单的例子:
EXTERN_C BSTR WINAPI RetStr()
{
char *str="1234567890";
return SysAllocString((BSTR)str);
}
能否在vb中实现wav和avi文件的自动播放
播放WAV文件可以采用API函数sndPlaySound。
先加入如下声明:
Private Declare Function sndPlaySound Lib "WINMM.DLL" Alias _
"sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As _
Long) As Long
Const SND_SYNC = &H0
Const SND_ASYNC = &H1
Const SND_NODEFAULT = &H2
Const SND_LOOP = &H8
Const SND_NOSTOP = &H10
然后使用
sndPlaySound("c:\windows\tada.wav", SND_ASYNC Or SND_NODEFAULT)
播放AVI文件,可以在工程中加上Microsoft Windows Common Controls - 2,其中有一个Automation控件是播放AVI文件的。
在下面示例中,用“打开”对话框打开一个 .avi 文件并自动播放。要试用此例,在窗体上放置 Animation 控件和 CommonDialog 控件,并把代码粘贴到窗体的声明部分。运行该例,并选择要打开的 .avi 文件。
Private Sub Animation1_Click ()
With CommonDialog1
.Filter = "avi (*.avi)|*.avi"
.ShowOpen
End With
With Animation1
.Autoplay = True
.Open CommonDialog1.Filename
End With
End Sub
如何自动播放背景音乐
你可以将MMControl1的Visible属性设置为False,然后输入下面的代码:
Private Sub Form_Load()
MMControl1.Notify = False
MMControl1.Wait = True
MMControl1.Shareable = False
MMControl1.DeviceType = "WaveAudio"
MMControl1.filename = "C:\WIN98\MEDIA\Ctmelody.wav"
MMControl1.Command = "Open"
MMControl1.Command = "Play"
End Sub
Private Sub Form_Unload(Cancel As Integer)
MMControl1.Command = "Close"
End Sub
使用定时器使得标签背景色由红到蓝,再到绿,且使标签的left 沿窗体的左边向右边同时移动。
Private Sub Form_Load()
Timer1.Interval = 500
End Sub
Private Sub Timer1_Timer()
With Label1
Select Case .BackColor
Case vbRed
.BackColor = vbBlue
Case vbBlue
.BackColor = vbGreen
Case Else
.BackColor = vbRed
End Select
If .Left + .Width < Width Then .Left = .Left + 50
End With
End Sub
通过一定的算法还可以出现各种特效。
如何屏蔽一个事件
你可以建立一个窗体级变量:
Dim bWorking As Boolean
在Form_Load中:
bWorking = False
然后,
Private Sub DBGrid1_RowColChange(...)
If bWorking Then Exit Sub ' 如果还没有处理完,退出
bWorking = True
.....
bWorking = False
End Sub
我现在要做一个类似于用身份证号码抽奖的程序。要求从1到370随机抽取一个整数,并且每次抽取的数字不得相同,但为保证公平又要每个数字都有可能抽到,当然抽取的次数不大于370次,不知用VB6如何实现。
实现的方法有很多,下面只是一种。先建立一组标志,如果选中了就设置为1。每次选数时,先判断标志是否为1,如果不为1,则选中,否则忽略选择下一个。下面是例子:
Dim n(1 To 370), i, j, q
For i = 1 To 370
n(i) = 0
Next
j = 0
Randomize Timer
While j < 10
q = Int(Rnd(1) * 369 + 1)
If n(q) = 0 Then
Print q
n(q) = 1
j = j + 1
End If
Wend
我想让1到370个数字在窗体内不停的快速循环显示,一按下停止按钮或按下回车键就停止显示,应如何做。最好能和以上程序结合起来。
可以建立两个按钮,Command1和Command2,其中Command1是开始按钮,Command2是结束按钮。再加上Label1。
Dim bStop As Boolean
Dim n(1 To 370), i, j, q
Private Sub Command1_Click()
Command1.Visible = False
Randomize Timer
While j < 10
q = Int(Rnd(1) * 369 + 1)
Label1.Caption = q: DoEvents
If n(q) = 0 And bStop = True Then
Print q
n(q) = 1
j = j + 1
bStop = False
End If
Wend
End Sub
Private Sub Command2_Click()
bStop = True
End Sub
Private Sub Form_Load()
For i = 1 To 370
n(i) = 0
Next
j = 0
bStop = False
End Sub
如何全屏播放avi动画文件
使用下面的语句:
Private Declare Function mciSendString Lib "winmm.dll" Alias _
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _
hwndCallback As Long) As Long
Sub Command1_Click()
'// --- Modify FILE_TO_OPEN constant as appropriate ---
Const FILE_TO_OPEN = "C:\winnt\clock.avi"
Dim strCmdStr As String
Dim lngReturnVal As Long
strCmdStr = "play " & FILE_TO_OPEN & " fullscreen "
lngReturnVal = mciSendString(strCmdStr, 0&, 0, 0&)
End Sub
如何在程序中实现将汉字内码输出成汉字的功能
假定有一个字符串"CECAD7A8BCD2",这个字符串是某三个汉字的内码。使用下面的代码进行转换(假定你运行在中文Windows下):
Private Sub Command1_Click()
Dim s As String, s2 As String
s = "CECAD7A8BCD2"
s2 = ""
For i = 1 To Len(s) Step 4
s2 = s2 + Chr("&H" + Mid(s, i, 4))
Next
Print s2
End Sub
我要实现一个类似Windows复制(移动)文件时的提示窗体,耗时很长,且要求中断后能继续未完成的操作,不知使用DoEvents从长循环中跳出后,程序将从何处开始继续执行,是否是从DoEvents所在的Sub开始?
事实上仅使用DoEvents,并不意味着从长循环中跳出。DoEvents只是允许用户选择其他按钮而已,不中断循环,不管用户如何操作,都继续执行DoEvents后面的语句,即使用户按下了中断按钮,你的循环仍然在继续,甚至你关闭了窗体,程序仍然继续在后台运行。正确的中断处理是这样的:
1、建立一个全局或窗体变量bRun。
2、在启动循环前设置bRun为True。
bRun = True
While bRun And (....)
....
DoEvents
Wend
...
3、在中断按钮Click事件中加入代码:
bRun = False
4、在Form_Unload事件中加入代码:
bRun = False
这样一旦用户按下了中断按钮,bRun = False,循环的条件就不满足了,所以退出循环,执行后续语句。你也可以采用下面的方式:
bRun = True
While ....
If Not bRun Then
Exit Sub
End If
....
DoEvents
Wend
...
关键问题归于doevents 函数
DoEvents函数的功能是:转让控制权,以便让操作系统处理其它的事件。
问:为什么要用doevents?
A.在需要用某一循环处理相当耗时或者很快速的代码时,就需要用到它,以便用户能在起处理过程中能做其他事情,即程序能被控制,而不是无响应状态
B.vb6.0中多线程vb代码极度不稳定,而且无法调试,所以vb中的多线程用的很少(注:是指vb的代码在多线程中运行时不稳定)
C.timer控件可以起到后台运行作用,但其是通过事件控制,一是不稳定,二是速度太慢,如果想用其处理高速又耗系统的代码更本不能达到预期的效果
下面将其某些用法和难点简介如下:
(注: '** 后面的代码表示如果在该处用了这个语句
以下代码中用到了一些api函数,请用vb附带的api浏览器查阅)
一. 基本用法:
1.窗体启动时如果要处理的事务太多或者用sleep函数暂停,造成其很久都不能出现时怎么办?
例如代码:
Private Sub Form_Load()
Show
'**DoEvents
Sleep 5000
End Sub
通常容易想到在sleep前加个show,但还是不能达到预想的效果,窗体虽然出来了,但好象只达到了一半,如果加上第3句,将看到效果大不相同
2.如果有个很耗时的循环导致程序不响应,怎么办?
例如:
Dim L As Long
For L = 1 To 1000000
'** DoEvents
Next L
如果无'**,在循环过程中程序无法处理事件,对于用户来说是不响应,无法控制的
3.想在循环中看到处理过程?
同样:
Dim L As Long
For L = 1 To 10000
'** DoEvents
Text1.Text=Cstr(l)
Next L
无'** 时将无法看到text1中的变化,而只在循环结束时看到最后结果
4.怎样中止循环?
如果有:
Private Sub Command3_Click()
Dim L As Long
Do
L = L + 1
Debug.Print L
DoEvents
Loop
End Sub
会发现当关闭窗口后,debug中的数据仍然在变化,说明并没结束
需要如下:
Dim IsExit As Boolean
Private Sub Command1_Click()
Dim L As Long
IsExit = False
Do While DoEvents
If IsExit = True Then Exit Do
L = L + 1
Loop
End Sub
Private Sub Command2_Click()''或者在form_unload模块中等等
IsExit = True
End Sub
其中 iXXXit是全局变量
<>有些人喜欢用end语句来结束程序,小程序固然可以,但当太大,或者调用了某些特殊的api函数后可能导致预想不到的错误,如果装载了许多东西在程序结束时不处理将卸载很慢,而且这种做法也极不符合正规软件的要求...总之end语句毛病很多,此不详谈,建议少使用甚至不使用
二. 其基本用法大概就这些,现在解析其中的一些[难点]
1.为什么还是不能结束?
代码如下:
Dim IsExit As Boolean
Private Sub Command1_Click()
Dim L As Long
IsExit = False
Do
If IsExit = True Then Exit Do '句0
DoEvents '** 句1
Text1.Text = CStr(L) '** 句2
L = L + 1
Loop
End Sub
Private Sub Form_Load()
Static N As Long
N = N + 1
MsgBox N
End Sub
Private Sub Form_Unload(Cancel As Integer)
IsExit = True
End Sub
运行结果:启动时msg显示1,点击command1,text1在变化
此时再点form右上角的小差(关闭窗体),发现vb运行控制上的按扭并没变化,说明程序还在运行.如果编译成程序后运行,按下ctrl+del+alt也可发现它还没结束.
通过读代码,并没发现错误,怎么回事?
关键在于 句2 访问了控件的属性
代码运行路径:当在doevents 时,程序释放控制权,可以接收事件消息,form-unload事件只能从此处产生,假设此时关闭form ,unload事件发生,即doevents后就运行unload代码,得到iXXXit=t,并且form卸载,代码返回到doevents 之后,运行 句2.注意现在form 已经卸载了,text1从哪里来呢?
于是form重新装载,代码跳到form_load模块运行,所以在关闭窗体后可以看到msg 显示2,此模块运行完后再继续句2后面的代码,当下次循环遇到 句0时退出循环
另:既然退出了循环,怎么还不能结束?
vb程序规定(其实其他的windows语言一样):窗体卸载时并不是立即卸载其模块代码,而只先卸载窗体中的控件和一些属性值,程序中最后一个窗体卸载时才完全卸载.
在这个单窗体程序中,form卸载时因为循环的控制无法卸载代码,失去了卸载代码的机会,导致再也不能卸载(因为没卸载代码,所以运行的 句2 是并不会出错)
另:既然再次运行了form_load代码,怎么看不见窗体?
因为程序启动时窗体的到显示的消息,而只运行此模块并没有(如果在msgbox n语句前加上show,就可以看到它了)
如何解决?
通过以上分析,应该很简单,把句1 和句2调换一下就可以了,关键:
<仔细分析代码是如何运行的,避免在form已经卸载了情况下访问控件>
2.用了doevents速度太慢了怎么办?
doevents的代价是速度变慢,但要程序响应又不得不用
其实doevents语句允许任何应用程序执行相关事件,而不仅仅是你自己的程序,所以变得很慢.
可以让它响应本程序事件动作,需要用到api函数GetInputState
例如用: If GetInputState() Then DoEvents '来代替doevents可使循环运行更快
3.既要同时响应事件又要控件不变化,怎么办?
例如在一个长的循环中向listview控件中添加记录,无doevents时程序无响应,但有它时控件又闪的厉害
解决办法:a.不一定每次循环都doevents,可以在适当时间时才用,至少没那么闪
b.应用api函数 ValidateRect 功能是使指定的矩型区域生效,通知Windows不对指定的区域进行重画 另:InvalidateRect 功能相反,同时需要用到函数 GetClientRect 取得指定对象的矩形区域 应用*rect函数指定listview的矩形区不重画,即可避免闪烁(但还是要注意恢复重画,否则看不见了真实效果)
4.控时循环和变速齿轮
请看下面的代码:
Option Explicit
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Dim IsExit As Boolean
Private Sub Command1_Click()
Dim L As Long
Dim Kt As Long
IsExit = False
Do
Kt = timeGetTime()
'do something
L = L + 1
Text1.Text = L
'DoEvents '句 1
While timeGetTime - Kt < 50 '句 2
'While Abs(timeGetTime - Kt) < 50 '句 3
'While Abs(timeGetTime - Kt) And (Not IsExit) < 50 '句 4
DoEvents '句 5
Wend
'DoEvents '句 6
If IsExit Then Exit Do
Loop
End Sub
Private Sub Form_Unload(Cancel As Integer)
IsExit = True
End Sub
其中可用的代码(除去加"'" 号的代码)就是通常的控时循环代码
运行代码并不会出现错误,但在循环过程,请开启变速齿轮看看
当关闭齿轮时,将发现text1.text停止了,别慌,等一段时间它又会继续(这要看你设定的时间,这里是50毫秒,如果设定的太长text1.text将半天都没变化,这是怎么回事?
变速齿轮在启动时将hook.dll映射到你的程序地址运行,更改了timegettime()函数获取的时间
如果在句2和句3间插入debug.print timegettime,timegettime-kt 将发现,在关闭齿轮的瞬间后者变成了负值,timegettime变小了,所以才造成需要等很久
如果是编写游戏,而用户开了齿轮,那可就惨了
解决方案:
a.用句3代替句2,这个方法最简便,虽然不符实,但不会出问题,建议使用
b.不要句5,换用句6(这样就能达到效果吗?) 因为齿轮还是从doevents语句运行时才能插的进来,所以只要kt=timegettime 和 timegettime之间没有doevents就不会出错
ab.两种方法都有些小问题,但无大碍,有兴趣者请自己分析
5.程序怎么"死了"?
这只是一些人编写时没注意到的小问题,提醒一下:
同样用上面的代码,如果设定的时间太短,以至在代码运行到句2时已经超时了,句5将不能运行了,当然程序就死了哦,以防万一,加上句1,所以此时也只能用a方案来解决齿轮的问题了
有必要用句4代替句3 吗? 除非你设定的时间太长,人家想关闭你的程序要等上好半天
[前言:]在这个专题中我收集了一些在Visual Basic编程中的常见问题,这些问题均来自论坛,本专题以解决实际问题主要目的。
问:VB中如何使用C++类?
答:把vc的类编译成dll文件,这样的话就可以使用,最好是作为组件com来使用。
VB调用DLL的方法和调用Windows API的方法是一样的,一般在VB的书中有介绍。对于上面一个例子,先要声明VC函数:
Declare Function sample Lib "mydll.dll" (ByVal nLen As Integer, buffer As Integer) As Integer
这里mydll.dll是你的dll的名字。你可能已经注意到了两个参数的声明有所不同,第一个参数加上了ByVal。规则是这样的:如果在VC中某个参数声明为指针和数组,就不加ByVal,否则都要加上ByVal。在VB中调用这个函数采用这样的语法:
sample 10, a(0)
这里的a()数组是用来存放数据的,10为数组长度,这里的第二个参数不能是a(),而必须是要传递的数据中的第一个。这是VB编程的关键。
下面在说几个可能遇到的问题。一个问题是VB可能报告找不到dll,你可以把dll放到system目录下,并确保VB的Declare语句正确。另一个问题是VB报告找不到需要的函数,这通常是因为在VC中*.def文件没设置。第三种情况是VB告诉不能进行转换,这可能是在VC中没有加上__stdcall关键字,也可能是VB和VC的参数类型不一致,注意在VC中int是4个字节(相当于VB的Long),而VB的Integer只有2个字节。必须保证VB和VC的参数个数相同,所占字节数也一致。最后一个要注意的问题是VC中绝对不能出现数组越界的情况,否则会导致VB程序崩溃。
问:怎样用编程方式在窗体上创建一个label或textbox?
答:代码如下:
'声明
Private WithEvents NewButton As ComandButton
'1,添加
Set NewButton=Controls.Add("VB.CommandButton","cmdNew",Me)
NewButton.Move 0,0,Width,Height
NewButton.Visible=True
'2,删除
Controls.Remove NewButton
Set NewButton=Nothing
问:如何把一个已编译的EXE程序打包到VB中再编译呢?
答:你需要先编写一个程序B,并将其编译为EXE。如果你希望今后允许程序A定制程序B的某个文本框,可以先将该文本框的Caption属性设置为“Change Me!Change Me!”之类首先定义好的字符串。然后程序A以二进制方式打开程序B,然后在其中查找“Change Me!Change Me!”字符串,并将其改变为程序A中设置的文字。但这种方法有几个缺点:
1、字符串长度有限;
2、对于VB来说,编译后有的中文字符串编译后格式有些办法,不好处理。
也可以采用另一种办法。程序A将设置信息保存在程序B文件的尾部。用程序B以二进制方式打开其自己的EXE文件,利用Seek命令移动到指定位置读出设置信息。如:
Dim s As String * 100
On Error GoTo ErrHandler
Open App.Path + "" + App.EXEName + ".EXE" For Binary As #1
Seek 1, 20480 ' 这里是EXE文件的长度
Get 1, , s
Label1.Caption = s
Close #1
Exit Sub
问:如何确定EXE文件的长度的具体数值呢?
答:先编译程序B,看看程序B的EXE文件的长度,例如17234。然后将上面的20480改为17234,再编译一次程序B。
问:关于程序热键公用问题?
如果两个程序都用到了相同的热键 比如说ctrl+enter 当这2个程序同时运行起来的时候,怎么才能让只有一个程序接受热键,换句话说就是谁在前台(前面 激活状态)谁就使用这个热键,谁在后台 或者最小化等非激活状态 那么就不使用这个热键! 怎么能做到呢?
答:代码如下:
Private Sub Text2_KeyDown(KeyCode As Integer, Shift As Integer)
If Shift = 2 Then
If KeyCode = vbKeyReturn Then
Text1.Text = Text2.Text
Text2.Text = ""
End If
End If
End Sub
问:在用二进制binary,写入一个字串时(比如"你好")后,如何用get读出来?
答:在VB读和写有专用的语法,或者直接使用FSO,如:
open 文件所在路径 for output as #1
write #1,"你好"
close (1)
'这是写文件操作
读的话类同,用line input读出来就可以了。
问:怎样让Listbox中的滚动条的颜色与Listbox的背景颜色一致?
答:其实要看每个控件是否可以设置颜色,一般检查一下控件的backcorlor和forecolor属性就可以了,有的话,自己设置吧。
问:怎么让form时刻处于最上方,formName.show不能做到这一点?
答:代码如下:
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const HWND_TOPMOST = -1
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOSIZE = &H1
Private Sub Form_Load()
SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, Me.Width, Me.Height, SWP_NOMOVE Or SWP_NOSIZE
End Sub
问:定义在类中的Procedure和Function有什么区别? 他们是不是都可以单独存在?
答:procedure是声明一个过程,没有返回值.
function是声明一个函数,有返回值的.
问:VB中在textbox中查找单个的字符或字符串有什么好方法? 如:
在textbox中查找: 如textbox.text="12345678"查找"78"或"8" 代码怎么写?
答:用instr函数
例:
dim i as integer
text1.text="12345678"
i=instr(text1.text,"78"
i 的值就是在textBox中找到的字符串"78"的第一次出现的位置.
问: 怎样判断程序是否在运行,如果运行怎样关闭他呢?
答:先用findwindow得到你要查的窗口的hwnd,然后用sendmessge yourform.hwnd,wm_close,0
private button1_click()
dim tmp as long
tmp=findwindow(vbnullstring,"程序的窗口名VB中FORM的NAME属性值")
if tmp > 0 then
sendmessage tmp,wm_close,0
else
msgbox "Sorry!Don't find formname"
end if
end sub
问:如何用vb实现真正的多线程而不是多进程?
答:1.最好把代码放在Active Dll里,编译时使用p代码方式,至少要装vbsp3以上
2.线程函数里不能有VB的内置函数,比如left,trim等
3.创建线程CreateThread的参数不要使用ByVal &0,使用变量
主程序退出时要使用TerminateProcess(GetCurrentProcess, ByVal 0&)强行结束当前进程,否则有可能出错,这是两个API函数,请查相关资料
问:局域网点对点传输,如何数据加密?怎样实现?
答:在text1中输入你要加密的数据(16进制)
将它和4E进行异或
再按就把数据还原了
Private Sub Command1_Click()
tmp = Hex(Val("&H" & Text1.Text) Xor Val("&H" & "4E"))
Text1.Text = tmp
End Sub
问:如何实现鼠标取词?
'所要用到的函数、常量、类型
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal x As Long, ByVal y As Long) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Const WM_GETTEXT = &HD
Private Const WM_SETTEXT = &HC
Private Type POINTAPI
x As Long
y As Long
End Type
Private Sub Form_Load()
End Sub
Private Sub Timer1_Timer()
'
' 代码就是这么简单,你好好研究一下吧。
'
'
Dim Shu As POINTAPI
Dim Str As String * 300
GetCursorPos Shu
SendMessage WindowFromPoint(Shu.x, Shu.y), WM_GETTEXT, 299, ByVal Str
Label1.Caption = Str
End Sub
根据代码加入相应控件,timer1的interval的属性为100再加入把当前窗口置顶就是一个完美的简单的取词工具了!
问:VB调DLL时,如何传Structure?
答:在DLL里定义时应该用指针作参数,在VB里面,只要把结构变量定义成 Long 类型就可以了,调用的时候传入地址,就是在调用的时候,在参数前面加 ByVal。
问:如何可以在VB中实现对整个系统鼠标和键盘的屏蔽
答:我们常见一些导览系统或教学系统,会自动移动Mouse与Keyin字,而那个时候,我们不管Keyin或动Mouse都没有效,直到完成了导览系统的某个动作後才让使用者可以移动Mouse与做Keyin的动作;想做到这个,要借重JournalPlayBack Hook。
JournalPlayBack Hook,它和JournalRecord Hook合称Journal Hook,它们作用范围是整个System,也就是挂上这个Hook後,影响的层面不单是这个Process,而是有的Process,而这两Hook又不用写在Dll之中,所以很好用。
首先我们要知道由键盘和Mouse输入等的硬体讯息,会存到一个System Queue而後OS会该System Queue看有没有讯息在其中,若有则撷取出来,看目前Active的Window是谁将讯息Post给它。而挂上JournalRecord Hook时,当有讯息被撷取出来时,会先执行他们所设定的Hook Function(在vb中,一定要放在.BAS档之中)。这可以做什麽事呢?
例如我们可以Check整个系统是否有按了键盘或有没有移动Mouse(一般来说,KeyUp,KeyDown, MouseMove等Event只有Form在Active 时才收得到,挂上JournalRecord hook後,执行Hook的thread便能收到所有这些讯息)。再如,它既然能收到Keyboard、Mouse的讯息,那便可以将收到的讯息记录起来(记录於Memory或Disk都可以),之後再依方才的顺序重新将讯息放送出来,可重新执行方才的动作(这不就是巨集的作法吗),或许它叫JournalRecord便是这个原因。再来便是播放记录讯息的问题了,如果一面播放,一面有其他讯息插队(如移动Mouse),那就不对了,所以JournalPlayBack这个Hook它会让Mouse、Keyboard都失效,当OS 要求读System Queue时,便会启动这个Hook,就在此时,我们可以把方才记录起来的讯息丢出一个出来,OS再要求读System Queue时,再丢下一个讯息,如此达重播的效果(所以才叫JournalPlayBack),正因它会让键盘、Mouse失效,拿它来做导览、教学系统的自动Move Mouse或文字显示是最适合的了。
Mouse的自动导引系统制作方式,可叁考如何自动移动Mouse
'以下在.Bas中
Declare Sub Sleep Lib "KERNEL32" (ByVal dwMilliseconds As Long)
Const WM_MOUSELAST = &H209
Const WM_MOUSEFIRST = &H200
Public Const WM_KEYLAST = &H108
Public Const WM_KEYFIRST = &H100
Public Const WH_JOURNALRECORD = 0
Public Const WH_JOURNALPLAYBACK = 1
Type EVENTMSG
message As Long
paramL As Long
paramH As Long
time As Long
hwnd As Long
End Type
Declare Function SetWindowsHookEx Lib "user32" Alias _
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _
ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _
ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
Public hNxtHook As Long ' handle of Hook Procedure
Public msg As EVENTMSG
Sub EnableHook()
hNxtHook = SetWindowsHookEx(WH_JOURNALPLAYBACK, AddressOf HookProc, App.hInstance, 0)
End Sub
Sub FreeHook()
Dim ret As Long
ret = UnhookWindowsHookEx(hNxtHook)
End Sub
Function HookProc(ByVal code As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
HookProc = CallNextHookEx(hNxtHook, code, wParam, lParam)
End Function
'以下在Form中,需求:一个Command1, 一个text1
Private Sub Command1_Click()
Dim str5 As String, len5 As Long, i As Long
Call EnableHook
str5 = "这是一个测试JournalPlayBackHook的程式"
len5 = Len(str5)
For i = 1 To len5
Text1.Text = Mid(str5, 1, i)
Text1.Refresh
Sleep (200)
Next
Call FreeHook
End Sub
问:如何把picture控件中图形数据写成“流”?
答:可以使用adodb.stream对象。
上传图片或显示SWF的时候都希望得到它的高度和宽度,基本原理使用Adodb.Stream读二进制文件然后进行解析,然后返回一数组:
第一个元素为类型(BMP JPG PNG GIF SWF)
第二个元素为宽度{width}
第三个元素为高度{height}
第四个元素为width={width},height={height}式字符串
Class qswhImg
dim aso
Private Sub Class_Initialize
set aso=CreateObject("Adodb.Stream")
aso.Mode=3
aso.Type=1
aso.Open
End Sub
Private Sub Class_Terminate
set aso=nothing
End Sub
Private Function Bin2Str(Bin)
Dim I, Str
For I=1 to LenB(Bin)
clow=MidB(Bin,I,1)
if ASCB(clow)<128 then
Str = Str & Chr(ASCB(clow))
else
I=I+1
if I <= LenB(Bin) then Str = Str & Chr(ASCW(MidB(Bin,I,1)&clow))
end if
Next
Bin2Str = Str
End Function
Private Function Num2Str(num,base,lens)
'qiushuiwuhen (2002-8-12)
dim ret
ret = ""
while(num>=base)
ret = (num mod base) & ret
num = (num - num mod base)/base
wend
Num2Str = right(string(lens,"0") & num & ret,lens)
End Function
Private Function Str2Num(str,base)
'qiushuiwuhen (2002-8-12)
dim ret
ret = 0
for i=1 to len(str)
ret = ret *base + cint(mid(str,i,1))
next
Str2Num=ret
End Function
Private Function BinVal(bin)
'qiushuiwuhen (2002-8-12)
dim ret
ret = 0
for i = lenb(bin) to 1 step -1
ret = ret *256 + ascb(midb(bin,i,1))
next
BinVal=ret
End Function
Private Function BinVal2(bin)
'qiushuiwuhen (2002-8-12)
dim ret
ret = 0
for i = 1 to lenb(bin)
ret = ret *256 + ascb(midb(bin,i,1))
next
BinVal2=ret
End Function
Function getImageSize(filespec)
'qiushuiwuhen (2002-9-3)
dim ret(3)
aso.LoadFromFile(filespec)
bFlag=aso.read(3)
select case hex(binVal(bFlag))
case "4E5089":
aso.read(15)
ret(0)="PNG"
ret(1)=BinVal2(aso.read(2))
aso.read(2)
ret(2)=BinVal2(aso.read(2))
case "464947":
aso.read(3)
ret(0)="GIF"
ret(1)=BinVal(aso.read(2))
ret(2)=BinVal(aso.read(2))
case "535746":
aso.read(5)
binData=aso.Read(1)
sConv=Num2Str(ascb(binData),2 ,8)
nBits=Str2Num(left(sConv,5),2)
sConv=mid(sConv,6)
while(len(sConv) binData=aso.Read(1)
sConv=sConv&Num2Str(ascb(binData),2 ,8)
wend
ret(0)="SWF"
ret(1)=int(abs(Str2Num(mid(sConv,1*nBits+1,nBits),2)-Str2Num(mid(sConv,0*nBits+1,nBits),2))/20)
ret(2)=int(abs(Str2Num(mid(sConv,3*nBits+1,nBits),2)-Str2Num(mid(sConv,2*nBits+1,nBits),2))/20)
case "FFD8FF":
do
do: p1=binVal(aso.Read(1)): loop while p1=255 and not aso.EOS
if p1>191 and p1<196 then exit do else aso.read(binval2(aso.Read(2))-2)
do:p1=binVal(aso.Read(1)):loop while p1<255 and not aso.EOS
loop while true
aso.Read(3)
ret(0)="JPG"
ret(2)=binval2(aso.Read(2))
ret(1)=binval2(aso.Read(2))
case else:
if left(Bin2Str(bFlag),2)="BM" then
aso.Read(15)
ret(0)="BMP"
ret(1)=binval(aso.Read(4))
ret(2)=binval(aso.Read(4))
else
ret(0)=""
end if
end select
ret(3)="width=""" & ret(1) &""" height=""" & ret(2) &""""
getimagesize=ret
End Function
End Class
使用范例(读某目录下所有图片的宽度):
set qswh=new qswhImg
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.GetFolder(server.mappath("."))
Set fc = f.Files
For Each f1 in fc
ext=fso.GetExtensionName(f1.path)
select case ext
case "gif","bmp","jpg","png":
arr=qswh.getImageSize(f1.path)
response.write "
" & arr(0) & " " & arr(3) & ":" & f1.name & " width:" & arr(1) & " height:" & arr(2)
case "swf"
arr=qswh.getimagesize(f1.path)
response.write "
" & arr(0) & " " & arr(3) & ":" & f1.name & " width:" & arr(1) & " height:" & arr(2)
end select
Next
Set fc=nothing
Set f=nothing
Set fso=nothing
Set qswh=nothing
问题一:Visual Basic 导出到 Excel 提速之法
办法如下:
Excel 是一个非常优秀的报表制作软件,用VBA可以控制其生成优秀的报表,本文通过添加查询语句的方法,即用Excel中的获取外部数据的功能将数据很快地从一个查询语句中捕获到EXCEL中,比起往每个CELL里写数据的方法提高许多倍。
将下文加入到一个模块中,屏幕中调用如下ExporToExcel("select * from table")则实现将其导出到EXCEL中
Public Function ExporToExcel(strOpen As String)
'*********************************************************
'* 名称:ExporToExcel
'* 功能:导出数据到EXCEL
'* 用法:ExporToExcel(sql查询字符串)
'*********************************************************
Dim Rs_Data As New ADODB.Recordset
Dim Irowcount As Integer
Dim Icolcount As Integer
Dim xlApp As New Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlQuery As Excel.QueryTable
With Rs_Data
If .State = adStateOpen Then
.Close
End If
.ActiveConnection = Cn
.CursorLocation = adUseClient
.CursorType = adOpenStatic
.LockType = adLockReadOnly
.Source = strOpen
.Open
End With
With Rs_Data
If .RecordCount < 1 Then
MsgBox ("没有记录!")
Exit Function
End If
'记录总数
Irowcount = .RecordCount
'字段总数
Icolcount = .Fields.Count
End With
Set xlApp = CreateObject("Excel.Application")
Set xlBook = Nothing
Set xlSheet = Nothing
Set xlBook = xlApp.Workbooks().Add
Set xlSheet = xlBook.Worksheets("sheet1")
xlApp.Visible = True
'添加查询语句,导入EXCEL数据
Set xlQuery = xlSheet.QueryTables.Add(Rs_Data, xlSheet.Range("a1"))
With xlQuery
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = True
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
End With
xlQuery.FieldNames = True '显示字段名
xlQuery.Refresh
With xlSheet
.Range(.Cells(1, 1), .Cells(1, Icolcount)).Font.Name = "黑体"
'设标题为黑体字
.Range(.Cells(1, 1), .Cells(1, Icolcount)).Font.Bold = True
'标题字体加粗
.Range(.Cells(1, 1), .Cells(Irowcount + 1, Icolcount)).Borders.LineStyle = xlContinuous
'设表格边框样式
End With
With xlSheet.PageSetup
.LeftHeader = "" & Chr(10) & "&""楷体_GB2312,常规""&10公司名称:" ' & Gsmc
.CenterHeader = "&""楷体_GB2312,常规""公司人员情况表&""宋体,常规""" & Chr(10) & "&""楷体_GB2312,常规""&10日 期:"
.RightHeader = "" & Chr(10) & "&""楷体_GB2312,常规""&10单位:"
.LeftFooter = "&""楷体_GB2312,常规""&10制表人:"
.CenterFooter = "&""楷体_GB2312,常规""&10制表日期:"
.RightFooter = "&""楷体_GB2312,常规""&10第&P页 共&N页"
End With
xlApp.Application.Visible = True
Set xlApp = Nothing '"交还控制给Excel
Set xlBook = Nothing
Set xlSheet = Nothing
End Function
注:须在程序中引用'Microsoft Excel 9.0 Object Library'和ADO对象,机器必装Excel 2000
本程序在Windows 98/2000,VB 6 下运行通过。
问题二:vb中从域名得到IP及从IP得到域名
办法如下:
Private Const WS_VERSION_REQD = &H101
Private Const WS_VERSION_MAJOR = WS_VERSION_REQD &H100 And &HFF&
Private Const WS_VERSION_MINOR = WS_VERSION_REQD And &HFF&
Private Const MIN_SOCKETS_REQD = 1
Private Const SOCKET_ERROR = -1
Private Const WSADescription_Len = 256
Private Const WSASYS_Status_Len = 128
Private Type HOSTENT
hname As Long
hAliases As Long
hAddrType As Integer
hLength As Integer
hAddrList As Long
End Type
Private Type WSADATA
wversion As Integer
wHighVersion As Integer
szDescription(0 To WSADescription_Len) As Byte
szSystemStatus(0 To WSASYS_Status_Len) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpszVendorInfo As Long
End Type
Private Declare Function gethostbyaddr Lib "WSOCK32.DLL" (addr As Any, ByVal _
byteslen As Integer, addrtype As Integer) As Long
Private Declare Function WSAGetLastError Lib "WSOCK32.DLL" () As Long
Private Declare Function WSAStartup Lib "WSOCK32.DLL" (ByVal _
wVersionRequired&, lpWSAData As WSADATA) As Long
Private Declare Function WSACleanup Lib "WSOCK32.DLL" () As Long
Private Declare Function gethostbyname Lib "WSOCK32.DLL" (ByVal _
hostname$) As Long
Private Declare Sub RtlMoveMemory Lib "KERNEL32" (hpvDest As Any, _
ByVal hpvSource&, ByVal cbCopy&)
Function hibyte(ByVal wParam As Integer) '获得整数的高位
hibyte = wParam &H100 And &HFF&
End Function
Function lobyte(ByVal wParam As Integer) '获得整数的低位
lobyte = wParam And &HFF&
End Function
Function SocketsInitialize()
Dim WSAD As WSADATA
Dim iReturn As Integer
Dim sLowByte As String, sHighByte As String, sMsg As String
iReturn = WSAStartup(WS_VERSION_REQD, WSAD)
If iReturn <> 0 Then
MsgBox "Winsock.dll 没有反应."
End
End If
If lobyte(WSAD.wversion) < WS_VERSION_MAJOR Or (lobyte(WSAD.wversion) = WS_VERSION_MAJOR And hibyte(WSAD.wversion) < WS_VERSION_MINOR) Then
sHighByte = Trim$(str$(hibyte(WSAD.wversion)))
sLowByte = Trim$(str$(lobyte(WSAD.wversion)))
sMsg = "Windows Sockets版本 " & sLowByte & "." & sHighByte
sMsg = sMsg & " 不被winsock.dll支持 "
MsgBox sMsg
End
End If
If WSAD.iMaxSockets < MIN_SOCKETS_REQD Then
sMsg = "这个系统需要的最少Sockets数为 "
sMsg = sMsg & Trim$(str$(MIN_SOCKETS_REQD))
MsgBox sMsg
End
End If
End Function
Sub SocketsCleanup()
Dim lReturn As Long
lReturn = WSACleanup()
If lReturn <> 0 Then
MsgBox "Socket错误 " & Trim$(str$(lReturn)) & " occurred in Cleanup "
End
End If
End Sub
Sub Form_Load()
'初始化Socket
SocketsInitialize
End Sub
Private Sub Form_Unload(Cancel As Integer)
'清除Socket
SocketsCleanup
End Sub
Private Function getip(name As String) As String
Dim hostent_addr As Long
Dim host As HOSTENT
Dim hostip_addr As Long
Dim temp_ip_address() As Byte
Dim i As Integer
Dim ip_address As String
hostent_addr = gethostbyname(name)
If hostent_addr = 0 Then
getip = "" '主机名不能被解释
Exit Function
End If
RtlMoveMemory host, hostent_addr, LenB(host)
RtlMoveMemory hostip_addr, host.hAddrList, 4
ReDim temp_ip_address(1 To host.hLength)
RtlMoveMemory temp_ip_address(1), hostip_addr, host.hLength
For i = 1 To host.hLength
ip_address = ip_address & temp_ip_address(i) & "."
Next
ip_address = Mid$(ip_address, 1, Len(ip_address) - 1)
getip = ip_address
End Function
Private Sub Command1_click()
Dim str As String
str = getip(Text1.Text)
If str = "" Then
Text2.Text = "主机名不能被解释"
Else
Text2.Text = str
End If
End Sub
Private Function getname(addrstr As String) As String
Dim hostent_addr As Long
Dim host As HOSTENT
Dim addr(0 To 50) As Byte
Dim addrs As String
Dim hname(1 To 50) As Byte
Dim str As String
Dim i As Integer, j As Integer
Dim temp_int As Integer
Dim byt As Byte
str = Trim$(addrstr)
i = 0
j = 0
Do
temp_int = 0
i = i + 1
Do While Mid$(str, i, 1) >= "0" And Mid$(str, i, 1) <= "9" And i <= Len(str)
temp_int = temp_int * 10 + Mid$(str, i, 1)
i = i + 1
Loop
If temp_int <= 255 Then
addr(j) = temp_int
j = j + 1
End If
Loop Until Mid$(str, i, 1) <> "." Or i > Len(str) Or temp_int > 255
If temp_int > 255 Then
getname = "地址非法"
Exit Function
End If
hostent_addr = gethostbyaddr(addr(0), j, 2)
If hostent_addr = 0 Then
getname = "此地址无法解析"
Exit Function
End If
RtlMoveMemory host, hostent_addr, LenB(host)
RtlMoveMemory hname(1), host.hname, 50
j = 51
For i = 1 To 50
If hname(i) = 0 Then
j = i
End If
If i >= j Then
hname(i) = 32
End If
Next i
getname = Trim$(StrConv(hname, vbUnicode))
End Function
Private Sub Command2_Click()
Dim name As String
name = getname(Text2.Text)
If name = "" Then
name = "此地址没有域名"
End If
Text1.Text = name
End Sub
问题三:怎么把图片加入到数据库里面
办法如下:
Private Sub Command3_Click()
Dim conn As New ADODB.Connection
conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:1.mdb;Persist Security Info=False"
conn.Execute "create table a (b longbinary)"
End Sub
Private Sub Command4_Click()
Set b = New ADODB.Recordset
Set c = New ADODB.Stream
c.Mode = adModeReadWrite
c.Type = adTypeBinary
c.Open
c.LoadFromFile "c:1.bmp"
b.Open "select * from a", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:1.mdb;Persist Security Info=False", adOpenDynamic, adLockOptimistic
b.AddNew
b.Fields.Item(0).Value = c.Read()
b.Update
b.Close
Set b = New ADODB.Recordset
b.Open "select * from a", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:1.mdb;Persist Security Info=False", adOpenKeyset, adLockOptimistic
MsgBox b.RecordCount
b.MoveLast
c.Write (b.Fields.Item(0).Value)
c.SaveToFile "c:aa.bmp", adSaveCreateOverWrite
Picture1.Picture = LoadPicture("c:aa.bmp")
End Sub
问题四:VB6.0中如何快速实现大面积不规则区域的填充
办法如下:
一、引言
区域填充是指先将区域内的一个像素 ,一般称为种子点赋予给定的颜色和辉亮,然后将该颜色扩展到整个区域内的过程。
二、已有的填充算法及缺点
1.扫描线法
扫描线法可以实现已知多边形域边界的填充,多边形域可以是凹的、凸的、还可以是带孔的。该填充方法是按扫描线的顺序,计算扫描线与待填充区域的相交区间,再用要求的颜色显示这些区间的像素,即完成填充工作。这里区间的端点通过计算扫描线与多边形边界线的交点获得。所以待填充区域的边界线必须事先知道,因此它的缺点是无法实现对未知边界的区域填充。
2.边填充算法
边填充的基本思想是:对于每一条扫描线和每条多边形边的交点,将该扫描线上交点右方的所有像素取补。对多边形的每条边作些处理,多边形的顺序随意。该算法适用于具有帧缓冲器的图形系统,按任意顺序处理多边形的边。处理每条边时,仅访问与该边有交的扫描线上交点右方的像素。所有的边都被处理之后,按扫描线顺序读出帧缓冲器的内容,送入显示设备。该算法的优点是简单,缺点是对于复杂图形,每一像素可能被访问多次,重要的是必须事先知道待填充多边形的边界,所以在填充未知边界的区域时不适用。
3.递归算法
递归算法的优点是编程实现时,语言简洁。但在VB6.0实际编程实现时,这种递归算法填充稍稍大一些的图形就会出现堆栈溢出现象,据我们的实践证明,递归算法只能连续递归深度在2090次左右,也就是说,如果待填充的图形大于二千多个像素那么堆栈溢出。下面给出八连通填充方法的VB程序实现(四连通算法同理)。
Public Sub area(p, q As Integer)
If ((imagepixels(0, p, q) = red1) And (imagepixels(1, p, q) = green1) And (imagepixels(2, p, q) = blue1)) Then
imagepixels(0, p, q) = 0: imagepixels(2, p, q) = 0: imagepixels(1, p, q) = 0
Picture1.PSet (p, q), RGB(0, 0, 0)
Call area(p + 1, q): Call area(p, q + 1)
Call area(p - 1, q): Call area(p, q - 1)
Call area(p + 1, q + 1): Call area(p + 1, q - 1)
Call area(p - 1, q + 1): Call area(p - 1, q - 1)
Else: Exit Sub
End If
End Sub
三、算法的基本思想
本算法采用两个队列(FIFO)filled和unfilled来实现区域填充。设计步骤如下:
1. 找出该区域内部任意一点,作为填充种子。
2. 填充该点,并把该点存入队列filled。
3. 按逆时针,判断该点的上、右、下、左邻像素是否在filled队列内。如果在filled,说明该相邻点已填充,若不在filled队列内,则判断该相邻点在未填充队列unfilled,如果不在则将该相邻点存入unfilled。
4. 判断未填充队列是否为空,若不空,则从队列unfilled中取出头元素,转向第三步。若为空则表示已完成所有像素填充,结束程序。
四、程序实现及说明
本算法定义的队列突破了递归算法中受堆栈空间大小的限制的束缚,因为它直接占用内存空间,与堆栈大小无关。以下源程序在Window 2000环境下用VB6.0编程实现。
建立如图所示标准窗体并画上控件-2个CommandButton控件和一个PictureBox控件,调整大小,并设置控件的属性。
通用声明
Dim Xx As Integer, Yy As Integer
Dim Array1(9000, 2), Array2(9000, 2) As Integer
4.2 采集
Private Sub Command1_Click()
Picture1.MousePointer = 2
End Sub
4.3 选取种子
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Xx = X '选择并记录种子点的位置
Yy = Y
End Sub
4.4 区域填充
Private Sub Command2_Click()
Dim i, j, k As Integer, BoundPoint1, BoundPoint2 As Integer
Dim Flag As Boolean, Pixel As Long
Dim Red, Green, Blue As Integer, Bound As Boolean
Flag = True '初始化
i = Xx: j = Yy: BoundPoint1 = 1
Array1(1, 1) = i
Array1(1, 2) = j
'搜索边界点
Do While BoundPoint1 > 0
BoundPoint2 = 0
For k = 1 To BoundPoint1
i = Array1(k, 1)
j = Array1(k, 2)
'搜索右点
Pixel& = Picture1.Point(i, j + 1)
Call IsBound(Pixel&, Bound)
If Not Bound Then
BoundPoint2 = BoundPoint2 + 1
Array2(BoundPoint2, 1) = i
Array2(BoundPoint2, 2) = j + 1
Picture1.PSet (i, j + 1), RGB(255, 255, 255)
End If
'搜索左邻点
Pixel& = Picture1.Point(i, j - 1)
Call IsBound(Pixel&, Bound)
If Not Bound Then
BoundPoint2 = BoundPoint2 + 1
Array2(BoundPoint2, 1) = i
Array2(BoundPoint2, 2) = j - 1
Picture1.PSet (i, j - 1), RGB(255, 255, 255)
End If
'搜索上邻点
Pixel& = Picture1.Point(i - 1, j)
Call IsBound(Pixel&, Bound)
If Not Bound Then
BoundPoint2 = BoundPoint2 + 1
Array2(BoundPoint2, 1) = i - 1
Array2(BoundPoint2, 2) = j
Picture1.PSet (i - 1, j), RGB(255, 255, 255)
End If
'搜索下邻点
Pixel& = Picture1.Point(i + 1, j)
Call IsBound(Pixel&, Bound)
If Not Bound Then
BoundPoint2 = BoundPoint2 + 1
Array2(BoundPoint2, 1) = i + 1
Array2(BoundPoint2, 2) = j
Picture1.PSet (i + 1, j), RGB(255, 255, 255)
End If
Next k
'数组array2 中的数据传给array1
BoundPoint1 = BoundPoint2
For k = 1 To BoundPoint1
Array1(k, 1) = Array2(k, 1)
Array1(k, 2) = Array2(k, 2)
Next k
Picture1.Refresh
Loop
End Sub
Public Sub IsBound(P As Long, Bound As Boolean) '判断P是否为边界点
Red = P& Mod 256
Bound = False
Green = ((P& And &HFF00) / 256&) Mod 256&
Blue = (P& And &HFF0000) / 65536
If Red = 255 And Green = 255 And Blue = 255 Then
Bound = True
End If
End Sub
问题五:如何获取打印机纸张信息?
办法如下:
Option Explicit
Private Const DC_MAXEXTENT = 5
Private Const DC_MINEXTENT = 4
Private Const DC_PAPERNAMES = 16
Private Const DC_PAPERS = 2
Private Const DC_PAPERSIZE = 3
Private Declare Function DeviceCapabilities Lib "winspool.drv" Alias "DeviceCapabilitiesA" (ByVal lpDeviceName As String, ByVal lpPort As String, ByVal iIndex As Long, lpOutput As Any, lpDevMode As Any) As Long
Private Type POINTS
x As Long
y As Long
End Type
'***********************************************************
'* 名称:GetPaperInfo
'* 功能:得到打印机低张信息
'* 用法:GetPaperInfo(控件名)
'* 描述:如在 form_load()中调用GetPaperInfo MSHFlexGrid1
'***********************************************************
Public Function GetPaperInfo(Flex As MSHFlexGrid) As Boolean
Dim i As Long, ret As Long
Dim Length As Integer, Width As Integer
Dim PaperNo() As Integer, PaperName() As String, PaperSize() As POINTS
With Flex
.FormatString = "^纸张编号|^纸张名称|^纸张长度|^纸张宽度"
For i = 0 To .Cols - 1
.ColWidth(i) = 1700
Next i
.AllowUserResizing = flexResizeColumns
.Left = 0
End With
'支持最大打印纸:
ret = DeviceCapabilities(Printer.DeviceName, "LPT1", DC_MAXEXTENT, ByVal 0&, ByVal 0&)
Length = ret 65536
Width = ret - Length * 65536
'支持最小打印纸:
ret = DeviceCapabilities(Printer.DeviceName, "LPT1", DC_MINEXTENT, ByVal 0&, ByVal 0&)
Length = ret 65536
Width = ret - Length * 65536
'支持纸张种类数
ret = DeviceCapabilities(Printer.DeviceName, "LPT1", DC_PAPERS, ByVal 0&, ByVal 0&)
'纸张编号
ReDim PaperNo(1 To ret) As Integer
Call DeviceCapabilities(Printer.DeviceName, "LPT1", DC_PAPERS, PaperNo(1), ByVal 0&)
'纸张名称
Dim arrPageName() As Byte
Dim allNames As String
Dim lStart As Long, lEnd As Long
ReDim PaperName(1 To ret) As String
ReDim arrPageName(1 To ret * 64) As Byte
Call DeviceCapabilities(Printer.DeviceName, "LPT1", DC_PAPERNAMES, arrPageName(1), ByVal 0&)
allNames = StrConv(arrPageName, vbUnicode)
'loop through the string and search for the names of the papers
i = 1
Do
lEnd = InStr(lStart + 1, allNames, Chr$(0), vbBinaryCompare)
If (lEnd > 0) And (lEnd - lStart - 1 > 0) Then
PaperName(i) = Mid$(allNames, lStart + 1, lEnd - lStart - 1)
i = i + 1
End If
lStart = lEnd
Loop Until lEnd = 0
'纸张尺寸
ReDim PaperSize(1 To ret) As POINTS
Call DeviceCapabilities(Printer.DeviceName, "LPT1", DC_PAPERSIZE, PaperSize(1), ByVal 0&)
'显示在表格中
For i = 1 To ret
Flex.AddItem PaperNo(i) & vbTab & PaperName(i)
& vbTab & PaperSize(i).y & vbTab & PaperSize(i).x
Next i
End Function
问题六:在DataGrid中显示DataCombo
办法如下:
DataGrid1_MouseDown
Dim col As MSDataGridLib.Column
Set col = DataGrid1.Columns(DataGrid1.col)
If col.Caption = "MS" And DataGrid1.CurrentCellVisible Then
DataCombo1.Left = DataGrid1.Left + col.Left + 2 * Screen.TwipsPerPixelX
DataCombo1.Top = DataGrid1.Top + DataGrid1.RowTop(DataGrid1.Row) + 2 * Screen.TwipsPerPixelX
DataCombo1.Width = col.Width - 2 * Screen.TwipsPerPixelX
DataCombo1.Text = col.Text
DataCombo1.Visible = True
DataCombo1.SetFocus
DataCombo1.ZOrder
Else
DataCombo1.Visible = False
End If
问题七:如何识别操作系统版本?
办法如下:
'引用控件 Microsoft SysInfo Control 6.0
Dim OS As String
With SysInfo1
Select Case .OSPlatform
Case 0: OS = "Win32"
Case 1:
Select Case .OSVersion
Case 4: OS = "Win 95"
Case 4.1: OS = "Win 98"
Case 4.9: OS = "Wim Me"
End Select
Case 2:
Select Case .OSVersion
Case 4: OS = "Win NT"
Case 5: OS = "Win 2000"
Case 6: OS = "Win XP"
End Select
End Select
MsgBox "Build:" & .OSBuild & vbNewLine & _
"Platform:" & OS & "(" & .OSPlatform & ")" & vbNewLine & _
"Version:" & .OSVersion
End With
问题八:如何实现遍历文件夹中的所有文件
办法如下:
把下面放到模块中
Option Explicit
Public Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" _
(ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Public Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" _
(ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Public Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
Public Const MAX_PATH = 260
Public Const FILE_ATTRIBUTE_ARCHIVE = &H20
Public Const FILE_ATTRIBUTE_COMPRESSED = &H800
Public Const FILE_ATTRIBUTE_DIRECTORY = &H10
Public Const FILE_ATTRIBUTE_HIDDEN = &H2
Public Const FILE_ATTRIBUTE_NORMAL = &H80
Public Const FILE_ATTRIBUTE_READONLY = &H1
Public Const FILE_ATTRIBUTE_SYSTEM = &H4
Public Const FILE_ATTRIBUTE_TEMPORARY = &H100
'自定义数据类型FILETIME和WIN32_FIND_DATA的定义
Public Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Public Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * MAX_PATH
cAlternate As String * 14
End Type
----------------------
'--------------------------------------------------------------------------------
' 把当前文件夹路径下的所有文件入到listview中
'--------------------------------------------------------------------------------
Private Sub finfiles(tCurrentdir As String)
Dim itmX As ListItem
Dim tFindData As WIN32_FIND_DATA
Dim strFileName As String
Dim lHandle As Long
Dim CountFolder As Integer
Dim CountFiles As Integer
CountFolder = 0
CountFiles = 0
ListView1.ListItems.Clear
lHandle = FindFirstFile(tCurrentdir & "*.*", tFindData)
If lHandle = 0 Then
Set itmX = ListView1.ListItems.Add(, , strFileName & "找不到文件")
Exit Sub
End If
strFileName = fDelInvaildChr(tFindData.cFileName)
Do While True
tFindData.cFileName = ""
If FindNextFile(lHandle, tFindData) = 0 Then
FindClose (lHandle)
Exit Do
Else
strFileName = fDelInvaildChr(tFindData.cFileName)
If tFindData.dwFileAttributes = &H10 Then
If strFileName <> "." And strFileName <> "." Then
Set itmX = ListView1.ListItems.Add(, , strFileName)
itmX.SmallIcon = 1
CountFolder = CountFolder + 1
End If
Else
Debug.Print InStr(LCase(Right(strFileName, 3)), ExtendFileName)
If InStr(ExtendFileName, LCase(Right(strFileName, 3))) > 0 Then
Set itmX = ListView1.ListItems.Add(, , strFileName)
itmX.SubItems(1) = CStr(FileLen(tCurrentdir & "" & strFileName))
itmX.SmallIcon = 2
itmX.SubItems(2) = FileDateTime(tCurrentdir & "" & strFileName)
CountFiles = CountFiles + 1
End If
End If
End If
Loop
ListView1.Sorted = True
ListView1.SortKey = 1
StatusBar1.Panels(2).Text = CurrentDir
StatusBar1.Panels(3).Text = "文件夹:" & CountFolder & " 文件:" & CountFiles
End Sub
问题九:如何让你的程序在任务列表隐藏
办法如下:
Private Declare Function RegisterServiceProcess Lib "kernel32"
(ByVal ProcessID As Long, ByVal ServiceFlags As Long) As Long
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
'请你试试 Ctrl+Alt+Del 是不是你的程序隐藏了
Private Sub Command1_Click()
i = RegisterServiceProcess(GetCurrentProcessId, 1)
End Sub
问题十:如何计算出本月的最后一天
办法如下:
首先为下个月的第一天生成一个顺序数值,然后再减去一天
Private Sub Command1_Click()
Dim dtl As Date
dtl = DateSerial(Year(Now), Month(Now) + 1, 1) - 1
MsgBox dtl
End Sub
-------------------------------------------------------------------------------------------
错误的作法 ==> x = Shell("c:windowsSheep.scr") '这种作法只能开启屏幕保护程序的设定画面而已!
正确的作法 ==> Shell ("start c:windowssheep.scr") '这种作法才能正确启动屏幕保护程序
------------------------------------------------------------------------------------
Sub mnuEditText_Click (Index As Integer)
' 我们只要使用 SendKeys,其他的就让 Windows 去做吧!
Select Case Index
Case 0 '复原/UNDO
SendKeys "^Z" 'Keys Ctrl+Z
Case 1 '剪下/CUT
SendKeys "^X" 'Keys Ctrl+X
Case 2 '复制/COPY
SendKeys "^C" 'Keys Ctrl+C
Case 3 '贴上/PASTE
SendKeys "^V" 'Keys Ctrl+V
End Select
End Sub
-------------------------------------------------------------------------------------
Private Declare Function MessageBox Lib "user32" Alias "MessageBoxA"
(ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String,
ByVal wType As Long) As Long
'加入以下程序码:
Private Sub Command1_Click()
MsgBox "计时器停掉了!", 64, "VB 的讯息框"
End Sub
Private Sub Command2_Click()
Timer1.Enabled = 1
MessageBox Me.hwnd, "注意!计时器还在跑!", "API 的讯息框", 64
End Sub
Private Sub Form_Load()
Timer1.Interval = 2000
Label1.Caption = "目前的时间是:" & Time
End Sub
Private Sub Timer1_Timer()
SendKeys Chr(13)
Timer1.Enabled = 0
End Sub
WIN 9X 中带的 avifil32.dll库中有:AVIFileRelease、AVIStreamRelease、AVIStreamWrite、AVIStreamSetFormat、AVIFileCreateStreamA、AVIFileOpenA、AVIFileExit、AVIFileInit,这些函数及过程可以处理生成 AVI 文件,
Refer to MSDN library:
Platform SDK \ Graphics and Multimedia Services \Windows Multimedia \ Video for Windows \ AVIFile Functions and Macros
I don't know if there are some Chinese books about this topic.
如何在放入CD碟时自动调入我的CD播放软件
修改HKEY_CLASSES_ROOT\AudioCD\shell\play\command键。该键的默认值为“C:\Windows\cdplayer.exe /play %1”
这里的%1是音轨文件。你可以把它修改为:
"C:\MyPath\MyPlayer.exe %1"
如何为用VB做的程序加上特定的图标
一般先设置主窗口的Icon属性为你自己的图标,然后选择菜单“工程|??? 属性”,选择“生成”(Make)选项卡,在其中为工程选定图标。这里的???是你的工程名。
如何得知wav文件所用时间
mci控件的length属性可取得当前的wav文件的时间。VB有一个MCI的例子演示了如何使用这个属性。
如何用VB5.0编程来播放VCD
微软有一个软件叫DirectMedia或者ActiveMovie,这个软件可以播放MPEG文件。如果你安装了IE 4.0x,那么这个软件已经在你机器上了(在System目录中,叫amovie.ocx)。如果没有安装IE 4.0x,也可以从微软的站点上(http://www.microsoft.com)单独下载这个软件的SDK或运行版本。
Xing MPEG Player支持MCI接口,可以在VB中利用MCI控件调用它来播放VCD。
超级解霸也提供了一个编程接口,不过这个接口是面向C语言的,需要改造一下才能在VB中使用。
怎样以“分:秒”的格式显示时间
假定你使用一个整数保存已经播放的秒数。你可以这样做:
Dim nSeconds As Integer
......
Print Format(nSeconds \ 60, "00") + ":" + Format(nSeconds Mod 60, "00")
编写多媒体播器时,怎样才能实现遁环播放
一个专用的API函数,SndPlaySound(), 此函数是一个可独立播放WAV 语音文件的函数, 使用相对来说较为简单,无需使用MMControl,下面的例子可直接播放TEST.WAV文件:
Private Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
i=SndPlaySound("test.wav",SND_LOOP),最后一个参数可设置。SND_LOOP表示遁环播放。更具体的说明可查阅MSDN,成功的话返回 true。
利用多媒体的mciSendString API 函数, 再搭配mci(multimedia control inteXXXce) 指令, 即可播放.wav 声音文件, 细节如下:
1. API 的声明:
Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" (ByVal lpstrCommand As String, ByVal lpstrReturnString As String, ByVal uReturnLength As Long, ByVal hwndCallback As Long) As Long
注:如果以上的声明放在「一般模块」底下, 应将Private 保留字去掉。
2. 程序范例:
'自定义过程PlaySound
Sub PlaySound(filename)
Dim cmd As String
Call mciSendString("close MyWav", 0, 0, 0) ' MyWav 这个名称可依需要来修改
cmd = "open " & filename & " type WAVEAudio alias MyWav"
Call mciSendString(cmd, 0, 0, 0)
Call mciSendString("play MyWav", 0, 0, 0)
End Sub
' 假设要播放"c:\windows\Tada.wav"
PlaySound "c:\windows\Tada.wav"
在表单上布置一个Timer 控制文件、将
Interval 属性设定成100(表示0.1 秒), 然后撰写
Timer1_Timer 事件程序,如下:
Private Sub Timer1_Timer()
Dim retStr As String * 80
Call mciSendString("status MyWav mode", retStr, 80, 0)
If Left(retStr, 7) = "stopped" Then ' 如果停止了
PlaySound "c:\windows\Tada.wav" ' 重复播放
End If
End Sub
主持人注:实际上有更简单的方法,只要使用API函数mciSendCommand时在命令后加上repeat就可以实现遁环播放。如
mciSendString "play mov notify repeat", 0, 0, hWnd
就可以实现重复放映电影。
VC编写的动态链接库,其返回的字符串在VB中怎样正确读取
在动态链接库中用函数返回,而不是参数返回。如:
char * cDate(int year,int month,int day)
{
……;
}
从网上查找了许多资料,均介绍的是VB向VC传递字符串,虽然挺麻烦,但还是可行的。为什么我们不能象调用API函数一样,用结构传输参数,或用于返回,而必需用结构数组?
直接返回char *是不行的,VB不支持这种做法。正如你在资料中看到,大多数都是在VB中先给字符串分配空间,再传递给VC,在DLL中可以修改字符串,但不能超过VB中分配的空间。如果你希望直接返回字符串,必须使用BSTR类型,这实际上就是VB中的字符串所使用的类型。下面是一个简单的例子:
EXTERN_C BSTR WINAPI RetStr()
{
char *str="1234567890";
return SysAllocString((BSTR)str);
}
能否在vb中实现wav和avi文件的自动播放
播放WAV文件可以采用API函数sndPlaySound。
先加入如下声明:
Private Declare Function sndPlaySound Lib "WINMM.DLL" Alias _
"sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As _
Long) As Long
Const SND_SYNC = &H0
Const SND_ASYNC = &H1
Const SND_NODEFAULT = &H2
Const SND_LOOP = &H8
Const SND_NOSTOP = &H10
然后使用
sndPlaySound("c:\windows\tada.wav", SND_ASYNC Or SND_NODEFAULT)
播放AVI文件,可以在工程中加上Microsoft Windows Common Controls - 2,其中有一个Automation控件是播放AVI文件的。
在下面示例中,用“打开”对话框打开一个 .avi 文件并自动播放。要试用此例,在窗体上放置 Animation 控件和 CommonDialog 控件,并把代码粘贴到窗体的声明部分。运行该例,并选择要打开的 .avi 文件。
Private Sub Animation1_Click ()
With CommonDialog1
.Filter = "avi (*.avi)|*.avi"
.ShowOpen
End With
With Animation1
.Autoplay = True
.Open CommonDialog1.Filename
End With
End Sub
如何自动播放背景音乐
你可以将MMControl1的Visible属性设置为False,然后输入下面的代码:
Private Sub Form_Load()
MMControl1.Notify = False
MMControl1.Wait = True
MMControl1.Shareable = False
MMControl1.DeviceType = "WaveAudio"
MMControl1.filename = "C:\WIN98\MEDIA\Ctmelody.wav"
MMControl1.Command = "Open"
MMControl1.Command = "Play"
End Sub
Private Sub Form_Unload(Cancel As Integer)
MMControl1.Command = "Close"
End Sub
使用定时器使得标签背景色由红到蓝,再到绿,且使标签的left 沿窗体的左边向右边同时移动。
Private Sub Form_Load()
Timer1.Interval = 500
End Sub
Private Sub Timer1_Timer()
With Label1
Select Case .BackColor
Case vbRed
.BackColor = vbBlue
Case vbBlue
.BackColor = vbGreen
Case Else
.BackColor = vbRed
End Select
If .Left + .Width < Width Then .Left = .Left + 50
End With
End Sub
通过一定的算法还可以出现各种特效。
如何屏蔽一个事件
你可以建立一个窗体级变量:
Dim bWorking As Boolean
在Form_Load中:
bWorking = False
然后,
Private Sub DBGrid1_RowColChange(...)
If bWorking Then Exit Sub ' 如果还没有处理完,退出
bWorking = True
.....
bWorking = False
End Sub
我现在要做一个类似于用身份证号码抽奖的程序。要求从1到370随机抽取一个整数,并且每次抽取的数字不得相同,但为保证公平又要每个数字都有可能抽到,当然抽取的次数不大于370次,不知用VB6如何实现。
实现的方法有很多,下面只是一种。先建立一组标志,如果选中了就设置为1。每次选数时,先判断标志是否为1,如果不为1,则选中,否则忽略选择下一个。下面是例子:
Dim n(1 To 370), i, j, q
For i = 1 To 370
n(i) = 0
Next
j = 0
Randomize Timer
While j < 10
q = Int(Rnd(1) * 369 + 1)
If n(q) = 0 Then
Print q
n(q) = 1
j = j + 1
End If
Wend
我想让1到370个数字在窗体内不停的快速循环显示,一按下停止按钮或按下回车键就停止显示,应如何做。最好能和以上程序结合起来。
可以建立两个按钮,Command1和Command2,其中Command1是开始按钮,Command2是结束按钮。再加上Label1。
Dim bStop As Boolean
Dim n(1 To 370), i, j, q
Private Sub Command1_Click()
Command1.Visible = False
Randomize Timer
While j < 10
q = Int(Rnd(1) * 369 + 1)
Label1.Caption = q: DoEvents
If n(q) = 0 And bStop = True Then
Print q
n(q) = 1
j = j + 1
bStop = False
End If
Wend
End Sub
Private Sub Command2_Click()
bStop = True
End Sub
Private Sub Form_Load()
For i = 1 To 370
n(i) = 0
Next
j = 0
bStop = False
End Sub
如何全屏播放avi动画文件
使用下面的语句:
Private Declare Function mciSendString Lib "winmm.dll" Alias _
"mciSendStringA" (ByVal lpstrCommand As String, ByVal _
lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _
hwndCallback As Long) As Long
Sub Command1_Click()
'// --- Modify FILE_TO_OPEN constant as appropriate ---
Const FILE_TO_OPEN = "C:\winnt\clock.avi"
Dim strCmdStr As String
Dim lngReturnVal As Long
strCmdStr = "play " & FILE_TO_OPEN & " fullscreen "
lngReturnVal = mciSendString(strCmdStr, 0&, 0, 0&)
End Sub
如何在程序中实现将汉字内码输出成汉字的功能
假定有一个字符串"CECAD7A8BCD2",这个字符串是某三个汉字的内码。使用下面的代码进行转换(假定你运行在中文Windows下):
Private Sub Command1_Click()
Dim s As String, s2 As String
s = "CECAD7A8BCD2"
s2 = ""
For i = 1 To Len(s) Step 4
s2 = s2 + Chr("&H" + Mid(s, i, 4))
Next
Print s2
End Sub
我要实现一个类似Windows复制(移动)文件时的提示窗体,耗时很长,且要求中断后能继续未完成的操作,不知使用DoEvents从长循环中跳出后,程序将从何处开始继续执行,是否是从DoEvents所在的Sub开始?
事实上仅使用DoEvents,并不意味着从长循环中跳出。DoEvents只是允许用户选择其他按钮而已,不中断循环,不管用户如何操作,都继续执行DoEvents后面的语句,即使用户按下了中断按钮,你的循环仍然在继续,甚至你关闭了窗体,程序仍然继续在后台运行。正确的中断处理是这样的:
1、建立一个全局或窗体变量bRun。
2、在启动循环前设置bRun为True。
bRun = True
While bRun And (....)
....
DoEvents
Wend
...
3、在中断按钮Click事件中加入代码:
bRun = False
4、在Form_Unload事件中加入代码:
bRun = False
这样一旦用户按下了中断按钮,bRun = False,循环的条件就不满足了,所以退出循环,执行后续语句。你也可以采用下面的方式:
bRun = True
While ....
If Not bRun Then
Exit Sub
End If
....
DoEvents
Wend
...
关键问题归于doevents 函数
DoEvents函数的功能是:转让控制权,以便让操作系统处理其它的事件。
问:为什么要用doevents?
A.在需要用某一循环处理相当耗时或者很快速的代码时,就需要用到它,以便用户能在起处理过程中能做其他事情,即程序能被控制,而不是无响应状态
B.vb6.0中多线程vb代码极度不稳定,而且无法调试,所以vb中的多线程用的很少(注:是指vb的代码在多线程中运行时不稳定)
C.timer控件可以起到后台运行作用,但其是通过事件控制,一是不稳定,二是速度太慢,如果想用其处理高速又耗系统的代码更本不能达到预期的效果
下面将其某些用法和难点简介如下:
(注: '** 后面的代码表示如果在该处用了这个语句
以下代码中用到了一些api函数,请用vb附带的api浏览器查阅)
一. 基本用法:
1.窗体启动时如果要处理的事务太多或者用sleep函数暂停,造成其很久都不能出现时怎么办?
例如代码:
Private Sub Form_Load()
Show
'**DoEvents
Sleep 5000
End Sub
通常容易想到在sleep前加个show,但还是不能达到预想的效果,窗体虽然出来了,但好象只达到了一半,如果加上第3句,将看到效果大不相同
2.如果有个很耗时的循环导致程序不响应,怎么办?
例如:
Dim L As Long
For L = 1 To 1000000
'** DoEvents
Next L
如果无'**,在循环过程中程序无法处理事件,对于用户来说是不响应,无法控制的
3.想在循环中看到处理过程?
同样:
Dim L As Long
For L = 1 To 10000
'** DoEvents
Text1.Text=Cstr(l)
Next L
无'** 时将无法看到text1中的变化,而只在循环结束时看到最后结果
4.怎样中止循环?
如果有:
Private Sub Command3_Click()
Dim L As Long
Do
L = L + 1
Debug.Print L
DoEvents
Loop
End Sub
会发现当关闭窗口后,debug中的数据仍然在变化,说明并没结束
需要如下:
Dim IsExit As Boolean
Private Sub Command1_Click()
Dim L As Long
IsExit = False
Do While DoEvents
If IsExit = True Then Exit Do
L = L + 1
Loop
End Sub
Private Sub Command2_Click()''或者在form_unload模块中等等
IsExit = True
End Sub
其中 iXXXit是全局变量
<>有些人喜欢用end语句来结束程序,小程序固然可以,但当太大,或者调用了某些特殊的api函数后可能导致预想不到的错误,如果装载了许多东西在程序结束时不处理将卸载很慢,而且这种做法也极不符合正规软件的要求...总之end语句毛病很多,此不详谈,建议少使用甚至不使用
二. 其基本用法大概就这些,现在解析其中的一些[难点]
1.为什么还是不能结束?
代码如下:
Dim IsExit As Boolean
Private Sub Command1_Click()
Dim L As Long
IsExit = False
Do
If IsExit = True Then Exit Do '句0
DoEvents '** 句1
Text1.Text = CStr(L) '** 句2
L = L + 1
Loop
End Sub
Private Sub Form_Load()
Static N As Long
N = N + 1
MsgBox N
End Sub
Private Sub Form_Unload(Cancel As Integer)
IsExit = True
End Sub
运行结果:启动时msg显示1,点击command1,text1在变化
此时再点form右上角的小差(关闭窗体),发现vb运行控制上的按扭并没变化,说明程序还在运行.如果编译成程序后运行,按下ctrl+del+alt也可发现它还没结束.
通过读代码,并没发现错误,怎么回事?
关键在于 句2 访问了控件的属性
代码运行路径:当在doevents 时,程序释放控制权,可以接收事件消息,form-unload事件只能从此处产生,假设此时关闭form ,unload事件发生,即doevents后就运行unload代码,得到iXXXit=t,并且form卸载,代码返回到doevents 之后,运行 句2.注意现在form 已经卸载了,text1从哪里来呢?
于是form重新装载,代码跳到form_load模块运行,所以在关闭窗体后可以看到msg 显示2,此模块运行完后再继续句2后面的代码,当下次循环遇到 句0时退出循环
另:既然退出了循环,怎么还不能结束?
vb程序规定(其实其他的windows语言一样):窗体卸载时并不是立即卸载其模块代码,而只先卸载窗体中的控件和一些属性值,程序中最后一个窗体卸载时才完全卸载.
在这个单窗体程序中,form卸载时因为循环的控制无法卸载代码,失去了卸载代码的机会,导致再也不能卸载(因为没卸载代码,所以运行的 句2 是并不会出错)
另:既然再次运行了form_load代码,怎么看不见窗体?
因为程序启动时窗体的到显示的消息,而只运行此模块并没有(如果在msgbox n语句前加上show,就可以看到它了)
如何解决?
通过以上分析,应该很简单,把句1 和句2调换一下就可以了,关键:
<仔细分析代码是如何运行的,避免在form已经卸载了情况下访问控件>
2.用了doevents速度太慢了怎么办?
doevents的代价是速度变慢,但要程序响应又不得不用
其实doevents语句允许任何应用程序执行相关事件,而不仅仅是你自己的程序,所以变得很慢.
可以让它响应本程序事件动作,需要用到api函数GetInputState
例如用: If GetInputState() Then DoEvents '来代替doevents可使循环运行更快
3.既要同时响应事件又要控件不变化,怎么办?
例如在一个长的循环中向listview控件中添加记录,无doevents时程序无响应,但有它时控件又闪的厉害
解决办法:a.不一定每次循环都doevents,可以在适当时间时才用,至少没那么闪
b.应用api函数 ValidateRect 功能是使指定的矩型区域生效,通知Windows不对指定的区域进行重画 另:InvalidateRect 功能相反,同时需要用到函数 GetClientRect 取得指定对象的矩形区域 应用*rect函数指定listview的矩形区不重画,即可避免闪烁(但还是要注意恢复重画,否则看不见了真实效果)
4.控时循环和变速齿轮
请看下面的代码:
Option Explicit
Private Declare Function timeGetTime Lib "winmm.dll" () As Long
Dim IsExit As Boolean
Private Sub Command1_Click()
Dim L As Long
Dim Kt As Long
IsExit = False
Do
Kt = timeGetTime()
'do something
L = L + 1
Text1.Text = L
'DoEvents '句 1
While timeGetTime - Kt < 50 '句 2
'While Abs(timeGetTime - Kt) < 50 '句 3
'While Abs(timeGetTime - Kt) And (Not IsExit) < 50 '句 4
DoEvents '句 5
Wend
'DoEvents '句 6
If IsExit Then Exit Do
Loop
End Sub
Private Sub Form_Unload(Cancel As Integer)
IsExit = True
End Sub
其中可用的代码(除去加"'" 号的代码)就是通常的控时循环代码
运行代码并不会出现错误,但在循环过程,请开启变速齿轮看看
当关闭齿轮时,将发现text1.text停止了,别慌,等一段时间它又会继续(这要看你设定的时间,这里是50毫秒,如果设定的太长text1.text将半天都没变化,这是怎么回事?
变速齿轮在启动时将hook.dll映射到你的程序地址运行,更改了timegettime()函数获取的时间
如果在句2和句3间插入debug.print timegettime,timegettime-kt 将发现,在关闭齿轮的瞬间后者变成了负值,timegettime变小了,所以才造成需要等很久
如果是编写游戏,而用户开了齿轮,那可就惨了
解决方案:
a.用句3代替句2,这个方法最简便,虽然不符实,但不会出问题,建议使用
b.不要句5,换用句6(这样就能达到效果吗?) 因为齿轮还是从doevents语句运行时才能插的进来,所以只要kt=timegettime 和 timegettime之间没有doevents就不会出错
ab.两种方法都有些小问题,但无大碍,有兴趣者请自己分析
5.程序怎么"死了"?
这只是一些人编写时没注意到的小问题,提醒一下:
同样用上面的代码,如果设定的时间太短,以至在代码运行到句2时已经超时了,句5将不能运行了,当然程序就死了哦,以防万一,加上句1,所以此时也只能用a方案来解决齿轮的问题了
有必要用句4代替句3 吗? 除非你设定的时间太长,人家想关闭你的程序要等上好半天
[前言:]在这个专题中我收集了一些在Visual Basic编程中的常见问题,这些问题均来自论坛,本专题以解决实际问题主要目的。
问:VB中如何使用C++类?
答:把vc的类编译成dll文件,这样的话就可以使用,最好是作为组件com来使用。
VB调用DLL的方法和调用Windows API的方法是一样的,一般在VB的书中有介绍。对于上面一个例子,先要声明VC函数:
Declare Function sample Lib "mydll.dll" (ByVal nLen As Integer, buffer As Integer) As Integer
这里mydll.dll是你的dll的名字。你可能已经注意到了两个参数的声明有所不同,第一个参数加上了ByVal。规则是这样的:如果在VC中某个参数声明为指针和数组,就不加ByVal,否则都要加上ByVal。在VB中调用这个函数采用这样的语法:
sample 10, a(0)
这里的a()数组是用来存放数据的,10为数组长度,这里的第二个参数不能是a(),而必须是要传递的数据中的第一个。这是VB编程的关键。
下面在说几个可能遇到的问题。一个问题是VB可能报告找不到dll,你可以把dll放到system目录下,并确保VB的Declare语句正确。另一个问题是VB报告找不到需要的函数,这通常是因为在VC中*.def文件没设置。第三种情况是VB告诉不能进行转换,这可能是在VC中没有加上__stdcall关键字,也可能是VB和VC的参数类型不一致,注意在VC中int是4个字节(相当于VB的Long),而VB的Integer只有2个字节。必须保证VB和VC的参数个数相同,所占字节数也一致。最后一个要注意的问题是VC中绝对不能出现数组越界的情况,否则会导致VB程序崩溃。
问:怎样用编程方式在窗体上创建一个label或textbox?
答:代码如下:
'声明
Private WithEvents NewButton As ComandButton
'1,添加
Set NewButton=Controls.Add("VB.CommandButton","cmdNew",Me)
NewButton.Move 0,0,Width,Height
NewButton.Visible=True
'2,删除
Controls.Remove NewButton
Set NewButton=Nothing
问:如何把一个已编译的EXE程序打包到VB中再编译呢?
答:你需要先编写一个程序B,并将其编译为EXE。如果你希望今后允许程序A定制程序B的某个文本框,可以先将该文本框的Caption属性设置为“Change Me!Change Me!”之类首先定义好的字符串。然后程序A以二进制方式打开程序B,然后在其中查找“Change Me!Change Me!”字符串,并将其改变为程序A中设置的文字。但这种方法有几个缺点:
1、字符串长度有限;
2、对于VB来说,编译后有的中文字符串编译后格式有些办法,不好处理。
也可以采用另一种办法。程序A将设置信息保存在程序B文件的尾部。用程序B以二进制方式打开其自己的EXE文件,利用Seek命令移动到指定位置读出设置信息。如:
Dim s As String * 100
On Error GoTo ErrHandler
Open App.Path + "" + App.EXEName + ".EXE" For Binary As #1
Seek 1, 20480 ' 这里是EXE文件的长度
Get 1, , s
Label1.Caption = s
Close #1
Exit Sub
问:如何确定EXE文件的长度的具体数值呢?
答:先编译程序B,看看程序B的EXE文件的长度,例如17234。然后将上面的20480改为17234,再编译一次程序B。
问:关于程序热键公用问题?
如果两个程序都用到了相同的热键 比如说ctrl+enter 当这2个程序同时运行起来的时候,怎么才能让只有一个程序接受热键,换句话说就是谁在前台(前面 激活状态)谁就使用这个热键,谁在后台 或者最小化等非激活状态 那么就不使用这个热键! 怎么能做到呢?
答:代码如下:
Private Sub Text2_KeyDown(KeyCode As Integer, Shift As Integer)
If Shift = 2 Then
If KeyCode = vbKeyReturn Then
Text1.Text = Text2.Text
Text2.Text = ""
End If
End If
End Sub
问:在用二进制binary,写入一个字串时(比如"你好")后,如何用get读出来?
答:在VB读和写有专用的语法,或者直接使用FSO,如:
open 文件所在路径 for output as #1
write #1,"你好"
close (1)
'这是写文件操作
读的话类同,用line input读出来就可以了。
问:怎样让Listbox中的滚动条的颜色与Listbox的背景颜色一致?
答:其实要看每个控件是否可以设置颜色,一般检查一下控件的backcorlor和forecolor属性就可以了,有的话,自己设置吧。
问:怎么让form时刻处于最上方,formName.show不能做到这一点?
答:代码如下:
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const HWND_TOPMOST = -1
Private Const SWP_NOMOVE = &H2
Private Const SWP_NOSIZE = &H1
Private Sub Form_Load()
SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, Me.Width, Me.Height, SWP_NOMOVE Or SWP_NOSIZE
End Sub
问:定义在类中的Procedure和Function有什么区别? 他们是不是都可以单独存在?
答:procedure是声明一个过程,没有返回值.
function是声明一个函数,有返回值的.
问:VB中在textbox中查找单个的字符或字符串有什么好方法? 如:
在textbox中查找: 如textbox.text="12345678"查找"78"或"8" 代码怎么写?
答:用instr函数
例:
dim i as integer
text1.text="12345678"
i=instr(text1.text,"78"
i 的值就是在textBox中找到的字符串"78"的第一次出现的位置.
问: 怎样判断程序是否在运行,如果运行怎样关闭他呢?
答:先用findwindow得到你要查的窗口的hwnd,然后用sendmessge yourform.hwnd,wm_close,0
private button1_click()
dim tmp as long
tmp=findwindow(vbnullstring,"程序的窗口名VB中FORM的NAME属性值")
if tmp > 0 then
sendmessage tmp,wm_close,0
else
msgbox "Sorry!Don't find formname"
end if
end sub
问:如何用vb实现真正的多线程而不是多进程?
答:1.最好把代码放在Active Dll里,编译时使用p代码方式,至少要装vbsp3以上
2.线程函数里不能有VB的内置函数,比如left,trim等
3.创建线程CreateThread的参数不要使用ByVal &0,使用变量
主程序退出时要使用TerminateProcess(GetCurrentProcess, ByVal 0&)强行结束当前进程,否则有可能出错,这是两个API函数,请查相关资料
问:局域网点对点传输,如何数据加密?怎样实现?
答:在text1中输入你要加密的数据(16进制)
将它和4E进行异或
再按就把数据还原了
Private Sub Command1_Click()
tmp = Hex(Val("&H" & Text1.Text) Xor Val("&H" & "4E"))
Text1.Text = tmp
End Sub
问:如何实现鼠标取词?
'所要用到的函数、常量、类型
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function WindowFromPoint Lib "user32" (ByVal x As Long, ByVal y As Long) As Long
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Const WM_GETTEXT = &HD
Private Const WM_SETTEXT = &HC
Private Type POINTAPI
x As Long
y As Long
End Type
Private Sub Form_Load()
End Sub
Private Sub Timer1_Timer()
'
' 代码就是这么简单,你好好研究一下吧。
'
'
Dim Shu As POINTAPI
Dim Str As String * 300
GetCursorPos Shu
SendMessage WindowFromPoint(Shu.x, Shu.y), WM_GETTEXT, 299, ByVal Str
Label1.Caption = Str
End Sub
根据代码加入相应控件,timer1的interval的属性为100再加入把当前窗口置顶就是一个完美的简单的取词工具了!
问:VB调DLL时,如何传Structure?
答:在DLL里定义时应该用指针作参数,在VB里面,只要把结构变量定义成 Long 类型就可以了,调用的时候传入地址,就是在调用的时候,在参数前面加 ByVal。
问:如何可以在VB中实现对整个系统鼠标和键盘的屏蔽
答:我们常见一些导览系统或教学系统,会自动移动Mouse与Keyin字,而那个时候,我们不管Keyin或动Mouse都没有效,直到完成了导览系统的某个动作後才让使用者可以移动Mouse与做Keyin的动作;想做到这个,要借重JournalPlayBack Hook。
JournalPlayBack Hook,它和JournalRecord Hook合称Journal Hook,它们作用范围是整个System,也就是挂上这个Hook後,影响的层面不单是这个Process,而是有的Process,而这两Hook又不用写在Dll之中,所以很好用。
首先我们要知道由键盘和Mouse输入等的硬体讯息,会存到一个System Queue而後OS会该System Queue看有没有讯息在其中,若有则撷取出来,看目前Active的Window是谁将讯息Post给它。而挂上JournalRecord Hook时,当有讯息被撷取出来时,会先执行他们所设定的Hook Function(在vb中,一定要放在.BAS档之中)。这可以做什麽事呢?
例如我们可以Check整个系统是否有按了键盘或有没有移动Mouse(一般来说,KeyUp,KeyDown, MouseMove等Event只有Form在Active 时才收得到,挂上JournalRecord hook後,执行Hook的thread便能收到所有这些讯息)。再如,它既然能收到Keyboard、Mouse的讯息,那便可以将收到的讯息记录起来(记录於Memory或Disk都可以),之後再依方才的顺序重新将讯息放送出来,可重新执行方才的动作(这不就是巨集的作法吗),或许它叫JournalRecord便是这个原因。再来便是播放记录讯息的问题了,如果一面播放,一面有其他讯息插队(如移动Mouse),那就不对了,所以JournalPlayBack这个Hook它会让Mouse、Keyboard都失效,当OS 要求读System Queue时,便会启动这个Hook,就在此时,我们可以把方才记录起来的讯息丢出一个出来,OS再要求读System Queue时,再丢下一个讯息,如此达重播的效果(所以才叫JournalPlayBack),正因它会让键盘、Mouse失效,拿它来做导览、教学系统的自动Move Mouse或文字显示是最适合的了。
Mouse的自动导引系统制作方式,可叁考如何自动移动Mouse
'以下在.Bas中
Declare Sub Sleep Lib "KERNEL32" (ByVal dwMilliseconds As Long)
Const WM_MOUSELAST = &H209
Const WM_MOUSEFIRST = &H200
Public Const WM_KEYLAST = &H108
Public Const WM_KEYFIRST = &H100
Public Const WH_JOURNALRECORD = 0
Public Const WH_JOURNALPLAYBACK = 1
Type EVENTMSG
message As Long
paramL As Long
paramH As Long
time As Long
hwnd As Long
End Type
Declare Function SetWindowsHookEx Lib "user32" Alias _
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _
ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Declare Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _
ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
Public hNxtHook As Long ' handle of Hook Procedure
Public msg As EVENTMSG
Sub EnableHook()
hNxtHook = SetWindowsHookEx(WH_JOURNALPLAYBACK, AddressOf HookProc, App.hInstance, 0)
End Sub
Sub FreeHook()
Dim ret As Long
ret = UnhookWindowsHookEx(hNxtHook)
End Sub
Function HookProc(ByVal code As Long, ByVal wParam As Long, _
ByVal lParam As Long) As Long
HookProc = CallNextHookEx(hNxtHook, code, wParam, lParam)
End Function
'以下在Form中,需求:一个Command1, 一个text1
Private Sub Command1_Click()
Dim str5 As String, len5 As Long, i As Long
Call EnableHook
str5 = "这是一个测试JournalPlayBackHook的程式"
len5 = Len(str5)
For i = 1 To len5
Text1.Text = Mid(str5, 1, i)
Text1.Refresh
Sleep (200)
Next
Call FreeHook
End Sub
问:如何把picture控件中图形数据写成“流”?
答:可以使用adodb.stream对象。
上传图片或显示SWF的时候都希望得到它的高度和宽度,基本原理使用Adodb.Stream读二进制文件然后进行解析,然后返回一数组:
第一个元素为类型(BMP JPG PNG GIF SWF)
第二个元素为宽度{width}
第三个元素为高度{height}
第四个元素为width={width},height={height}式字符串
Class qswhImg
dim aso
Private Sub Class_Initialize
set aso=CreateObject("Adodb.Stream")
aso.Mode=3
aso.Type=1
aso.Open
End Sub
Private Sub Class_Terminate
set aso=nothing
End Sub
Private Function Bin2Str(Bin)
Dim I, Str
For I=1 to LenB(Bin)
clow=MidB(Bin,I,1)
if ASCB(clow)<128 then
Str = Str & Chr(ASCB(clow))
else
I=I+1
if I <= LenB(Bin) then Str = Str & Chr(ASCW(MidB(Bin,I,1)&clow))
end if
Next
Bin2Str = Str
End Function
Private Function Num2Str(num,base,lens)
'qiushuiwuhen (2002-8-12)
dim ret
ret = ""
while(num>=base)
ret = (num mod base) & ret
num = (num - num mod base)/base
wend
Num2Str = right(string(lens,"0") & num & ret,lens)
End Function
Private Function Str2Num(str,base)
'qiushuiwuhen (2002-8-12)
dim ret
ret = 0
for i=1 to len(str)
ret = ret *base + cint(mid(str,i,1))
next
Str2Num=ret
End Function
Private Function BinVal(bin)
'qiushuiwuhen (2002-8-12)
dim ret
ret = 0
for i = lenb(bin) to 1 step -1
ret = ret *256 + ascb(midb(bin,i,1))
next
BinVal=ret
End Function
Private Function BinVal2(bin)
'qiushuiwuhen (2002-8-12)
dim ret
ret = 0
for i = 1 to lenb(bin)
ret = ret *256 + ascb(midb(bin,i,1))
next
BinVal2=ret
End Function
Function getImageSize(filespec)
'qiushuiwuhen (2002-9-3)
dim ret(3)
aso.LoadFromFile(filespec)
bFlag=aso.read(3)
select case hex(binVal(bFlag))
case "4E5089":
aso.read(15)
ret(0)="PNG"
ret(1)=BinVal2(aso.read(2))
aso.read(2)
ret(2)=BinVal2(aso.read(2))
case "464947":
aso.read(3)
ret(0)="GIF"
ret(1)=BinVal(aso.read(2))
ret(2)=BinVal(aso.read(2))
case "535746":
aso.read(5)
binData=aso.Read(1)
sConv=Num2Str(ascb(binData),2 ,8)
nBits=Str2Num(left(sConv,5),2)
sConv=mid(sConv,6)
while(len(sConv) binData=aso.Read(1)
sConv=sConv&Num2Str(ascb(binData),2 ,8)
wend
ret(0)="SWF"
ret(1)=int(abs(Str2Num(mid(sConv,1*nBits+1,nBits),2)-Str2Num(mid(sConv,0*nBits+1,nBits),2))/20)
ret(2)=int(abs(Str2Num(mid(sConv,3*nBits+1,nBits),2)-Str2Num(mid(sConv,2*nBits+1,nBits),2))/20)
case "FFD8FF":
do
do: p1=binVal(aso.Read(1)): loop while p1=255 and not aso.EOS
if p1>191 and p1<196 then exit do else aso.read(binval2(aso.Read(2))-2)
do:p1=binVal(aso.Read(1)):loop while p1<255 and not aso.EOS
loop while true
aso.Read(3)
ret(0)="JPG"
ret(2)=binval2(aso.Read(2))
ret(1)=binval2(aso.Read(2))
case else:
if left(Bin2Str(bFlag),2)="BM" then
aso.Read(15)
ret(0)="BMP"
ret(1)=binval(aso.Read(4))
ret(2)=binval(aso.Read(4))
else
ret(0)=""
end if
end select
ret(3)="width=""" & ret(1) &""" height=""" & ret(2) &""""
getimagesize=ret
End Function
End Class
使用范例(读某目录下所有图片的宽度):
set qswh=new qswhImg
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.GetFolder(server.mappath("."))
Set fc = f.Files
For Each f1 in fc
ext=fso.GetExtensionName(f1.path)
select case ext
case "gif","bmp","jpg","png":
arr=qswh.getImageSize(f1.path)
response.write "
" & arr(0) & " " & arr(3) & ":" & f1.name & " width:" & arr(1) & " height:" & arr(2)
case "swf"
arr=qswh.getimagesize(f1.path)
response.write "
" & arr(0) & " " & arr(3) & ":" & f1.name & " width:" & arr(1) & " height:" & arr(2)
end select
Next
Set fc=nothing
Set f=nothing
Set fso=nothing
Set qswh=nothing
问题一:Visual Basic 导出到 Excel 提速之法
办法如下:
Excel 是一个非常优秀的报表制作软件,用VBA可以控制其生成优秀的报表,本文通过添加查询语句的方法,即用Excel中的获取外部数据的功能将数据很快地从一个查询语句中捕获到EXCEL中,比起往每个CELL里写数据的方法提高许多倍。
将下文加入到一个模块中,屏幕中调用如下ExporToExcel("select * from table")则实现将其导出到EXCEL中
Public Function ExporToExcel(strOpen As String)
'*********************************************************
'* 名称:ExporToExcel
'* 功能:导出数据到EXCEL
'* 用法:ExporToExcel(sql查询字符串)
'*********************************************************
Dim Rs_Data As New ADODB.Recordset
Dim Irowcount As Integer
Dim Icolcount As Integer
Dim xlApp As New Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim xlQuery As Excel.QueryTable
With Rs_Data
If .State = adStateOpen Then
.Close
End If
.ActiveConnection = Cn
.CursorLocation = adUseClient
.CursorType = adOpenStatic
.LockType = adLockReadOnly
.Source = strOpen
.Open
End With
With Rs_Data
If .RecordCount < 1 Then
MsgBox ("没有记录!")
Exit Function
End If
'记录总数
Irowcount = .RecordCount
'字段总数
Icolcount = .Fields.Count
End With
Set xlApp = CreateObject("Excel.Application")
Set xlBook = Nothing
Set xlSheet = Nothing
Set xlBook = xlApp.Workbooks().Add
Set xlSheet = xlBook.Worksheets("sheet1")
xlApp.Visible = True
'添加查询语句,导入EXCEL数据
Set xlQuery = xlSheet.QueryTables.Add(Rs_Data, xlSheet.Range("a1"))
With xlQuery
.FieldNames = True
.RowNumbers = False
.FillAdjacentFormulas = False
.PreserveFormatting = True
.RefreshOnFileOpen = False
.BackgroundQuery = True
.RefreshStyle = xlInsertDeleteCells
.SavePassword = True
.SaveData = True
.AdjustColumnWidth = True
.RefreshPeriod = 0
.PreserveColumnInfo = True
End With
xlQuery.FieldNames = True '显示字段名
xlQuery.Refresh
With xlSheet
.Range(.Cells(1, 1), .Cells(1, Icolcount)).Font.Name = "黑体"
'设标题为黑体字
.Range(.Cells(1, 1), .Cells(1, Icolcount)).Font.Bold = True
'标题字体加粗
.Range(.Cells(1, 1), .Cells(Irowcount + 1, Icolcount)).Borders.LineStyle = xlContinuous
'设表格边框样式
End With
With xlSheet.PageSetup
.LeftHeader = "" & Chr(10) & "&""楷体_GB2312,常规""&10公司名称:" ' & Gsmc
.CenterHeader = "&""楷体_GB2312,常规""公司人员情况表&""宋体,常规""" & Chr(10) & "&""楷体_GB2312,常规""&10日 期:"
.RightHeader = "" & Chr(10) & "&""楷体_GB2312,常规""&10单位:"
.LeftFooter = "&""楷体_GB2312,常规""&10制表人:"
.CenterFooter = "&""楷体_GB2312,常规""&10制表日期:"
.RightFooter = "&""楷体_GB2312,常规""&10第&P页 共&N页"
End With
xlApp.Application.Visible = True
Set xlApp = Nothing '"交还控制给Excel
Set xlBook = Nothing
Set xlSheet = Nothing
End Function
注:须在程序中引用'Microsoft Excel 9.0 Object Library'和ADO对象,机器必装Excel 2000
本程序在Windows 98/2000,VB 6 下运行通过。
问题二:vb中从域名得到IP及从IP得到域名
办法如下:
Private Const WS_VERSION_REQD = &H101
Private Const WS_VERSION_MAJOR = WS_VERSION_REQD &H100 And &HFF&
Private Const WS_VERSION_MINOR = WS_VERSION_REQD And &HFF&
Private Const MIN_SOCKETS_REQD = 1
Private Const SOCKET_ERROR = -1
Private Const WSADescription_Len = 256
Private Const WSASYS_Status_Len = 128
Private Type HOSTENT
hname As Long
hAliases As Long
hAddrType As Integer
hLength As Integer
hAddrList As Long
End Type
Private Type WSADATA
wversion As Integer
wHighVersion As Integer
szDescription(0 To WSADescription_Len) As Byte
szSystemStatus(0 To WSASYS_Status_Len) As Byte
iMaxSockets As Integer
iMaxUdpDg As Integer
lpszVendorInfo As Long
End Type
Private Declare Function gethostbyaddr Lib "WSOCK32.DLL" (addr As Any, ByVal _
byteslen As Integer, addrtype As Integer) As Long
Private Declare Function WSAGetLastError Lib "WSOCK32.DLL" () As Long
Private Declare Function WSAStartup Lib "WSOCK32.DLL" (ByVal _
wVersionRequired&, lpWSAData As WSADATA) As Long
Private Declare Function WSACleanup Lib "WSOCK32.DLL" () As Long
Private Declare Function gethostbyname Lib "WSOCK32.DLL" (ByVal _
hostname$) As Long
Private Declare Sub RtlMoveMemory Lib "KERNEL32" (hpvDest As Any, _
ByVal hpvSource&, ByVal cbCopy&)
Function hibyte(ByVal wParam As Integer) '获得整数的高位
hibyte = wParam &H100 And &HFF&
End Function
Function lobyte(ByVal wParam As Integer) '获得整数的低位
lobyte = wParam And &HFF&
End Function
Function SocketsInitialize()
Dim WSAD As WSADATA
Dim iReturn As Integer
Dim sLowByte As String, sHighByte As String, sMsg As String
iReturn = WSAStartup(WS_VERSION_REQD, WSAD)
If iReturn <> 0 Then
MsgBox "Winsock.dll 没有反应."
End
End If
If lobyte(WSAD.wversion) < WS_VERSION_MAJOR Or (lobyte(WSAD.wversion) = WS_VERSION_MAJOR And hibyte(WSAD.wversion) < WS_VERSION_MINOR) Then
sHighByte = Trim$(str$(hibyte(WSAD.wversion)))
sLowByte = Trim$(str$(lobyte(WSAD.wversion)))
sMsg = "Windows Sockets版本 " & sLowByte & "." & sHighByte
sMsg = sMsg & " 不被winsock.dll支持 "
MsgBox sMsg
End
End If
If WSAD.iMaxSockets < MIN_SOCKETS_REQD Then
sMsg = "这个系统需要的最少Sockets数为 "
sMsg = sMsg & Trim$(str$(MIN_SOCKETS_REQD))
MsgBox sMsg
End
End If
End Function
Sub SocketsCleanup()
Dim lReturn As Long
lReturn = WSACleanup()
If lReturn <> 0 Then
MsgBox "Socket错误 " & Trim$(str$(lReturn)) & " occurred in Cleanup "
End
End If
End Sub
Sub Form_Load()
'初始化Socket
SocketsInitialize
End Sub
Private Sub Form_Unload(Cancel As Integer)
'清除Socket
SocketsCleanup
End Sub
Private Function getip(name As String) As String
Dim hostent_addr As Long
Dim host As HOSTENT
Dim hostip_addr As Long
Dim temp_ip_address() As Byte
Dim i As Integer
Dim ip_address As String
hostent_addr = gethostbyname(name)
If hostent_addr = 0 Then
getip = "" '主机名不能被解释
Exit Function
End If
RtlMoveMemory host, hostent_addr, LenB(host)
RtlMoveMemory hostip_addr, host.hAddrList, 4
ReDim temp_ip_address(1 To host.hLength)
RtlMoveMemory temp_ip_address(1), hostip_addr, host.hLength
For i = 1 To host.hLength
ip_address = ip_address & temp_ip_address(i) & "."
Next
ip_address = Mid$(ip_address, 1, Len(ip_address) - 1)
getip = ip_address
End Function
Private Sub Command1_click()
Dim str As String
str = getip(Text1.Text)
If str = "" Then
Text2.Text = "主机名不能被解释"
Else
Text2.Text = str
End If
End Sub
Private Function getname(addrstr As String) As String
Dim hostent_addr As Long
Dim host As HOSTENT
Dim addr(0 To 50) As Byte
Dim addrs As String
Dim hname(1 To 50) As Byte
Dim str As String
Dim i As Integer, j As Integer
Dim temp_int As Integer
Dim byt As Byte
str = Trim$(addrstr)
i = 0
j = 0
Do
temp_int = 0
i = i + 1
Do While Mid$(str, i, 1) >= "0" And Mid$(str, i, 1) <= "9" And i <= Len(str)
temp_int = temp_int * 10 + Mid$(str, i, 1)
i = i + 1
Loop
If temp_int <= 255 Then
addr(j) = temp_int
j = j + 1
End If
Loop Until Mid$(str, i, 1) <> "." Or i > Len(str) Or temp_int > 255
If temp_int > 255 Then
getname = "地址非法"
Exit Function
End If
hostent_addr = gethostbyaddr(addr(0), j, 2)
If hostent_addr = 0 Then
getname = "此地址无法解析"
Exit Function
End If
RtlMoveMemory host, hostent_addr, LenB(host)
RtlMoveMemory hname(1), host.hname, 50
j = 51
For i = 1 To 50
If hname(i) = 0 Then
j = i
End If
If i >= j Then
hname(i) = 32
End If
Next i
getname = Trim$(StrConv(hname, vbUnicode))
End Function
Private Sub Command2_Click()
Dim name As String
name = getname(Text2.Text)
If name = "" Then
name = "此地址没有域名"
End If
Text1.Text = name
End Sub
问题三:怎么把图片加入到数据库里面
办法如下:
Private Sub Command3_Click()
Dim conn As New ADODB.Connection
conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:1.mdb;Persist Security Info=False"
conn.Execute "create table a (b longbinary)"
End Sub
Private Sub Command4_Click()
Set b = New ADODB.Recordset
Set c = New ADODB.Stream
c.Mode = adModeReadWrite
c.Type = adTypeBinary
c.Open
c.LoadFromFile "c:1.bmp"
b.Open "select * from a", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:1.mdb;Persist Security Info=False", adOpenDynamic, adLockOptimistic
b.AddNew
b.Fields.Item(0).Value = c.Read()
b.Update
b.Close
Set b = New ADODB.Recordset
b.Open "select * from a", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:1.mdb;Persist Security Info=False", adOpenKeyset, adLockOptimistic
MsgBox b.RecordCount
b.MoveLast
c.Write (b.Fields.Item(0).Value)
c.SaveToFile "c:aa.bmp", adSaveCreateOverWrite
Picture1.Picture = LoadPicture("c:aa.bmp")
End Sub
问题四:VB6.0中如何快速实现大面积不规则区域的填充
办法如下:
一、引言
区域填充是指先将区域内的一个像素 ,一般称为种子点赋予给定的颜色和辉亮,然后将该颜色扩展到整个区域内的过程。
二、已有的填充算法及缺点
1.扫描线法
扫描线法可以实现已知多边形域边界的填充,多边形域可以是凹的、凸的、还可以是带孔的。该填充方法是按扫描线的顺序,计算扫描线与待填充区域的相交区间,再用要求的颜色显示这些区间的像素,即完成填充工作。这里区间的端点通过计算扫描线与多边形边界线的交点获得。所以待填充区域的边界线必须事先知道,因此它的缺点是无法实现对未知边界的区域填充。
2.边填充算法
边填充的基本思想是:对于每一条扫描线和每条多边形边的交点,将该扫描线上交点右方的所有像素取补。对多边形的每条边作些处理,多边形的顺序随意。该算法适用于具有帧缓冲器的图形系统,按任意顺序处理多边形的边。处理每条边时,仅访问与该边有交的扫描线上交点右方的像素。所有的边都被处理之后,按扫描线顺序读出帧缓冲器的内容,送入显示设备。该算法的优点是简单,缺点是对于复杂图形,每一像素可能被访问多次,重要的是必须事先知道待填充多边形的边界,所以在填充未知边界的区域时不适用。
3.递归算法
递归算法的优点是编程实现时,语言简洁。但在VB6.0实际编程实现时,这种递归算法填充稍稍大一些的图形就会出现堆栈溢出现象,据我们的实践证明,递归算法只能连续递归深度在2090次左右,也就是说,如果待填充的图形大于二千多个像素那么堆栈溢出。下面给出八连通填充方法的VB程序实现(四连通算法同理)。
Public Sub area(p, q As Integer)
If ((imagepixels(0, p, q) = red1) And (imagepixels(1, p, q) = green1) And (imagepixels(2, p, q) = blue1)) Then
imagepixels(0, p, q) = 0: imagepixels(2, p, q) = 0: imagepixels(1, p, q) = 0
Picture1.PSet (p, q), RGB(0, 0, 0)
Call area(p + 1, q): Call area(p, q + 1)
Call area(p - 1, q): Call area(p, q - 1)
Call area(p + 1, q + 1): Call area(p + 1, q - 1)
Call area(p - 1, q + 1): Call area(p - 1, q - 1)
Else: Exit Sub
End If
End Sub
三、算法的基本思想
本算法采用两个队列(FIFO)filled和unfilled来实现区域填充。设计步骤如下:
1. 找出该区域内部任意一点,作为填充种子。
2. 填充该点,并把该点存入队列filled。
3. 按逆时针,判断该点的上、右、下、左邻像素是否在filled队列内。如果在filled,说明该相邻点已填充,若不在filled队列内,则判断该相邻点在未填充队列unfilled,如果不在则将该相邻点存入unfilled。
4. 判断未填充队列是否为空,若不空,则从队列unfilled中取出头元素,转向第三步。若为空则表示已完成所有像素填充,结束程序。
四、程序实现及说明
本算法定义的队列突破了递归算法中受堆栈空间大小的限制的束缚,因为它直接占用内存空间,与堆栈大小无关。以下源程序在Window 2000环境下用VB6.0编程实现。
建立如图所示标准窗体并画上控件-2个CommandButton控件和一个PictureBox控件,调整大小,并设置控件的属性。
通用声明
Dim Xx As Integer, Yy As Integer
Dim Array1(9000, 2), Array2(9000, 2) As Integer
4.2 采集
Private Sub Command1_Click()
Picture1.MousePointer = 2
End Sub
4.3 选取种子
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Xx = X '选择并记录种子点的位置
Yy = Y
End Sub
4.4 区域填充
Private Sub Command2_Click()
Dim i, j, k As Integer, BoundPoint1, BoundPoint2 As Integer
Dim Flag As Boolean, Pixel As Long
Dim Red, Green, Blue As Integer, Bound As Boolean
Flag = True '初始化
i = Xx: j = Yy: BoundPoint1 = 1
Array1(1, 1) = i
Array1(1, 2) = j
'搜索边界点
Do While BoundPoint1 > 0
BoundPoint2 = 0
For k = 1 To BoundPoint1
i = Array1(k, 1)
j = Array1(k, 2)
'搜索右点
Pixel& = Picture1.Point(i, j + 1)
Call IsBound(Pixel&, Bound)
If Not Bound Then
BoundPoint2 = BoundPoint2 + 1
Array2(BoundPoint2, 1) = i
Array2(BoundPoint2, 2) = j + 1
Picture1.PSet (i, j + 1), RGB(255, 255, 255)
End If
'搜索左邻点
Pixel& = Picture1.Point(i, j - 1)
Call IsBound(Pixel&, Bound)
If Not Bound Then
BoundPoint2 = BoundPoint2 + 1
Array2(BoundPoint2, 1) = i
Array2(BoundPoint2, 2) = j - 1
Picture1.PSet (i, j - 1), RGB(255, 255, 255)
End If
'搜索上邻点
Pixel& = Picture1.Point(i - 1, j)
Call IsBound(Pixel&, Bound)
If Not Bound Then
BoundPoint2 = BoundPoint2 + 1
Array2(BoundPoint2, 1) = i - 1
Array2(BoundPoint2, 2) = j
Picture1.PSet (i - 1, j), RGB(255, 255, 255)
End If
'搜索下邻点
Pixel& = Picture1.Point(i + 1, j)
Call IsBound(Pixel&, Bound)
If Not Bound Then
BoundPoint2 = BoundPoint2 + 1
Array2(BoundPoint2, 1) = i + 1
Array2(BoundPoint2, 2) = j
Picture1.PSet (i + 1, j), RGB(255, 255, 255)
End If
Next k
'数组array2 中的数据传给array1
BoundPoint1 = BoundPoint2
For k = 1 To BoundPoint1
Array1(k, 1) = Array2(k, 1)
Array1(k, 2) = Array2(k, 2)
Next k
Picture1.Refresh
Loop
End Sub
Public Sub IsBound(P As Long, Bound As Boolean) '判断P是否为边界点
Red = P& Mod 256
Bound = False
Green = ((P& And &HFF00) / 256&) Mod 256&
Blue = (P& And &HFF0000) / 65536
If Red = 255 And Green = 255 And Blue = 255 Then
Bound = True
End If
End Sub
问题五:如何获取打印机纸张信息?
办法如下:
Option Explicit
Private Const DC_MAXEXTENT = 5
Private Const DC_MINEXTENT = 4
Private Const DC_PAPERNAMES = 16
Private Const DC_PAPERS = 2
Private Const DC_PAPERSIZE = 3
Private Declare Function DeviceCapabilities Lib "winspool.drv" Alias "DeviceCapabilitiesA" (ByVal lpDeviceName As String, ByVal lpPort As String, ByVal iIndex As Long, lpOutput As Any, lpDevMode As Any) As Long
Private Type POINTS
x As Long
y As Long
End Type
'***********************************************************
'* 名称:GetPaperInfo
'* 功能:得到打印机低张信息
'* 用法:GetPaperInfo(控件名)
'* 描述:如在 form_load()中调用GetPaperInfo MSHFlexGrid1
'***********************************************************
Public Function GetPaperInfo(Flex As MSHFlexGrid) As Boolean
Dim i As Long, ret As Long
Dim Length As Integer, Width As Integer
Dim PaperNo() As Integer, PaperName() As String, PaperSize() As POINTS
With Flex
.FormatString = "^纸张编号|^纸张名称|^纸张长度|^纸张宽度"
For i = 0 To .Cols - 1
.ColWidth(i) = 1700
Next i
.AllowUserResizing = flexResizeColumns
.Left = 0
End With
'支持最大打印纸:
ret = DeviceCapabilities(Printer.DeviceName, "LPT1", DC_MAXEXTENT, ByVal 0&, ByVal 0&)
Length = ret 65536
Width = ret - Length * 65536
'支持最小打印纸:
ret = DeviceCapabilities(Printer.DeviceName, "LPT1", DC_MINEXTENT, ByVal 0&, ByVal 0&)
Length = ret 65536
Width = ret - Length * 65536
'支持纸张种类数
ret = DeviceCapabilities(Printer.DeviceName, "LPT1", DC_PAPERS, ByVal 0&, ByVal 0&)
'纸张编号
ReDim PaperNo(1 To ret) As Integer
Call DeviceCapabilities(Printer.DeviceName, "LPT1", DC_PAPERS, PaperNo(1), ByVal 0&)
'纸张名称
Dim arrPageName() As Byte
Dim allNames As String
Dim lStart As Long, lEnd As Long
ReDim PaperName(1 To ret) As String
ReDim arrPageName(1 To ret * 64) As Byte
Call DeviceCapabilities(Printer.DeviceName, "LPT1", DC_PAPERNAMES, arrPageName(1), ByVal 0&)
allNames = StrConv(arrPageName, vbUnicode)
'loop through the string and search for the names of the papers
i = 1
Do
lEnd = InStr(lStart + 1, allNames, Chr$(0), vbBinaryCompare)
If (lEnd > 0) And (lEnd - lStart - 1 > 0) Then
PaperName(i) = Mid$(allNames, lStart + 1, lEnd - lStart - 1)
i = i + 1
End If
lStart = lEnd
Loop Until lEnd = 0
'纸张尺寸
ReDim PaperSize(1 To ret) As POINTS
Call DeviceCapabilities(Printer.DeviceName, "LPT1", DC_PAPERSIZE, PaperSize(1), ByVal 0&)
'显示在表格中
For i = 1 To ret
Flex.AddItem PaperNo(i) & vbTab & PaperName(i)
& vbTab & PaperSize(i).y & vbTab & PaperSize(i).x
Next i
End Function
问题六:在DataGrid中显示DataCombo
办法如下:
DataGrid1_MouseDown
Dim col As MSDataGridLib.Column
Set col = DataGrid1.Columns(DataGrid1.col)
If col.Caption = "MS" And DataGrid1.CurrentCellVisible Then
DataCombo1.Left = DataGrid1.Left + col.Left + 2 * Screen.TwipsPerPixelX
DataCombo1.Top = DataGrid1.Top + DataGrid1.RowTop(DataGrid1.Row) + 2 * Screen.TwipsPerPixelX
DataCombo1.Width = col.Width - 2 * Screen.TwipsPerPixelX
DataCombo1.Text = col.Text
DataCombo1.Visible = True
DataCombo1.SetFocus
DataCombo1.ZOrder
Else
DataCombo1.Visible = False
End If
问题七:如何识别操作系统版本?
办法如下:
'引用控件 Microsoft SysInfo Control 6.0
Dim OS As String
With SysInfo1
Select Case .OSPlatform
Case 0: OS = "Win32"
Case 1:
Select Case .OSVersion
Case 4: OS = "Win 95"
Case 4.1: OS = "Win 98"
Case 4.9: OS = "Wim Me"
End Select
Case 2:
Select Case .OSVersion
Case 4: OS = "Win NT"
Case 5: OS = "Win 2000"
Case 6: OS = "Win XP"
End Select
End Select
MsgBox "Build:" & .OSBuild & vbNewLine & _
"Platform:" & OS & "(" & .OSPlatform & ")" & vbNewLine & _
"Version:" & .OSVersion
End With
问题八:如何实现遍历文件夹中的所有文件
办法如下:
把下面放到模块中
Option Explicit
Public Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" _
(ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long
Public Declare Function FindNextFile Lib "kernel32" Alias "FindNextFileA" _
(ByVal hFindFile As Long, lpFindFileData As WIN32_FIND_DATA) As Long
Public Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long
Public Const MAX_PATH = 260
Public Const FILE_ATTRIBUTE_ARCHIVE = &H20
Public Const FILE_ATTRIBUTE_COMPRESSED = &H800
Public Const FILE_ATTRIBUTE_DIRECTORY = &H10
Public Const FILE_ATTRIBUTE_HIDDEN = &H2
Public Const FILE_ATTRIBUTE_NORMAL = &H80
Public Const FILE_ATTRIBUTE_READONLY = &H1
Public Const FILE_ATTRIBUTE_SYSTEM = &H4
Public Const FILE_ATTRIBUTE_TEMPORARY = &H100
'自定义数据类型FILETIME和WIN32_FIND_DATA的定义
Public Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type
Public Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * MAX_PATH
cAlternate As String * 14
End Type
----------------------
'--------------------------------------------------------------------------------
' 把当前文件夹路径下的所有文件入到listview中
'--------------------------------------------------------------------------------
Private Sub finfiles(tCurrentdir As String)
Dim itmX As ListItem
Dim tFindData As WIN32_FIND_DATA
Dim strFileName As String
Dim lHandle As Long
Dim CountFolder As Integer
Dim CountFiles As Integer
CountFolder = 0
CountFiles = 0
ListView1.ListItems.Clear
lHandle = FindFirstFile(tCurrentdir & "*.*", tFindData)
If lHandle = 0 Then
Set itmX = ListView1.ListItems.Add(, , strFileName & "找不到文件")
Exit Sub
End If
strFileName = fDelInvaildChr(tFindData.cFileName)
Do While True
tFindData.cFileName = ""
If FindNextFile(lHandle, tFindData) = 0 Then
FindClose (lHandle)
Exit Do
Else
strFileName = fDelInvaildChr(tFindData.cFileName)
If tFindData.dwFileAttributes = &H10 Then
If strFileName <> "." And strFileName <> "." Then
Set itmX = ListView1.ListItems.Add(, , strFileName)
itmX.SmallIcon = 1
CountFolder = CountFolder + 1
End If
Else
Debug.Print InStr(LCase(Right(strFileName, 3)), ExtendFileName)
If InStr(ExtendFileName, LCase(Right(strFileName, 3))) > 0 Then
Set itmX = ListView1.ListItems.Add(, , strFileName)
itmX.SubItems(1) = CStr(FileLen(tCurrentdir & "" & strFileName))
itmX.SmallIcon = 2
itmX.SubItems(2) = FileDateTime(tCurrentdir & "" & strFileName)
CountFiles = CountFiles + 1
End If
End If
End If
Loop
ListView1.Sorted = True
ListView1.SortKey = 1
StatusBar1.Panels(2).Text = CurrentDir
StatusBar1.Panels(3).Text = "文件夹:" & CountFolder & " 文件:" & CountFiles
End Sub
问题九:如何让你的程序在任务列表隐藏
办法如下:
Private Declare Function RegisterServiceProcess Lib "kernel32"
(ByVal ProcessID As Long, ByVal ServiceFlags As Long) As Long
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
'请你试试 Ctrl+Alt+Del 是不是你的程序隐藏了
Private Sub Command1_Click()
i = RegisterServiceProcess(GetCurrentProcessId, 1)
End Sub
问题十:如何计算出本月的最后一天
办法如下:
首先为下个月的第一天生成一个顺序数值,然后再减去一天
Private Sub Command1_Click()
Dim dtl As Date
dtl = DateSerial(Year(Now), Month(Now) + 1, 1) - 1
MsgBox dtl
End Sub
-------------------------------------------------------------------------------------------
错误的作法 ==> x = Shell("c:windowsSheep.scr") '这种作法只能开启屏幕保护程序的设定画面而已!
正确的作法 ==> Shell ("start c:windowssheep.scr") '这种作法才能正确启动屏幕保护程序
------------------------------------------------------------------------------------
Sub mnuEditText_Click (Index As Integer)
' 我们只要使用 SendKeys,其他的就让 Windows 去做吧!
Select Case Index
Case 0 '复原/UNDO
SendKeys "^Z" 'Keys Ctrl+Z
Case 1 '剪下/CUT
SendKeys "^X" 'Keys Ctrl+X
Case 2 '复制/COPY
SendKeys "^C" 'Keys Ctrl+C
Case 3 '贴上/PASTE
SendKeys "^V" 'Keys Ctrl+V
End Select
End Sub
-------------------------------------------------------------------------------------
Private Declare Function MessageBox Lib "user32" Alias "MessageBoxA"
(ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String,
ByVal wType As Long) As Long
'加入以下程序码:
Private Sub Command1_Click()
MsgBox "计时器停掉了!", 64, "VB 的讯息框"
End Sub
Private Sub Command2_Click()
Timer1.Enabled = 1
MessageBox Me.hwnd, "注意!计时器还在跑!", "API 的讯息框", 64
End Sub
Private Sub Form_Load()
Timer1.Interval = 2000
Label1.Caption = "目前的时间是:" & Time
End Sub
Private Sub Timer1_Timer()
SendKeys Chr(13)
Timer1.Enabled = 0
End Sub
0人赞
分享
二维码
赏一个