您的位置:首页 > 编程语言 > VB

完美隐藏系统托盘图标(VB源码)![转贴]

2009-02-17 16:39 375 查看
我做桌面托盘隐藏时翻译了一篇文章是关于托盘。现在公开我这个翻译。

三个文件,一个是FORM1,modIconToPic、modMain。

'************************modMain***********************************

'**模 块 名:获取托盘图标

'**说 明:By:小江翻译(http://www.codeproject.com/KB/applications/ShellTrayInfo.aspx

'**日 期:2008-12-10 00:27:01

'*************************************************************************

Option Explicit

Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long

Public Declare Function VirtualAllocEx Lib "kernel32.dll" (ByVal hProcess As Long, lpAddress As Any, ByRef dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long

Private Declare Function VirtualFreeEx Lib "kernel32.dll" (ByVal hProcess As Long, lpAddress As Any, ByRef dwSize As Long, ByVal dwFreeType As Long) As Long

Public Declare Function ReadProcessMemory Lib "kernel32.dll" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long

Public Declare Function EnumProcessModules Lib "PSAPI.DLL" (ByVal hProcess As Long, ByRef lphModule As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long

Public Declare Function GetModuleFileNameExA Lib "PSAPI.DLL" (ByVal hProcess As Long, ByVal hModule As Long, ByVal ModuleName As String, ByVal nSize As Long) As Long

Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Public Declare Function GetIconInfo Lib "user32" (ByVal hIcon As Long, piconinfo As ICONINFO) As Long

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Public Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long

Public Declare Function GetWindowThreadProcessId Lib "user32.dll" (ByVal hWnd As Long, lpdwProcessId As Long) As Long

Public Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long

'加入托盘

Public Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long

Public Const NIM_ADD = &H0 '表示要往任务栏中加入图标

Public Const NIM_DELETE = &H2 '删除图标

Public Const NIM_MODIFY = &H1 '修改图标

Public Const NIF_ICON = &H2 '允许图标显示

Public Const NIF_MESSAGE = &H1 '允许图标消息转发

Public Const NIF_TIP = &H4 '允许图标显示图标提示字符串

Public Const WM_USER = &H400

Public Const WM_NOTIFYICON = WM_USER + 1 ' 自定义消息,用于子类化时,取得托盘相应信息

'托盘BOTTON

Public Const TBSTATE_HIDDEN = &H8

Public Const WM_SIZE = &H5

'Public Const WM_USER As Long = &H400

Public Const TB_BUTTONCOUNT As Long = (WM_USER + 24)

Public Const TB_HIDEBUTTON As Long = (WM_USER + 4)

Public Const TB_GETBUTTON As Long = (WM_USER + 23)

Public Const TB_GETBITMAP As Long = (WM_USER + 44)

Public Const TB_DELETEBUTTON As Long = (WM_USER + 22)

Public Const TB_ADDBUTTONS As Long = (WM_USER + 20)

Public Const TB_INSERTBUTTON As Long = (WM_USER + 21)

Public Const TB_GETBUTTONTEXTA As Long = (WM_USER + 45)

Public Const TB_ISBUTTONHIDDEN As Long = (WM_USER + 12)

Public Const TB_MOVEBUTTON = (WM_USER + 82)

Public Const TB_AUTOSIZE As Long = (WM_USER + 33)

Public Const ILD_NORMAL As Long = &H0

'进程读写

Public Const READ_CONTROL As Long = &H20000

Public Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000

Public Const STANDARD_RIGHTS_READ As Long = (READ_CONTROL)

Public Const STANDARD_RIGHTS_EXECUTE As Long = (READ_CONTROL)

Public Const STANDARD_RIGHTS_ALL As Long = &H1F0000

Public Const STANDARD_RIGHTS_WRITE As Long = (READ_CONTROL)

Public Const SYNCHRONIZE As Long = &H100000

Public Const PROCESS_ALL_ACCESS As Long = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)

Public Const PROCESS_TERMINATE As Long = (&H1)

'内存读写参数

Public Const PROCESS_VM_OPERATION As Long = (&H8)

Public Const PROCESS_VM_READ As Long = (&H10)

Public Const PROCESS_VM_WRITE As Long = (&H20)

Public Const MEM_RESERVE As Long = &H2000

Public Const MEM_COMMIT As Long = &H1000

Public Const MEM_RELEASE As Long = &H8000

Public Const PAGE_READWRITE As Long = &H4

'窗口状态参数

Public Const SW_HIDE = 0

Public Const SW_SHOW = 5

Public Const SW_MINIMIZE = 6

Public Const PROCESS_QUERY_INFORMATION = 1024

'托盘

Public Type NOTIFYICONDATA

cbSize As Long

hWnd As Long

uid As Long

uFlags As Long

uCallBackMessage As Long

hIcon As Long

szTip As String * 64

End Type

'ICON结构

Public Type ICONINFO

fIcon As Long

xHotspot As Long

yHotspot As Long

hbmMask As Long

hbmColor As Long

End Type

'Botton结构

Public Type TBBUTTON

iBitmap As Long

idCommand As Long

fsState As Byte

fsStyle As Byte

bReserved1 As Byte

bReserved2 As Byte

dwData As Long

iString As Long

End Type

''没有公开的TRAYDATA结构

Public Type TRAYDATA

hWnd As Long

uid As Long

uCallBackMessage As Long

Reserved1(0 To 1) As Long

hIcon As Long

Reserved2(0 To 5) As Integer

ExePath(0 To 255) As Byte

End Type

'自定义结构

Public Type TrayItemInfo

hWnd As Long

uid As Long

hIcon As Long

uCallBackMessage As Long

sTip As String

sProcessPath As String

lIdCommand As Long

bVisible As Boolean

IsSetHide As Boolean

End Type

Public Const MAX_PATH& = 260

Public m_hTrayWnd As Long

Sub Main()

Form1.Show

End Sub

'*************************************************************************

'**函 数 名:得到系统托盘句柄

'*************************************************************************

Public Function FindSysTray() As Long

Dim hTrayWnd As Long

hTrayWnd = FindWindow("Shell_TrayWnd", vbNullString)

If hTrayWnd <> 0 Then

hTrayWnd = FindWindowEx(hTrayWnd, 0, "TrayNotifyWnd", vbNullString)

hTrayWnd = FindWindowEx(hTrayWnd, 0, "SysPager", vbNullString)

If hTrayWnd <> 0 Then

hTrayWnd = FindWindowEx(hTrayWnd, 0, "ToolbarWindow32", vbNullString)

End If

End If

FindSysTray = hTrayWnd

End Function

'*************************************************************************

'**函 数 名:转换BYTE数组 及 去除最后的"\0"。

'*************************************************************************

Public Function DelEndNull(ByVal sSrc As String) As String

Dim lNullpos As Long

lNullpos = InStr(sSrc, Chr$(0))

If lNullpos > 0 Then

DelEndNull = Left$(sSrc, lNullpos - 1)

Else

DelEndNull = sSrc

End If

End Function

'*************************************************************************

'**函 数 名:'去除路径中的??问号。

'*************************************************************************

Public Function CheckPath(ByVal sPath As String) As String

On Error Resume Next

sPath = Replace$(sPath, "\??\", "")

If UCase$(Left$(sPath, 12)) = "\SYSTEMROOT\" Then sPath = GetWinDir & Mid$(sPath, 12)

CheckPath = sPath

End Function

'*************************************************************************

'**函 数 名'得到系统路径

'*************************************************************************

Public Function GetWinDir() As String

Dim sTemp As String * 256

Dim iCharLen As Integer

iCharLen = GetWindowsDirectory(sTemp, Len(sTemp))

GetWinDir = Left$(sTemp, iCharLen)

End Function

'------------------------modIconToPic------------------------------------------------

Option Explicit

'网络上抄摘,原作者不详。

'把ICON文件转为一般图像文件与获取EXE文件的图标

'OleCreatePictureIndirect建立一个图像对象,并返回对象句柄

'pDicDesc 图象结构

'riid 接口的标识符

'fown 是否清除图像对象,如设置为真,则图片对象将摧毁它的图片当对象被摧毁时。如果假, 则由用户负责摧毁图片对象。

'lpUnk 输出变量地址接口类型

Public Declare Function OleCreatePictureIndirect Lib "oleaut32.dll" (pDicDesc As TypeIcon, riid As CLSID, ByVal fown As Long, lpUnk As Object) As Long

Public Type TypeIcon

cbSize As Long '结构大小

picType As PictureTypeConstants '图像类型

hIcon As Long '图标句柄

End Type

'CLSID类标识符的缩写

Public Type CLSID

id(16) As Byte '由16个成员组成的字节数组

End Type

Private Declare Function SHGetFileInfo Lib "shell32.dll" Alias "SHGetFileInfoA" (ByVal pszPath As String, ByVal dwFileAttributes As Long, psfi As SHFILEINFO, ByVal cbFileInfo As Long, ByVal uFlags As Long) As Long

Private Type SHFILEINFO

hIcon As Long '文件的图标句柄

iIcon As Long '图标的系统索引号

dwAttributes As Long '文件的属性值

szDisplayName As String * 260 '文件的显示名

szTypeName As String * 80 '文件的类型名

End Type

Public Const SHGFI_ICON = &H100 '获得图标

Public Const SHGFI_LARGEICON = &H0 '获取文件大图标

Public Const SHGFI_SMALLICON = &H1 '获取小图标

'ICON 转 Picture

Public Function IconToPic(hIcon As Long) As IPictureDisp

Dim cls_id As CLSID

Dim hRes As Long

Dim new_icon As TypeIcon

Dim lpUnk As IUnknown 'Com接口

With new_icon

.cbSize = Len(new_icon)

.picType = vbPicTypeIcon 'Picture 对象的图标类型

.hIcon = hIcon

End With

With cls_id

.id(8) = &HC0

.id(15) = &H46

End With

hRes = OleCreatePictureIndirect(new_icon, cls_id, 1, lpUnk)

If hRes = 0 Then Set IconToPic = lpUnk

End Function

'获得文件ICON

Public Function GetExeIcon(FileName, Optional ByVal SmallIcon As Boolean = True) As IPictureDisp

Dim Index As Integer

Dim hIcon As Long

Dim item_num As Long

Dim icon_pic As IPictureDisp

Dim sh_info As SHFILEINFO

If SmallIcon = True Then

SHGetFileInfo FileName, 0, sh_info, Len(sh_info), SHGFI_ICON + SHGFI_SMALLICON

Else

SHGetFileInfo FileName, 0, sh_info, Len(sh_info), SHGFI_ICON + SHGFI_LARGEICON

End If

hIcon = sh_info.hIcon

Set icon_pic = IconToPic(hIcon)

Set GetExeIcon = icon_pic

Set icon_pic = Nothing

End Function

'*************************************************************************

'**函 数 名:通过PID返回程序路径

'*************************************************************************

Public Function GetAppPathByPid(lPid As Long) As String

Dim sRet As String

Dim lret As Long

Dim lModules(1 To MAX_PATH) As Long

Dim sModName As String

Dim lCBSize As Long

Dim hProcess As Long

Dim sProcessPath As String

sProcessPath = "[Unknown Process]"

hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, False, lPid)

If hProcess Then

lret = EnumProcessModules(hProcess, lModules(1), MAX_PATH, lCBSize)

If lret <> 0 Then

sModName = Space$(MAX_PATH)

lret = GetModuleFileNameExA(hProcess, lModules(1), sModName, 500) '从句柄的取得对应的程序路径

sProcessPath = Left$(sModName, lret)

sProcessPath = CheckPath(Trim$(sProcessPath)) '去除路径中\??\的内容

End If

End If

GetAppPathByPid = sProcessPath

CloseHandle hProcess

End Function

'-------------------------------form1---------------------------------------

Option Explicit

'*************************************************************************

'**模 块 名:获取托盘图标

'**说 明:By:小江翻译(http://www.codeproject.com/KB/applications/ShellTrayInfo.aspx

'**日 期:2008-12-10 00:27:01

'*************************************************************************

Private Declare Function GetLastError Lib "kernel32" () As Long

Private m_aTrayinfo() As TrayItemInfo

Private iIndex As Integer

Public Sub Command1_Click()

Dim lTrayPid As Long

Dim lCount As Long

Dim lret As Long

Dim hProcess As Long

Dim lAddress As Long

Dim udtTb As TBBUTTON

Dim udtTray As TRAYDATA

Dim udtTifo As TrayItemInfo

Dim lTextAdr As Long

Dim asTip(0 To 1024) As Byte

Dim sTip As String

Dim icoInfo As ICONINFO

Dim i As Integer

Set ListView1.Icons = Nothing

Set ListView1.SmallIcons = Nothing

ListView1.ListItems.Clear

ImageList1.ListImages.Clear

ImageList1.ImageHeight = 16

ImageList1.ImageWidth = 16

m_hTrayWnd = FindSysTray()

lret = GetWindowThreadProcessId(m_hTrayWnd, lTrayPid)

lCount = SendMessage(m_hTrayWnd, TB_BUTTONCOUNT, 0, ByVal 0&)

hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, lTrayPid)

lAddress = VirtualAllocEx(hProcess, ByVal 0&, ByVal 4096&, MEM_COMMIT, PAGE_READWRITE)

For i = 0 To lCount - 1

lret = SendMessage(m_hTrayWnd, TB_GETBUTTON, ByVal i, ByVal lAddress&)

lret = ReadProcessMemory(hProcess, ByVal lAddress, ByVal VarPtr(udtTb), ByVal Len(udtTb), ByVal 0&)

lret = ReadProcessMemory(hProcess, ByVal udtTb.dwData, ByVal VarPtr(udtTray), ByVal Len(udtTray), ByVal 0&)

udtTifo.sProcessPath = DelEndNull(udtTray.ExePath)

If Not CBool((udtTb.fsState And TBSTATE_HIDDEN)) Then

lret = ReadProcessMemory(hProcess, ByVal udtTb.iString, ByVal VarPtr(asTip(0)), ByVal 1024, ByVal 0&)

sTip = DelEndNull(asTip)

Else

sTip = "[Hidden Icon]"

End If

With udtTifo

.sTip = sTip

.hWnd = udtTray.hWnd

.uCallBackMessage = udtTray.uCallBackMessage

.uid = udtTray.uid

.bVisible = Not CBool((udtTb.fsState And TBSTATE_HIDDEN))

