怎么让主窗体最小化后缩放到右下脚的图标中?

解决方案 »

  1.   


                            用 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]。 
      

  2.   


    用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    
      
      

  3.   

    模块:
    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
      

  4.   

    就是,呵呵vb的安装光盘里有tray控件源码,编译一下就可以用了网上这种控件也很多还有,在csdn里搜索 托盘,你就会发现好大的一堆^_^