怎么让主窗体最小化后缩放到右下脚的图标中?
解决方案 »
- VB中如何判别EXCEL是否已经启动?
- 急~!~!~! 如何实现修改文件后缀名
- 关于IE临时文件夹的问题
- 如何生成动态的控件数组
- 请问如何完全删除 msflexgrid 中的所有内容?
- 用VB写的发送邮件程序,如何做到像OutLook中可以同时抄送给多个人?
- 救命!!!300分!!!!EpsonLQ2180打印問題
- 怎樣用VB實行向一個已有數據的WORD文檔中插入一行數據,謝謝各位老鳥
- 我用opendatabase打开链接到Excel文件的mdb文件出错????
- 静态窗口,如何在MDIForm1中确定子窗体Form1是否已经打开或者已经关闭?thanks
- 请教一个关于生成文件的图标问题!
- 如何使用vb来对modem编程,(使用tapi也可以)
用 Visual Basic编写托盘程序 Windows 95、Windows 98、Windows NT 等操作系统的界面上都增加了Shell层的技术,这就为广大编程人员开辟了界面编程的新途径。本文讲述的是如何用VB 5.0来编写托盘程序。 托盘程序主要解决两个问题:(1)创建、修改、删除托盘;(2)如何对托盘接收到的消息进行处理。这就要用到几个Win32 API。 首先,Shell_NotifyIcon是用于托盘的Shell API。该API用到一个NOTIFYICONDATA结构,该结构包括:hIcon(托盘图标指针)、hwnd(接收托盘图标消息的窗口指针)、szTIP(提示字符串)、uCallbackMessage(标志应用程序的消息)、uFlag(对托盘图标操作的标志,包括添加、删除、修改)、Uid(由程序定义的图标识别符,因为有的程序有多个图标)、cbSize(该结构所占的字节数)。因为该API的用法在许多书刊中都有论述,故在此处不再多讲,具体用法可参见下文的注释。 其次,应该考虑怎样在VB中接收、处理托盘的消息。C++、Delphi等语言对消息循环的处理较简单,但在VB中处理消息循环时必须应用Win32的API,而且要采用窗口子类化技术,需要用到SetWindowLong、CallWindowProc这两个API。SetWindowLong 函数利用GWL_WNDPROC 索引来创建窗口类的子类(窗口类是用来创建窗口的),它使用AddressOf 关键字和回调函数(WindowProc)来截取消息并根据消息来执行相应的功能,如窗口的最大化、最小化、隐藏、退出等。CallWindowProc函数调用原窗口类缺省的指针,程序最后退出时可通过SetWindowLong来关闭子类,重新使原来的 Windows 过程成为回调函数。因为代码要调用VB 5.0的函数指针,所以必须将该代码放到标准的 .BAS 模块中,不可以将它放到类模块中,也不能将其附加到窗体上。在使用 AddressOf 关键字声明函数时,必须注意:VB 5.0仅支持从 Visual Basic 到 DLL 函数的指针,不支持“Basic 到 Basic”的函数指针。 本程序项目名为TRAY.vbp,它包括模块TRAY.bas和窗体TRAY.frm。 1、TRAY.bas源代码 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 Public a As Long '以下为 Shell_NotifyIcon将用到的常量 Public Const NIF_ICON = &H2 Public Const NIF_MESSAGE = &H1 Public Const NIF_TIP = &H4 Public Const NIM_ADD = &H0 Public Const NIM_DELETE = &H2 Public Const NIM_MODIFY = &H1 'Shell_NotifyIcon的函数声明 Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" _ (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long '处理消息将用到的结构、常量、API声明 Type POINTAPI x As Long y As Long End Type Type Msg hwnd As Long message As Long wParam As Long lParam As Long time As Long pt As POINTAPI End Type Public Const WM_USER = &H400 Public Const WM_RBUTTONDOWN = &H204 Public Const WM_LBUTTONDOWN = &H201 Public Const GWL_WNDPROC = -4 Public trayflag As Boolean Global lpPrevWndProc As Long Global gHW 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 Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long '以下过程为消息循环处理 Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long If hw = Form1.hwnd And uMsg = WM_USER+100 Then'检测到鼠标点动托盘图标 Select Case lParam Case WM_RBUTTONDOWN '鼠标右键按下 Form1.PopupMenu Form1.traymnu '弹出菜单 Case WM_LBUTTONDOWN '鼠标左键按下 Form1.PopupMenu Form1.mnutray2 '弹出菜单 Case Else End Select Else '调用缺省窗口指针 WindowProc = CallWindowProc(lpPrevWndProc, hw,uMsg, wParam, lParam) End If End Function 2、TRAY.frm源代码 Dim MyNot As NOTIFYICONDATA '定义一个托盘结构 Private Sub Command1_Click() '鼠标按下删除按钮 With MyNot .hIcon = Form1.Icon '托盘图标指针 .hwnd = Form1.hwnd '窗体指针 .szTip = "" '弹出提示字符串 .uCallbackMessage = WM_USER+100 '对应程序定义的消息 .uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE '标志 .uID = 1 '图标识别符 .cbSize = Len(MyNot) '计算该结构所占字节数 End With hh = Shell_NotifyIcon(NIM_DELETE, MyNot) '删除该图标 trayflag = False '图标删除后trayflag为假 End Sub Private Sub Command2_Click() '按下创建按钮 Dim hh As Long With MyNot .hIcon = Form1.Icon .hwnd = Form1.hwnd .szTip = "托盘图标" & Chr(&H0) .uCallbackMessage = WM_USER+100 .uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE .uID = 1 .cbSize = Len(MyNot) End With hh = Shell_NotifyIcon(NIM_ADD, MyNot) '添加一个托盘图标 trayflag = True '图标添加后trayflag为真 End Sub Private Sub Command3_Click() '修改托盘图标 Dim hh As Long Set P = LoadPicture("c:\dos\bridge.ico") '导入一个新图标 With MyNot .hIcon = P '将托盘图标改为新图标 .hwnd = Form1.hwnd .szTip = "桥梁图标" & Chr(&H0) '更改提示信息 .uCallbackMessage = WM_USER+100 .uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE .uID = 1 .cbSize = Len(MyNot) End With hh = Shell_NotifyIcon(NIM_MODIFY, MyNot) '修改托盘的某些特征 End Sub Private Sub Command4_Click() 'END按钮被按下 Quit '调用退出函数Quit End Sub Private Sub Form_Load() gHW = Me.hwnd '取得本窗体指针 '下一句调用钩子函数,将自制消息处理函数钩入Windows的消息循环 hook End Sub Public Sub hook() '利用AddressOf取得消息处理函数WindowProc的指针,并将其传给SetWindowLong 'lpPrevWndProc用来存储原窗口的指针 lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, AddressOfWindowProc) End Sub Public Sub Unhook() '本子程序用原窗口的指针替换WindowProc函数的指针,即关闭子类、退出消息循环 Dim temp As Long temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc) End Sub Private Sub mnuhideForm_Click() '点中弹出菜单的‘隐藏’功能 Form1.Hide '将窗体隐藏 End Sub Private Sub mnumaxForm_Click() '点中弹出菜单的‘最大化’功能 formstatus (2) '窗体最大化 End Sub Private Sub mnuminForm_Click() '点中弹出菜单的‘最小化’功能 formstatus (1) '窗体最小化 End Sub Private Sub mnunorForm_Click() '点中弹出菜单的‘正常’功能 formstatus (0) '窗体还原到正常 End Sub Public Sub quit() '退出 If trayflag = True Then Command1_Click '托盘图标仍在,模拟按下‘删除’按钮 Unhook '退出消息循环 Unload Me '卸载窗体 End Sub Private Sub mnuQuit_Click() '点中弹出菜单的‘退出’功能 quit End Sub Public Sub formstatus(ByVal wstates) '根据传递的参数变化窗体的状态 Form1.WindowState = wstates '设置窗体的状态 Form1.Show '显示窗体 End Sub 对于Shell_NotifyIcon函数的介绍可参见Win32 API类的书籍。因为在VB中使用函数指针将大大降低程序的坚固性,所以在应用与其相关的函数及关键字时应多加小心。在工作的时候必须经常地保存和备份工作成果。也可以借用第三方的回调消息控件来实现消息循环,这样做会比较安全一些。有兴趣的读者还可以参阅以下网址:www.mywebpages.com/nagar(VB编程的各种技术及控件)、www.chez.com/scribe/vb_us.htm(在VB中用OpenGL、DirectX编程)、 www.apexsc.com/vb/index.html(VB编程之家)。希望与我进一步交流的朋友请e-mail至[email protected]。
用VB实现托盘动画图标
现在,程序员把自己开发的程序的静态图标放入托盘已不是难事,使用Visual C++、Visual Basic、Delphi等编程语言,借助于Windows API函数(Shell_NotifyIcon)可以很容易地实现对托盘图标的操作。那么,如何在托盘中实现动态图标呢?本文将通过一个在托盘中交替显示笑脸/哭脸的实例来介绍用VB实现托盘中动画图标的方法和步骤。
1.可视部分设计
新建一个标准EXE项目,在窗体中设置如下控件:
⑴一个计时器(命名为timer1),其属性Enabled=False、Interval=100;
⑵一个弹出选单(命名为mMyPopMenu),设计时清除其“可视”检查框(右单击托盘动画图标时弹出);
⑶若干图画框(本例为2个),这些图画框名称相同(例如picture1),其Index属性值依次为0、1、2、...,Visible属性值均为False,Picture属性设置为循环显示的图标文件,如图1所示;
图1
⑷其它控件,根据程序实际功能需要设置。
2.编写程序代码
⑴在窗体的声明部分给出如下声明:
Private Type NOTIFYICONDATA
cbSize As Long
注释:指定NOTIFYICONDATA结构长度
hWnd As Long 注释:指定接收回调消息的窗体或控件的句柄
uId As Long
注释:指定放入托盘中的图标的ID标识
uFlags As Long
注释:指定要绘制的图标的属性
ucallbackMessage As Long
注释:指定一条自定义的回调消息
hIcon As Long
注释:指定要显示于托盘中的图标的句柄
szTip As String * 64
注释:指定图标的提示信息
End Type
Private Const NIF_ICON = &&H2
Private Const NIF_MESSAGE = &&H1
Private Const NIF_TIP = &&H4
Private Const NIM_ADD = &&H0
Private Const NIM_DELETE = &&H2
Private Const NIM_MODIFY = &&H1
Private Const WM_MOUSEMOVE = &&H200
Private Declare Function Shell_NotifyIcon Lib "shell32" _
Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, _
pnid As NOTIFYICONDATA) As Boolean
Dim tb As NOTIFYICONDATA
⑵窗体加载时把图标放入托盘:
Private Sub Form_Load()
mMyPopMenu.Visible = False
注释:使弹出选单隐藏
mHide.Enabled = False
With tb
.cbSize = Len(tb)
.hWnd = Picture1(0).hWnd
.uId = 1&&
.uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
.ucallbackMessage = WM_MOUSEMOVE
.hIcon = Picture1(0).Picture
.szTip = "托盘动画图标演示" && Chr$(0)
End With
Shell_NotifyIcon NIM_ADD, tb
Timer1.Enabled = True
Me.Hide
App.TaskVisible = False
End Sub
⑶计时器每触发一次就修改一下托盘中的图标:
Private Sub timer1_Timer()
Static i As Integer
i =(i+1) Mod 2 注释:2 为图画框的个数
With tb
.cbSize = Len(tb)
.hWnd = Picture1(0).hWnd
.uId = 1&&
.uFlags = NIF_ICON
.hIcon = Picture1(i).Picture
End With
Shell_NotifyIcon NIM_MODIFY, tb
Timer1.Enabled = True
End Sub
⑷响应托盘中图标的鼠标事件:
Private Sub picture1_MouseMove(Index As Integer, _
Button As Integer, Shift As Integer, _
X As Single, Y As Single)
If X = &&H1E3C Then
Me.PopupMenu mMyPopMenu
End If
End Sub
⑸窗体卸载时删除托盘中的图标:
Private Sub Form_Unload(Cancel As Integer)
Timer1.Enabled = False
With tb
.cbSize = Len(tb)
.hWnd = Picture1(0).hWnd
.uId = 1&&
End With
Option ExplicitPublic clsDB As clsDatabasePublic Const SWP_NOMOVE = &H2
Public Const SWP_NOSIZE = &H1
Public Const HWND_TOPMOST = -1
Public Const HWND_NOTOPMOST = -2Public 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 LongPublic Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPrivate Type STARTUPINFO
cb As Long
lpReserved As String
lpDesktop As String
lpTitle As String
dwX As Long
dwY As Long
dwXSize As Long
dwYSize As Long
dwXCountChars As Long
dwYCountChars As Long
dwFillAttribute As Long
dwFlags As Long
wShowWindow As Integer
cbReserved2 As Integer
lpReserved2 As Long
hStdInput As Long
hStdOutput As Long
hStdError As Long
End TypePrivate Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId As Long
End TypePublic Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Public Declare Function CreateProcessA Lib "kernel32" (ByVal lpApplicationName As Long, ByVal lpCommandLine As String, ByVal lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, ByVal lpCurrentDriectory As Long, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Const NORMAL_PRIORITY_CLASS = &H20
Public Const INFINITE = &HFFFF ' Infinite timeoutPublic OldWindowProc As Long
Public TheForm As Form
Public TheMenu As Menu
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
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Declare Function Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As Long
Public Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
Public Const WM_USER = &H400
Public Const WM_LBUTTONUP = &H202
Public Const WM_MBUTTONUP = &H208
Public Const WM_RBUTTONUP = &H205
Public Const TRAY_CALLBACK = (WM_USER + 1001&)
Public Const GWL_WNDPROC = (-4)
Public Const GWL_USERDATA = (-21)
Public Const NIF_ICON = &H2
Public Const NIF_TIP = &H4
Public Const NIM_ADD = &H0
Public Const NIF_MESSAGE = &H1
Public Const NIM_MODIFY = &H1
Public Const NIM_DELETE = &H2
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
Private TheData As NOTIFYICONDATA
'新的窗口程序,它将取代原来的窗口程序
Public Function NewWindowProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
'如果用户单击了托盘图标
If Msg = TRAY_CALLBACK Then
' 单击的是左键,恢复窗体
If lParam = WM_LBUTTONUP Then
TheForm.Show
TheForm.WindowState = 0
' TheForm.StartUpPosition = 2
End If
'单击的是右键,弹出快捷菜单
If lParam = WM_RBUTTONUP Then
SetForegroundWindow TheForm.hwnd
TheForm.PopupMenu TheMenu
Exit Function
End If
End If
'将其他消息传递给原来的窗口程序
NewWindowProc = CallWindowProc(OldWindowProc, hwnd, Msg, wParam, lParam)
End Function
'将程序图标添加到系统托盘区
Public Sub AddToTray(frm As Form, mnu As Menu)
'保存变量以供其他处引用
Set TheForm = frm
Set TheMenu = mnu
'装载新的窗口程序
OldWindowProc = SetWindowLong(frm.hwnd, GWL_WNDPROC, AddressOf NewWindowProc)
' 将程序图标添加到系统托盘区
With TheData
.uID = 0
.hwnd = frm.hwnd
.cbSize = Len(TheData)
.hIcon = frm.Icon.Handle
.uFlags = NIF_ICON + NIF_TIP + NIF_MESSAGE
.uCallbackMessage = TRAY_CALLBACK
.uFlags = .uFlags Or NIF_MESSAGE
.cbSize = Len(TheData)
End With
Shell_NotifyIcon NIM_ADD, TheData
End Sub
'将图标从系统托盘区中删除
Public Sub RemoveFromTray()
With TheData
.uFlags = 0
End With
Shell_NotifyIcon NIM_DELETE, TheData
' 恢复原来的窗口程序 .
SetWindowLong TheForm.hwnd, GWL_WNDPROC, OldWindowProc
End Sub
'设置图标的提示信息
Public Sub SetTrayTip(tip As String)
With TheData
.szTip = tip & vbNullChar
.uFlags = NIF_TIP
End With
Shell_NotifyIcon NIM_MODIFY, TheData
End Sub窗体:
Private Sub Form_Load()
'调用添加托盘图标子程序
AddToTray Me, mnuHide_
'调用在托盘图标上显示提示的子程序
SetTrayTip "Document Manager"
End SubPrivate Sub Form_Unload(Cancel As Integer)
RemoveFromTray '移除系统托盘
End Sub