.hIcon = udtTray.hIcon

End With

If GetIconInfo(udtTray.hIcon, icoInfo) <> 0 Then

ImageList1.ListImages.Add , , IconToPic(udtTray.hIcon)

'Debug.Print GetLastError

Else

ImageList1.ListImages.Add , , GetExeIcon(udtTifo.sProcessPath)

End If

Debug.Print sTip, GetLastError, i

If ImageList1.ListImages.Count = 1 Then

Set ListView1.Icons = ImageList1

Set ListView1.SmallIcons = ImageList1

End If

ReDim Preserve m_aTrayinfo(0 To i)

m_aTrayinfo(i) = udtTifo

ListView1.ListItems.Add i + 1, , udtTifo.sTip, 1, i + 1

ListView1.ListItems(i + 1).SubItems(1) = udtTifo.sProcessPath

Next

VirtualFreeEx hProcess, ByVal lAddress, ByVal 4096&, MEM_RELEASE

CloseHandle hProcess

End Sub

Public Sub Command2_Click()

Dim s As String

iIndex = ListView1.SelectedItem.Index - 1

s = ListView1.SelectedItem.Text

Debug.Print s

If iIndex > 0 And s <> "[Hidden Icon]" Then

Call SendMessage(m_hTrayWnd, TB_MOVEBUTTON, iIndex, ByVal CLng(iIndex - 1))

