程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> Visual Basic語言 >> VB綜合教程 >> 把最小化圖標放到任務欄右下角

把最小化圖標放到任務欄右下角

編輯:VB綜合教程
----目前有不少Win95應用程序在最小化後,代表該程序的小圖標就會隱藏在屏幕的右下角(即任務欄的右邊),如“金山詞霸”、“東方快車”等,而我們用VisualBasic編制的程序在最小化後,圖標卻總是出現在任務欄的中央,並且占據較大的空間。如何讓我們自己的程序也能將最小化圖標放在任務欄的右邊呢?我們可以通過WindowsAPI函數調用來實現該功能。
  
  一、如何添加和隱藏圖標
  ----在Windows的動態連接庫Shell32.dll中有一個名為Shell_NotifyIconA的WindowsAPI函數,其功能是對任務欄的右下角圖標進行操作,包括添加、刪除和修改。Shell_NotifyIconA函數的VB聲明格式如下:
  ----DeclareFunctionShell_NotifyIconALib"SHELL32"(ByValdwMessageAsLong,lpDataAsNOTIFYICONDATA)AsIntegerShell_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環境下截獲中斷的“曲線救國“的方法來處理消息,過程是:
  
  ----在窗體最小化後,立即讀取該窗體原消息處理過程的地址並記錄在一個全局變量中,方法是調用WindowsAPI函數GetWindowLong,其聲明如下:
  
  ----DeclareFunctionGetWindowLongLib"user32"Alias"GetWindowLongA"(ByValhWndAsLong,ByValnIndexAsLong)AsLong其中hWnd為窗體句柄,nIndex為過程類型,這裡為-4(Windows默認過程)。
  
  ----(2)編寫自己的消息處理過程,注意參數的數量和類型必須按照下面的格式(過程名可隨意):
  
  ----SubWndProcForIcon(ByValhWndAsLong,ByValMsgAsLong,ByValwParamAsLong,ByVallParamAsLong)
  
  ----(3)將自己的消息處理過程設置為默認的消息處理程序,方法是調用WindowsAPI函數SetWindowLong,其聲明如下:
  
  ----DeclareFunctionSetWindowLongLib"user32"Alias"SetWindowLongA"(ByValhWndAsLong,ByValnIndexAsLong,ByValdwNewLongAsLong)AsLong
  
  ----其中hWnd與nIndex含義同上,dwNewLong為自定義過程的地址,可使用VB的求地址運算符AddressOf得到,如AddressOfWndProcForIcon可得到自定義過程WndProcForIcon的地址。
  
  ----(4)當鼠標事件發生後,自己的消息處理過程(現在已成為默認的消息處理過程)首先進行處理,一般是根據按鍵將窗體恢復或彈出一個PopUp菜單供用戶選擇。
  
  ----(5)讓Windows去執行原消息處理過程(該過程的地址由全局變量保存),方法是調用WindowsAPI函數CallWindowProc,其聲明如下:
  
  ----DeclareFunctionCallWindowProcLib"user32"Alias"CallWindowProcA"(ByVallpPrevWndFuncAsLong,ByValhWndAsLong,ByValMsgAsLong,ByValwParamAsLong,ByVallParamAsLong)AsLong
  
  ----其中lpPrevWndFunc為原消息處理程序的地址,其它參數與自定義消息處理過程中的參數相對應。
  
  ----細心的讀者一定會發現,如果在上述第3步完成後,沒有進行第5步,即:使用setWindowLong改變了原先消息處理程序的地址,卻沒有在程序結束前將地址設定回來,那程序將不會正常結束,往往會造成死機,因此,程序中一定要小心處理這個問題。
  
  ----另外,為了正確的處理消息,還有一個問題需要解決,就是如何識別消息是否是由圖標發出的?這一點可以這樣解決:利用一個全局變量記錄下NOTIFYICONDATA型變量的成員uCallbackMessage(消息號)的值,然後在消息處理程序中檢查Windows傳回的消息號(MsgNo)是否與其一致,如果一致,則說明消息的確是由圖標發出的,應該進行處理,否則即可忽略。如本文後面的程序實例就用全局變量IconMsg來實現這一功能(具體請參照程序代碼)。
  
  三、程序實例
  ----下面,我們通過一個簡單的實例來實現上述方法:
  ----1、窗體布局
  
  ----新建一個工程IconTest,新建一個標准窗體frmIconTest,在窗體上放置三個命令按鈕,名稱(Name)分別為cmdCreateIcon、cmdNormalMin和cmdExit,標題(Caption)分別為“最小化到右下角”、“普通最小化”和“退出”。
  
  ----2、代碼
  
  ----添加一個模塊modIconTest,在其中編寫如下的代碼:
  
  OptionExplicit
  '定義常量
  PublicConstGWL_WNDPROC=(-4)
  PublicConstWM_LBUTTONDOWN=&H201
  PublicConstNIM_ADD=0
  PublicConstNIM_DELETE=2
  PublicConstNIF_MESSAGE=1
  PublicConstNIF_ICON=2
  PublicConstNIF_TIP=4
  '定義全局變量
  PublicIconMsgAsLong'消息編號
  PublicOldWinProcAsLong'原消息處理程序的地址
  '定義自定義數據類型
  PublicTypeNOTIFYICONDATA
  cbSizeAsLong
  hWndAsLong
  uIDAsLong
  uFlagsAsLong
  uCallbackMessageAsLong
  hIconAsLong
  szTipAsString*64
  EndType
  'WindowsAPI函數聲明
  DeclareFunctionCallWindowProcLib"user32"Alias
  "CallWindowProcA"(ByVallpPrevWndFuncAsLong,
  ByValhWndAsLong,ByValMsgAsLong,ByVal
  wParamAsLong,ByVallParamAsLong)AsLong
  DeclareFunctionGetWindowLongLib"user32"
  Alias"GetWindowLongA"(ByValhWndAsLong,
  ByValnIndexAsLong)AsLong
  DeclareFunctionSetWindowLongLib"user32"Alias
  "SetWindowLongA"(ByValhWndAsLong,ByValnIndex
  AsLong,ByValdwNewLongAsLong)AsLong
  DeclareFunctionShell_NotifyIconALib"SHELL32"(ByVal
  dwMessageAsLong,lpDataAsNOTIFYICONDATA)AsInteger
  '自定義消息處理程序
  SubMyProc(ByValhWndAsLong,ByValMsgAsLong,
  ByValwParamAsLong,ByVallParamAsLong)
  '根據Msg判斷,消息是否是圖標發出的,
  如果是,再進行處理
  IfMsg=IconMsgThen
  IflParam=WM_LBUTTONDOWNThen
  frmIconTest.Show'如果在圖標上按
  下了左鍵則顯示窗體
  EndIf
  EndIf
  '執行全程變量OldWinProc記錄的原
  消息處理程序的地址中的消息處理程序
  CallWindowProcOldWinProc,hWnd,Msg,wParam,lParam
  EndSub
  在frmIconTest的窗體模塊中編寫如下代碼:
  OptionExplicit
  DimHadAddAsBoolean
  DimnidAsNOTIFYICONDATA
  PrivateSubcmdEnd_Click()
  IfHadAddThen
  '如果曾向右下角添加過小圖標
  '則根據事先記錄的OldWinProc
  恢復原來的消息處理程序,並刪除圖標
  SetWindowLongfrmIconTest.hWnd,
  GWL_WNDPROC,OldWinProc
  CallShell_NotifyIconA(NIM_DELETE,nid)
  '刪除圖標
  EndIf
  UnloadMe'卸載窗體
  EndSub
  PrivateSubcmdCreateIcon_Click()
  IfNotHadAddThen
  '如果沒有產生過圖標,則添加圖標到右下角
  Withnid
  '以下填寫nid變量的所有成員
  .cbSize=Len(nid)'填寫自定義數據類型的長度
  .hWnd=frmIconTest.hWnd'填寫窗體的句柄
  .uID=9999'圖標的Id,可隨意
  '允許顯示圖標、提示並產生消息
  .uFlags=NIF_ICON NIF_TIP NIF_MESSAGE
  .hIcon=frmIconTest.Icon.Handle'圖標句柄
  .szTip="單擊鼠標左鍵恢復窗體!"'提示信息
  .uCallbackMessage=2'圖標的消息號
  EndWith
  Shell_NotifyIconANIM_ADD,nid'添加圖標
  IconMsg=nid.uCallbackMessage
  '用全局變量記錄消息號,
  '讀取frmIconTest正常的消息處理程序
  的地址保存在全程變量OldWinProc中
  OldWinProc=GetWindowLong(frmIconTest.hWnd,
  GWL_WNDPROC)
  '用自定義過程MyProc的地址
  代替正常消息處理程序的地址
  SetWindowLongfrmIconTest.hWnd,
  GWL_WNDPROC,AddressOfMyProc
  frmIconTest.Hide'隱藏窗體
  HadAdd=True'置“已經添加圖標”標志
  Else
  frmIconTest.Hide'如果已經有小圖標了,
  則直接隱藏窗體
  EndIf
  EndSub
  PrivateSubcmdNormalMin_Click()
  frmIconTest.WindowState=1'普通最小化窗體
  EndSub
  PrivateSubForm_Load()
  HadAdd=False'將“是否添加了圖標的標志”置為False
  '下面為窗體裝載圖標,讀者應當根據自己的VB目錄而定
  frmIconTest.Icon=oadPicture("c:MyIconfiles10.ico")
  EndSub
  
  ----按下F5,執行本程序,單擊“最小化到右下角”按鈕,窗體將消失,同時任務欄的右邊出現代表窗體的圖標(如圖2),在該圖標上單擊鼠標左鍵,窗體恢復正常。再單擊“普通最小化圖標”按鈕,你會看到窗體雖然也消失了,但最小化圖標在任務欄的中間,即普通位置(如圖3)。
  
  ----本程序用VB5編制,在Pwin95下調試正常。->

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved