运行中隐藏/显示窗口标题栏
声明:
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long 
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long 
Private Const GWL_STYLE = (-16) 
Private Const WS_CAPTION = &HC00000
Private Const WS_MAXIMIZEBOX = &H10000 
Private Const WS_MINIMIZEBOX = &H20000 
Private Const WS_SYSMENU = &H80000 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 Enum ESetWindowPosStyles 
SWP_SHOWWINDOW = &H40 
SWP_HIDEWINDOW = &H80 
SWP_FRAMECHANGED = &H20 ' The frame changed: send WM_NCCALCSIZE 
SWP_NOACTIVATE = &H10 
SWP_NOCOPYBITS = &H100 
SWP_NOMOVE = &H2 
SWP_NOOWNERZORDER = &H200 ' Don't do owner Z ordering 
SWP_NOREDRAW = &H8 
SWP_NOREPOSITION = SWP_NOOWNERZORDER 
SWP_NOSIZE = &H1 
SWP_NOZORDER = &H4 
SWP_DRAWFRAME = SWP_FRAMECHANGED 
HWND_NOTOPMOST = -2 
End Enum Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long 
Private Type RECT 
Left As Long 
Top As Long 
Right As Long 
Bottom As Long 
End Type Private Function ShowTitleBar(ByVal bState As Boolean) 
Dim lStyle As Long 
Dim tR As RECT GetWindowRect Me.hwnd, tR 
lStyle = GetWindowLong(Me.hwnd, GWL_STYLE) 
If (bState) Then 
Me.Caption = Me.Tag 
If Me.ControlBox Then 
lStyle = lStyle Or WS_SYSMENU 
End If 
If Me.MaxButton Then 
lStyle = lStyle Or WS_MAXIMIZEBOX 
End If 
If Me.MinButton Then 
lStyle = lStyle Or WS_MINIMIZEBOX 
End If 
If Me.Caption <> "" Then 
lStyle = lStyle Or WS_CAPTION 
End If 
Else 
Me.Tag = Me.Caption 
Me.Caption = "" 
lStyle = lStyle And Not WS_SYSMENU 
lStyle = lStyle And Not WS_MAXIMIZEBOX 
lStyle = lStyle And Not WS_MINIMIZEBOX 
lStyle = lStyle And Not WS_CAPTION 
End If 
SetWindowLong Me.hwnd, GWL_STYLE, lStyle 任务栏的右下角显示要编写托盘程序。 