Call Command1_Click

ListView1.SelectedItem = ListView1.ListItems(iIndex)

ListView1.SelectedItem.EnsureVisible

ListView1.SetFocus

End If

End Sub

Public Sub Command3_Click()

Dim s As String

iIndex = ListView1.SelectedItem.Index - 1

s = ListView1.SelectedItem.Text

Debug.Print s

If iIndex < ListView1.ListItems.Count - 1 And s <> "[Hidden Icon]" Then

Call SendMessage(m_hTrayWnd, TB_MOVEBUTTON, iIndex, ByVal CLng(iIndex + 1))

Call Command1_Click

ListView1.SelectedItem = ListView1.ListItems(iIndex + 2)

ListView1.SelectedItem.EnsureVisible

ListView1.SetFocus

End If

End Sub

Private Sub Command4_Click()

iIndex = ListView1.SelectedItem.Index - 1

Const WM_RBUTTONDOWN = &H204

Const WM_RBUTTONUP = &H205

Call PostMessage(m_aTrayinfo(iIndex).hWnd, m_aTrayinfo(iIndex).uCallBackMessage, m_aTrayinfo(iIndex).uid, WM_RBUTTONDOWN)

Call PostMessage(m_aTrayinfo(iIndex).hWnd, m_aTrayinfo(iIndex).uCallBackMessage, m_aTrayinfo(iIndex).uid, WM_RBUTTONUP)

