未公開函數揭密——之一 什么是未公開函數? 對于 Windows 的 API 函數調用相信大家已經不會陌生了。 API 函數調用是通過在 VB 中定義和調用 Wi" name="description" />
什么是未公開函數?
對于Windows的API函數調用相信大家已經不會陌生了。API函數調用是通過在VB中定義和調用Windows動態連接庫中的函數從而擴展VB程序的功能。API函數的定義和調用方法在微軟的開發工具中都有詳細的說明。
那么什么是“未公開”函數呢?微軟為了某種目的。對于一些封裝在系統中的函數沒有在任何開發文檔提供任何函數說明和定義。而這些函數有很多都是很有用的。所幸的是一些有心之人對Windows系統動態連接庫做了十分詳細的分析,從而將這些未公開函數公開以供廣大開發人員共享(我對他們的感激之情就象滔滔江水,綿綿不絕…)
好了,廢話少說,言歸正傳,這里首先向大家介紹的是Windows下未公開的關閉Windows的函數。在Windows API函數中雖然提供了ExitWindowsEx這樣的API函數,但是在有一些程序中我們需要象一些程序安裝完畢那樣提示用戶重新啟動計算機或者不重新啟動計算機?;蛘咭诔绦蛑袕棾鲫P閉系統對話框。要實現這些功能就要使用Windows未公開函數了。下面來看程序
首先建立一個新的工程文件,在工程文件中加入一個Module文件。在Module文件中加入以下代碼:
Option Explicit
Public bIsWinNT As Boolean
'下面就是未公開的函數定義,注意在Alias之后沒有使用函數的真正名字
'而是用了函數編號,這是因為微軟沒有公開函數名
Declare Function SHRestartSystemMB Lib "shell32" _
Alias "#59" _
(ByVal hOwner As Long, _
ByVal sExtraPrompt As String, _
ByVal uFlags As Long) As Long
Declare Function SHShutDownDialog Lib "shell32" _
Alias "#60" _
(ByVal YourGuess As Long) As Long
Declare Function GetVersionEx Lib "kernel32" _
Alias "GetVersionExA" _
(lpVersionInformation As OSVERSIONINFO) As Long
Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128
End Type
Public Const EWX_LOGOFF = 0
Public Const EWX_SHUTDOWN = 1
Public Const EWX_REBOOT = 2
Public Const EWX_FORCE = 4
Public Const EWX_POWEROFF = 8
Public Const shrsExitNoDefPrompt = 1
Public Const shrsRebootSystem = 2
Const VER_PLATFORM_WIN32s = 0
Const VER_PLATFORM_WIN32_WINDOWS = 1
Const VER_PLATFORM_WIN32_NT = 2
Declare Sub CopyMemory Lib "kernel32" _
Alias "RtlMoveMemory" _
(pDest As Any, _
pSource As Any, _
ByVal ByteLen As Long)
Declare Function IsTextUnicode Lib "advapi32" _
(lpBuffer As Any, _
ByVal cb As Long, _
lpi As Long) As Long
Public Const IS_TEXT_UNICODE_ASCII16 = &H1
Public Const IS_TEXT_UNICODE_REVERSE_ASCII16 = &H10
Public Const IS_TEXT_UNICODE_STATISTICS = &H2
Public Const IS_TEXT_UNICODE_REVERSE_STATISTICS = &H20
Public Const IS_TEXT_UNICODE_CONTROLS = &H4
Public Const IS_TEXT_UNICODE_REVERSE_CONTROLS = &H40
Public Const IS_TEXT_UNICODE_SIGNATURE = &H8
Public Const IS_TEXT_UNICODE_REVERSE_SIGNATURE = &H80
Public Const IS_TEXT_UNICODE_ILLEGAL_CHARS = &H100
Public Const IS_TEXT_UNICODE_ODD_LENGTH = &H200
Public Const IS_TEXT_UNICODE_DBCS_LEADBYTE = &H400
Public Const IS_TEXT_UNICODE_NULL_BYTES = &H1000
Public Const IS_TEXT_UNICODE_UNICODE_MASK = &HF
Public Const IS_TEXT_UNICODE_REVERSE_MASK = &HF0
Public Const IS_TEXT_UNICODE_NOT_UNICODE_MASK = &HF00
Public Const IS_TEXT_UNICODE_NOT_ASCII_MASK = &HF000
Public Function IsWinNT() As Boolean
Dim osvi As OSVERSIONINFO
osvi.dwOSVersionInfoSize = Len(osvi)
GetVersionEx osvi
IsWinNT = (osvi.dwPlatformId = VER_PLATFORM_WIN32_NT)
End Function
Public Function CheckString(msg As String) As String
If bIsWinNT Then
CheckString = StrConv(msg, vbUnicode)
Else: CheckString = msg
End If
End Function
Public Function GetStrFromPtr(lpszStr As Long, nBytes As Integer) As String
ReDim ab(nBytes) As Byte
CopyMemory ab(0), ByVal lpszStr, nBytes
GetStrFromPtr = GetStrFromBuffer(StrConv(ab(), vbUnicode))
End Function
Public Function GetStrFromBuffer(szStr As String) As String
If IsUnicodeStr(szStr) Then szStr = StrConv(szStr, vbFromUnicode)
If InStr(szStr, vbNullChar) Then
GetStrFromBuffer = Left$(szStr, InStr(szStr, vbNullChar) - 1)
Else: GetStrFromBuffer = szStr
End If
End Function
Public Function IsUnicodeStr(sBuffer As String) As Boolean
Dim dwRtnFlags As Long
dwRtnFlags = IS_TEXT_UNICODE_UNICODE_MASK
IsUnicodeStr = IsTextUnicode(ByVal sBuffer, Len(sBuffer), dwRtnFlags)
End Function
然后在Form1中加入一個ComboBox控件、兩個CommandButton控件,然后在Form1的代碼窗口中加入以下代碼:
Private Sub Command1_Click()
Call SHShutDownDialog(0)
End Sub
Private Sub Command2_Click()
Dim sPrompt As String
Dim uFlag As Long
Select Case Combo1.ListIndex
Case -1: uFlag = Val(Combo1.Text)
Case 0: uFlag = shrsExitNoDefPrompt
Case 1: uFlag = shrsRebootSystem
End Select
If SHRestartSystemMB(hWnd, sPrompt, uFlag) = vbYes Then
End If
End Sub
Private Sub Form_Load()
bIsWinNT = IsWinNT()
If bIsWinNT Then 'WinNT操作系統
With Combo1
.AddItem "0 - 關閉程序并以其它用戶身份登陸"
.AddItem "1 - 關閉計算機"
.AddItem "2 - 重新啟動計算機"
.Text = ""
End With
Else 'Win95/98操作系統
With Combo1
.AddItem "1 - 關閉計算機"
.AddItem "2 - 重新啟動計算機"
.Text = ""
End With
End If
Command1.Caption = "關閉系統對話框"
Command2.Caption = "關閉或重新啟動計算機"
End Sub
運行程序,點擊“關閉系統對話框”按鈕就可以彈出關閉系統對話框。在Combo1中選擇關閉系統、重新啟動或者關閉程序并以其它用戶身份登陸項再點擊“關閉或重新啟動計算機”按鈕,系統就會彈出提示對話框提示是否執行相應的操作,點擊“是”就可以執行了。
E-Mail vbcode@21cn.com