解决方案 »

  1.   

    不在任务栏显示窗体,将窗体的ShowInTaskBar属性改为False不就行了吗?用得着那么复杂吗?
    至于在任务栏的右下角显示为一个图标,正如楼上的所说。
      

  2.   

    引用vb编程乐园的一篇文章吧:   把最小化图标放到任务栏右下角---- 目 前 有 不 少Win95 应 用 程 序 在 最 小 化 后, 代 表 该 程 序 的 小 图 标 就 会 隐 藏 在 屏 幕 的 右 下 角( 即 任 务 栏 的 右 边), 如“ 金 山 词 霸”、“ 东 方 快 车” 等, 而 我 们 用Visual Basic 编 制 的 程 序 在 最 小 化 后, 图 标 却 总 是 出 现 在 任 务 栏 的 中 央, 并 且 占 据 较 大 的 空 间。 如 何 让 我 们 自 己 的 程 序 也 能 将 最 小 化 图 标 放 在 任 务 栏 的 右 边 呢 ? 我 们 可 以 通 过Windows API 函 数 调 用 来 实 现 该 功 能。 一、 如 何 添 加 和 隐 藏 图 标
    ---- 在Windows 的 动 态 连 接 库Shell32.dll 中 有 一 个 名 为Shell_NotifyIconA 的Windows API 函 数, 其 功 能 是 对 任 务 栏 的 右 下 角 图 标 进 行 操 作, 包 括 添 加、 删 除 和 修 改。Shell_NotifyIconA 函 数 的VB 声 明 格 式 如 下: 
    ---- Declare Function Shell_NotifyIconA Lib "SHELL32" (ByVal dwMessage As Long, lpData As NOTIFYICONDATA) As IntegerShell_NotifyIconA 有 两 个 参 数DwMessage 和lpData。DwMessage 为 操 作 图 标 的 方 式, 可 能 的 取 值 和 含 义 如 下: ---- 0( 向 任 务 栏 添 加 图 标) 
    ---- 1( 修 改 任 务 栏 中 的 图 标) 
    ---- 2( 删 除 任 务 栏 中 的 图 标) ---- lpData 是 自 定 义 数 据 类 型NOTIFYICONDATA 的 数 据, 该 自 定 义 数 据 结 构 由 以 下 成 员 构 成: ---- 1. cbSize: 需 填 写NOTIFYICONDATA 数 据 结 构 的 长 度, 在 使 用 时 可 通 过VB 的 标 准 函 数Len 来 计 算, 如nid 为NOTIFYICONDATA 类 型 的 变 量, 则cbSize 为Len(nid)。 ---- 2. hWnd: 最 小 化 窗 体 的 句 柄。 ---- 3. uID: 使 用 者 为 图 标 所 设 定 的 ID, 可 自 定。 ---- 4. uFlags: 用 来 设 定 后 面 三 个 成 员(uCallbackMessage、hIcon、szTip) 是 否 有 效, 等 于 1 时 为uCallbackMessage 有 效, 将 来 使 用 者 在 图 标 上 按 下 鼠 标 键 时, Windows 会 发 出 消 息 给 窗 体 程 序; 等 于 2 时 为hIcon 有 效, 表 示 要 显 示 图 标( 如 果 不 显 示 图 标, 用 户 只 是 无 法 看 见 图 标, 但 仍 然 可 在 任 务 栏 的 图 标 应 该 出 现 的 位 置 上 操 作); 等 于 4 时 为szTip 有 效, 当 用 户 将 鼠 标 指 针 放 在 图 标 上 时, 要 显 示 提 示 信 息, 否 则 不 显 示。 通 常 将uFlags 设 定 成 7( 即 1 + 2 + 4), 表 示 全 部 有 效。 ---- 5. uCallbackMessage: 当 用 户 在 图 标 上 按 下 鼠 标 按 键 时,Windows 发 给 应 用 程 序 的 消 息 编 号。 ---- 6. hIcon: 图 标 句 柄。 ---- 7. szTip: 当 用 户 将 鼠 标 指 针 放 在 图 标 上 时 显 示 的 提 示 信 息。 ---- 在 调 用Shell_NotifyIconA 函 数 之 前, 必 须 将NOTIFYICONDATA 类 型 变 量 的 以 上 各 成 员 填 写 正 确 的 内 容。 ---- 该 函 数 如 果 调 用 成 功 则 返 回1, 否 则 返 回0。 ---- 了 解 了Shell_NotifyIconA 函 数 的 功 能 和 用 法 后, 我 们 可 以 很 容 易 地 将 图 标 添 加 在 任 务 栏 的 右 边, 或 者 从 任 务 栏 上 将 图 标 删 除。 ---- 如: 假 设 我 们 事 先 声 明 了 一 个NOTIFYICONDATA 型 的 变 量nid, 且 已 经 给 它 的 所 有 成 员 赋 予 了 合 适 的 值, 那 么, 下 面 的 两 条 语 句 分 别 可 完 成 添 加 和 删 除 图 标 的 任 务: Shell_NotifyIconA( 0, nid)    ' 添加图标
    Shell_NotifyIconA( 2, nid) ' 删除图标二、 如 何 响 应 鼠 标 按 键
    ---- 按 照 上 面 的 方 法, 我 们 可 以 将 最 小 化 后 的 图 标 放 在 任 务 栏 的 右 边, 那 么 当 我 们 在 该 图 标 上 按 下 鼠 标 按 键 时 会 发 生 什 么 事 情 呢 ? 很 遗 憾, 什 么 也 没 有 发 生, 最 小 化 的 窗 体 不 会 象 我 们 希 望 的 那 样 恢 复 正 常 显 示 状 态。 
    ---- 这 时 怎 么 回 事 呢 ? 很 简 单, 前 面 我 们 只 是 将 图 标 添 加 到 了 任 务 栏 上, 而 并 没 有 对 鼠 标 事 件 做 任 何 的 工 作, 为 了 对 鼠 标 按 键 作 出 响 应, 我 们 还 有 一 些 事 情 要 做。 ---- 前 面 已 经 说 过, 如 果 将 将NOTIFYICONDATA 类 型 变 量 的 成 员uFlags 设 定 为1, 则 当 用 户 在 图 标 上 按 下 鼠 标 按 键 时,Windows 会 将 编 号 为uCallbackMessage 的 消 息 发 送 到 应 用 程 序, 因 此, 为 了 能 响 应 鼠 标 事 件, 我 们 必 须 在 程 序 中 对 该 消 息 进 行 处 理。 ---- 需 要 注 意 的 是, 由 于Windows 自 身 的 消 息 处 理 机 制 的 限 制, 我 们 无 法 直 接 干 预Windows 的 自 身 消 息 处 理 过 程, 所 以 只 有 采 用 一 种 类 似 于 从 前DOS 环 境 下 截 获 中 断 的“ 曲 线 救 国“ 的 方 法 来 处 理 消 息, 过 程 是: ---- 在 窗 体 最 小 化 后, 立 即 读 取 该 窗 体 原 消 息 处 理 过 程 的 地 址 并 记 录 在 一 个 全 局 变 量 中, 方 法 是 调 用Windows API 函 数GetWindowLong, 其 声 明 如 下: ---- Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long 其 中hWnd 为 窗 体 句 柄,nIndex 为 过 程 类 型, 这 里 为-4(Windows 默 认 过 程)。 ---- (2) 编 写 自 己 的 消 息 处 理 过 程, 注 意 参 数 的 数 量 和 类 型 必 须 按 照 下 面 的 格 式( 过 程 名 可 随 意): ---- Sub WndProcForIcon(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) ---- (3) 将 自 己 的 消 息 处 理 过 程 设 置 为 默 认 的 消 息 处 理 程 序, 方 法 是 调 用Windows API 函 数SetWindowLong, 其 声 明 如 下: ---- Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long ---- 其 中hWnd 与nIndex 含 义 同 上,dwNewLong 为 自 定 义 过 程 的 地 址, 可 使 用VB 的 求 地 址 运 算 符AddressOf 得 到, 如AddressOf WndProcForIcon 可 得 到 自 定 义 过 程WndProcForIcon 的 地 址。 ---- (4) 当 鼠 标 事 件 发 生 后, 自 己 的 消 息 处 理 过 程( 现 在 已 成 为 默 认 的 消 息 处 理 过 程) 首 先 进 行 处 理, 一 般 是 根 据 按 键 将 窗 体 恢 复 或 弹 出 一 个PopUp 菜 单 供 用 户 选 择。 ---- (5) 让Windows 去 执 行 原 消 息 处 理 过 程( 该 过 程 的 地 址 由 全 局 变 量 保 存), 方 法 是 调 用Windows API 函 数CallWindowProc, 其 声 明 如 下: ---- 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 ---- 其 中lpPrevWndFunc 为 原 消 息 处 理 程 序 的 地 址, 其 它 参 数 与 自 定 义 消 息 处 理 过 程 中 的 参 数 相 对 应。 ---- 细 心 的 读 者 一 定 会 发 现, 如 果 在 上 述 第3 步 完 成 后, 没 有 进 行 第5 步, 即: 使 用setWindowLong 改 变 了 原 先 消 息 处 理 程 序 的 地 址, 却 没 有 在 程 序 结 束 前 将 地 址 设 定 回 来, 那 程 序 将 不 会 正 常 结 束, 往 往 会 造 成 死 机, 因 此, 程 序 中 一 定 要 小 心 处 理 这 个 问 题。 ---- 另 外, 为 了 正 确 的 处 理 消 息, 还 有 一 个 问 题 需 要 解 决, 就 是 如 何 识 别 消 息 是 否 是 由 图 标 发 出 的 ? 这 一 点 可 以 这 样 解 决: 利 用 一 个 全 局 变 量 记 录 下NOTIFYICONDATA 型 变 量 的 成 员uCallbackMessage( 消 息 号) 的 值, 然 后 在 消 息 处 理 程 序 中 检 查Windows 传 回 的 消 息 号(MsgNo) 是 否 与 其 一 致, 如 果 一 致, 则 说 明 消 息 的 确 是 由 图 标 发 出 的, 应 该 进 行 处 理, 否 则 即 可 忽 略。 如 本 文 后 面 的 程 序 实 例 就 用 全 局 变 量IconMsg 来 实 现 这 一 功 能( 具 体 请 参 照 程 序 代 码)。
      

  3.   

    三、 程 序 实 例
    ---- 下 面, 我 们 通 过 一 个 简 单 的 实 例 来 实 现 上 述 方 法: 
    ---- 1、 窗 体 布 局 ---- 新 建 一 个 工 程IconTest, 新 建 一 个 标 准 窗 体frmIconTest, 在 窗 体 上 放 置 三 个 命 令 按 钮, 名 称(Name) 分 别 为cmdCreateIcon、cmdNormalMin 和cmdExit, 标 题(Caption) 分 别 为“ 最 小 化 到 右 下 角”、“ 普 通 最 小 化” 和“ 退 出”。 ---- 2、 代 码 ---- 添 加 一 个 模 块modIconTest, 在 其 中 编 写 如 下 的 代 码: Option Explicit
    '定义常量
    Public Const GWL_WNDPROC = (-4)
    Public Const WM_LBUTTONDOWN = &H201
    Public Const NIM_ADD = 0
    Public Const NIM_DELETE = 2
    Public Const NIF_MESSAGE = 1
    Public Const NIF_ICON = 2
    Public Const NIF_TIP = 4
    '定义全局变量
    Public IconMsg As Long '消息编号
    Public OldWinProc As Long '原消息处理程序的地址
    '定义自定义数据类型
    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
    'Windows API函数声明
    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 GetWindowLong Lib "user32" 
    Alias "GetWindowLongA" (ByVal hWnd As Long,
    ByVal nIndex 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_NotifyIconA Lib "SHELL32" (ByVal
    dwMessage As Long, lpData As NOTIFYICONDATA) As Integer
    '自定义消息处理程序
    Sub MyProc(ByVal hWnd As Long, ByVal Msg As Long, 
    ByVal wParam As Long, ByVal lParam As Long)
    '根据Msg判断,消息是否是图标发出的, 
    如果是,再进行处理
    If Msg = IconMsg Then
    If lParam = WM_LBUTTONDOWN Then
    frmIconTest.Show '如果在图标上按 
    下了左键则显示窗体
    End If
    End If
    '执行全程变量OldWinProc记录的原
    消息处理程序的地址中的消息处理程序
    CallWindowProc OldWinProc, hWnd, Msg, wParam, lParam
    End Sub
    在frmIconTest的窗体模块中编写如下代码:
    Option Explicit
    Dim HadAdd As Boolean
    Dim nid As NOTIFYICONDATA
    Private Sub cmdEnd_Click()
    If HadAdd Then
    '如果曾向右下角添加过小图标
    '则根据事先记录的OldWinProc
    恢复原来的消息处理程序,并删除图标
    SetWindowLong frmIconTest.hWnd, 
    GWL_WNDPROC, OldWinProc
    Call Shell_NotifyIconA(NIM_DELETE, nid) 
    '删除图标
    End If
    Unload Me '卸载窗体
    End Sub
    Private Sub cmdCreateIcon_Click()
    If Not HadAdd Then
    '如果没有产生过图标,则添加图标到右下角
    With nid
    '以下填写nid变量的所有成员
    .cbSize = Len(nid) '填写自定义数据类型的长度
    .hWnd = frmIconTest.hWnd '填写窗体的句柄
    .uID = 9999 '图标的Id,可随意
    '允许显示图标、提示并产生消息
    .uFlags = NIF_ICON + NIF_TIP + NIF_MESSAGE
    .hIcon = frmIconTest.Icon.Handle '图标句柄
    .szTip = "单击鼠标左键恢复窗体!" '提示信息
    .uCallbackMessage = 2 '图标的消息号
    End With
    Shell_NotifyIconA NIM_ADD, nid '添加图标
    IconMsg = nid.uCallbackMessage 
    '用全局变量记录消息号,
    '读取frmIconTest正常的消息处理程序 
    的地址保存在全程变量OldWinProc中
    OldWinProc = GetWindowLong(frmIconTest.hWnd, 
    GWL_WNDPROC)
    '用自定义过程MyProc的地址
    代替正常消息处理程序的地址
    SetWindowLong frmIconTest.hWnd,
    GWL_WNDPROC, AddressOf MyProc
    frmIconTest.Hide '隐藏窗体
    HadAdd = True '置“已经添加图标”标志
    Else
    frmIconTest.Hide '如果已经有小图标了,
    则直接隐藏窗体
    End If
    End Sub
    Private Sub cmdNormalMin_Click()
    frmIconTest.WindowState = 1 '普通最小化窗体
    End Sub
    Private Sub Form_Load()
    HadAdd = False '将“是否添加了图标的标志”置为False
    '下面为窗体装载图标,读者应当根据自己的VB目录而定
    frmIconTest.Icon= oadPicture("c:\MyIcon\files10.ico")
    End Sub---- 按 下F5, 执 行 本 程 序, 单 击“ 最 小 化 到 右 下 角” 按 钮, 窗 体 将 消 失, 同 时 任 务 栏 的 右 边 出 现 代 表 窗 体 的 图 标( 如 图2), 在 该 图 标 上 单 击 鼠 标 左 键, 窗 体 恢 复 正 常。 再 单 击“ 普 通 最 小 化 图 标” 按 钮, 你 会 看 到 窗 体 虽 然 也 消 失 了, 但 最 小 化 图 标 在 任 务 栏 的 中 间, 即 普 通 位 置( 如 图3)。 ---- 本 程 序 用VB5 编 制, 在Pwin95 下 调 试 正 常。
      

  4.   

    'Download the full source+pictures+... at http://www.allapi.net/php/redirect/redirect.php?action=download&id=38
    Private 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 TypePrivate Const NIM_ADD = &H0
    Private Const NIM_MODIFY = &H1
    Private Const NIM_DELETE = &H2
    Private Const NIF_MESSAGE = &H1
    Private Const NIF_ICON = &H2
    Private Const NIF_TIP = &H4Private Const WM_LBUTTONDBLCLK = &H203
    Private Const WM_LBUTTONDOWN = &H201
    Private Const WM_RBUTTONUP = &H205Private Declare Function Shell_NotifyIcon Lib "shell32" Alias "Shell_NotifyIconA" (ByVal dwMessage As Long, pnid As NOTIFYICONDATA) As Boolean
    Dim TrayI As NOTIFYICONDATA
    Private Sub Form_Load()
        TrayI.cbSize = Len(TrayI)
        'Set the window's handle (this will be used to hook the specified window)
        TrayI.hWnd = pichook.hWnd
        'Application-defined identifier of the taskbar icon
        TrayI.uId = 1&
        'Set the flags
        TrayI.uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
        'Set the callback message
        TrayI.ucallbackMessage = WM_LBUTTONDOWN
        'Set the picture (must be an icon!)
        TrayI.hIcon = imgIcon(2).Picture
        'Set the tooltiptext
        TrayI.szTip = "Recent" & Chr$(0)
        'Create the icon
        Shell_NotifyIcon NIM_ADD, TrayI    Me.Hide
    End Sub
    Private Sub Form_Unload(Cancel As Integer)
        'remove the icon
        TrayI.cbSize = Len(TrayI)
        TrayI.hWnd = pichook.hWnd
        TrayI.uId = 1&
        Shell_NotifyIcon NIM_DELETE, TrayI
        End
    End Sub
    Private Sub mnuPop_Click(Index As Integer)
        Select Case Index
            Case 0
                MsgBox "KPD-Team 1998" + Chr$(13) + "URL: http://www.allapi.net/" + Chr$(13) + "E-Mail: [email protected]", vbInformation + vbOKOnly
            Case 2
                Unload Me
        End Select
    End Sub
    Private Sub pichook_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
        Msg = X / Screen.TwipsPerPixelX
        If Msg = WM_LBUTTONDBLCLK Then
            'Left button double click
            mnuPop_Click 0
        ElseIf Msg = WM_RBUTTONUP Then
            'Right button click
            Me.PopupMenu mnuPopUp
        End If
    End Sub
    Private Sub Timer1_Timer()
        Static Tek As Integer
        'Animate the icon
        Me.Icon = imgIcon(Tek).Picture
        TrayI.hIcon = imgIcon(Tek).Picture
        Tek = Tek + 1
        If Tek = 3 Then Tek = 0
        Shell_NotifyIcon NIM_MODIFY, TrayI
    End Sub