End Sub

Private Sub Command5_Click()

Dim udtIconData As NOTIFYICONDATA

iIndex = ListView1.SelectedItem.Index - 1

If m_aTrayinfo(iIndex).bVisible Then

With udtIconData

.cbSize = Len(udtIconData)

.hIcon = m_aTrayinfo(iIndex).hIcon

.hWnd = m_aTrayinfo(iIndex).hWnd

.szTip = m_aTrayinfo(iIndex).sTip

.uCallBackMessage = m_aTrayinfo(iIndex).uCallBackMessage

'*注:这要hIcon、szTip、uCallBackMessage对应相对应的值。这里我默认三者都有!

.uFlags = NIF_ICON Or NIF_MESSAGE Or NIF_TIP

.uid = m_aTrayinfo(iIndex).uid

End With

If m_aTrayinfo(iIndex).IsSetHide Then

m_aTrayinfo(iIndex).IsSetHide = False

Call Shell_NotifyIcon(NIM_ADD, udtIconData)

Command5.Caption = "HIDE"

Else

m_aTrayinfo(iIndex).IsSetHide = True

Call Shell_NotifyIcon(NIM_DELETE, udtIconData)

Command5.Caption = "SHOW"

End If

End If

End Sub

Private Sub Form_Load()

Call Command1_Click

End Sub

Private Sub Form_Unload(Cancel As Integer)

Dim iIndex As Integer

Dim udtIconData As NOTIFYICONDATA

Cancel = 1

For iIndex = 0 To UBound(m_aTrayinfo)

If m_aTrayinfo(iIndex).IsSetHide Then

With udtIconData

.cbSize = Len(udtIconData)

.hIcon = m_aTrayinfo(iIndex).hIcon

.hWnd = m_aTrayinfo(iIndex).hWnd

.szTip = m_aTrayinfo(iIndex).sTip

.uCallBackMessage = m_aTrayinfo(iIndex).uCallBackMessage

'*注:这要hIcon、szTip、uCallBackMessage对应相对应的值。这里我默认三者都有!

.uFlags = NIF_ICON Or NIF_MESSAGE Or NIF_TIP

.uid = m_aTrayinfo(iIndex).uid

End With

Call Shell_NotifyIcon(NIM_ADD, udtIconData)

End If

Next

Cancel = 0

End Sub
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: