李倓剧情怎么开:Visual Basic编程疑难问题解(一)(二)

来源:百度文库 编辑:偶看新闻 时间:2024/05/04 19:16:15
Visual Basic编程疑难问题解(一)(二)
[前言:]在这个专题中我收集了一些在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编程疑难问题解(二)
问题一: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

五?结束语

本算法实现了在对填充区域的形状、大小均未知的情况下,以种子点开始向四周对该区域进行“扩散式”的填充。本算法解决了传统的递归算法在填充较大区域时(本例中填充区约9800Pixels)堆栈溢出的缺点。我们的实验结果显示,本算法就填充区域大小和运算速度而言,都远远超过了传统的递归算法。

问题五:如何获取打印机纸张信息?

办法如下:

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:\windows\Sheep.scr") '这种作法只能开启屏幕保护程序的设定画面而已!

正确的作法 ==> Shell ("start c:\windows\sheep.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