windows工作列程式開發

來源:互聯網
上載者:User

一. 引言


  工作列是中一個眾所周知的概念,它指的是Windows案頭上顯示已運行程式的
一塊條狀地區。

電腦知識網
it.qc99.com


般來說,工作列是由三個部分組成的:最左邊是[開始] 按鈕,中間是已運行程式的顯示地區(Windows98還有一個快捷工具列),最右邊是工作列提示區
域。所謂的工作列編程主要指對工作列提示區進行編程。Windows系統允許使用者在工作列提示區裡放置自己的應用程式圖示並定製自己需要的操作。

 
 在工作列提示區裡放置應用程式圖示一方面方便了使用者與應用程式的交流,另一方面也可使應用程式以更形象的形式給使用者以提示。一般地,將應用程式圖示放置
在工作列提示區中意味著該應用程式是一個背景程式。例如在Windows中進行後台列印時,一個印表機表徵圖就會顯示在工作列提示區中提示使用者印表機進程正
在後台運行。目前有許多軟體都使用了工作列編程技術,如Netants、Go!zilla、金山詞霸等,這一方面是由於這些軟體具有某些“後台”性質,另
一方面也是因為將應用程式圖示放在工作列提示區中使得人機互動更為簡便。

  目前有許多程式設計語言都可以針對工作列進行編程,如V、、VB
等,也已有一些文章對其進行了介紹。但筆者發現很少有文章從原理到程式實現系統地對工作列編程進行論述,大多數的資料只是給出幾個API函式宣告和一段代
碼。但工作列編程不僅涉及到API,還涉及回呼函數等一些更為複雜的問題,因此有必要深入系統地對該問題進行探討。

  二.
工作列編程的實現技術

  Windows工作列編程的基本思路是:(1)通過API函數調用在應用程式啟動時將應用
程式表徵圖放入工作列提示區,在程式運行時修改表徵圖特性,並在應用程式關閉時將表徵圖從工作列中刪去;(2)通過使用回呼函數控制應用程式。本節主要探討通過
API來控製圖標的一些問題。下一節將主要探討回呼函數。

  1. Shell_NotifyIcon函數

  其聲明
為: Private Declare Function Shell_NotifyIconLib "shell32" Alias
"Shell_NotifyIconA" (ByVal dwMessage As Long,pnid As NOTIFYICONDATA) As
Long

  該函數給系統發送添加、修改、刪除工作列提示區表徵圖的訊息,系統根據發送的訊息進行相應的處理。可以說該函數是工作列提示區
編程的核心,掌握它就可以輕鬆地編寫出符合要求的程式來。該函數中的參數意義如下:

  (1) 參數dwMessage (ByVal
dwMessage As Long)

  該參數通知系統進行何種操作,取值如下:
NIM_ADD
添加表徵圖到工作列提示

NIM_DELETE
刪除表徵圖
NIM_MODIFY
發送表徵圖特性已改變的訊息

  (2)
參數pnid (pnid As NOTIFYICONDATA)

  表徵圖特性資料,NOTIFYICONDATA定義如下:
Private
Type NOTIFYICONDATA
CbSize As Long '該的大小
hWnd As Long
'處理表徵圖通知訊息的視窗控制代碼
uID As Long '應用程式自訂的表徵圖ID
uFlags As Long
'用來設定uCallbackMessage、hIcon、szTip等三個欄目是否有效,一般取組合NIF_ICON Or NIF_TIP Or
NIF_MESSAGE,表示全部有效
uCallbackMessage As Long
'訊息編號,將來當使用者在表徵圖上按下滑鼠時就會以訊息通知訊息處理回呼函數
hIcon As Long '表徵圖控制代碼
szTip As
String*64 '提示訊息
End Type

  2.加入表徵圖

  在啟動表單的Form_Load()事件
中加入以下代碼就可以在程式運行時在工作列提示區中添加一個表徵圖:

Dim nid As NOTIFYICONDATA
nid.cbSize
= Len(nid)
nid.hwnd = Me.hwnd
nid.uID = 9998
nid.uFlags =
NIF_ICON + NIF_TIP + NIF_MESSAGE
nid.hIcon = Me.Icon
nid.uCallbackMessage
= WM_USER+100
nid.szTip ="歡迎使用工作列"
Shell_NotifyIcon NIM_ADD, nid '

  3.刪除表徵圖

  在Form_Unload()事件中添加以下代碼在程式關閉時刪除表徵圖,要注意的是這裡所使
用到的uID和hWnd必須和當初加入表徵圖時所使用的uID和hWnd完全一致。

Dim nid As NOTIFYICONDATA
nid.cbSize
= Len(nid)
nid.hwnd = Me.hwnd
nid.uID = 9998
Shell_NotifyIcon
NIM_DELETE, nid

  4.修改表徵圖

  下面一段代碼實現表徵圖的修改。這裡的uId和hWnd也必須和當初
加入表徵圖時所使用的
uId和hWnd完全一致。同時還必須正確設定uFlags和hIcon。uFlags必須設定為NIF_ICON,表示修改對表徵圖有效;hIcon應設
為新表徵圖。

Dim nid As NOTIFYICONDATA
nid.cbSize = Len(nid)
nid.hWnd
= Me.hWnd
nid.uID = 9999
nid.uFlags = NIF_ICON
nid.hIcon =
Image1.Picture
Shell_NotifyIcon NIM_MODIFY, nid

  修改提示訊息和訊息編號的
方法與此類似。不同點是當修改提示訊息時須將uFlags設為NIF_TIP,修改訊息編號時須將uFlags設為NIF_MESSAGE。

 
 三. 回呼函數


  在前面已經講到,當使用者在表徵圖上按下滑鼠時,系統將接收並傳遞訊息給視窗訊息處
理回呼函數進行具體的處理。使用者可以在回呼函數中對不同的訊息進行不同的程式處理來定製自己的應用程式的功能(例如滑鼠左擊時彈出一個菜單,滑鼠右擊時彈
出另一個菜單,滑鼠雙擊時顯示主視窗等等)。在工作列提示區中加入表徵圖時設定的訊息編號uMessage就是用來告訴回呼函數此訊息來自表徵圖對應的程式,
回呼函數即可據此進行處理。回呼函數是個比較複雜的問題,下面從VB程式的運行機制入手來具體闡述工作列編程中回呼函數的實現方法。

  
1. VB應用程式的運行機制

  VB應用程式的運行是基於Windows的訊息傳遞機制的。Windows的工作方式是一種多任務多線
程的工作方式,VB程式運行時是受Windows控制的。具體講,一個VB程式運行時Windows的進程管理模組就會給它建立一個進程。進程與
Windows之間的通訊是通過訊息傳遞來實現的:進程發送一個訊息給Windows並等待,Windows處理完此訊息後將結果會傳給進程。由於
Windows支援多線程,因此一個進程可以在內部建立多個線程,這些線程共用此進程的地址空間、全域變數、檔案以及各種訊號。除了共用地址空間外,各個
線程是獨立的,每個線程有自己的程式計數器、堆棧、寄存器及狀態(等待、就緒、運行)。VB程式在運行時,通過對其所含的每個控制項都建立一個線程來並行地
處理控制項的事件。一個控制項在進程內對應一個線程。這些線程也同樣通過訊息與Windows進行通訊。Windows為運行於其上的應用程式提供了確省的消
息處理常式。例如在一個VB程式運行時,右擊一個文字框就會彈出一個包含“剪下”、“複製”、“粘貼”等功能的捷徑功能表,這就是由Windows的確省消
息處理常式來完成的。Windows系統允許使用者截獲應用程式視窗的訊息並用自訂的過程來加以處理。這個自訂的過程稱為“回調”函數,使用者可在回調函
數中對感興趣的訊息進行適當的處理,並將其它的訊息交給系統原來的訊息處理過程處理。這種“替代”似乎很困難,但實際上卻是完全可以實現的。

 
 2. 用回呼函數來處理工作列提示區的訊息

  回呼函數(Callback
Function)是應用程式提供給Windows系統DLL或其它DLL調用的函數,一般用於截獲訊息、擷取系統資訊或處理非同步事件。應用程式把回調函
數的地址指標告訴DLL,而DLL在適當的時候會調用該函數。回呼函數必須遵守事先規定好的參數格式和傳遞方式,否則DLL一調用它就會引起程式或系統的
崩潰。

  通常情況下,回呼函數採用Windows
API的調用方式,即_stdcall,當然,DLL編製者可以自已定義調用方式,但客戶程式也必須遵守相同的規定。在_stdcall方式下,函數的參
數按從右至左的順序壓入堆棧,除了明確指明是指標或引用外,參數都按值傳遞,函數返回之前自己負責把參數從堆棧中彈出。

  將應用程式圖
標放入工作列提示區後,如果使用者要想開啟該應用程式視窗,必須到工作列提示區中去點擊表徵圖。但這並不意味著使用者點擊後,視窗就會自動顯示出來。每當使用者點
擊表徵圖,系統會以訊息方式通知視窗的訊息處理回呼函數,所以只要在應用程式視窗的回呼函數中進行適當的編程就可以實現。

  視窗訊息回調
函數的格式如下所示:
Function WndProc(ByVal hwnd As Long, ByVal Msg As Long,
ByVal wParam As Long, ByVal lParam As Long) As Long

  因為回呼函數是自訂的
函數,因此函數名和參數名都可以自訂。各參數的含義如下表所示:
hWnd
視窗控制代碼
Msg
等於當初調用
Shell_NotifyIcon時所設定的uCallbackMessage的值
wParam
等於當初調用
Shell_NotifyIcon時所設定的uID的值
lParam
等於滑鼠訊息,例如WM_LBUTTONDOWN(按下滑鼠左鍵)等

 
 在VB使用回呼函數存在不少限制:

  1、回呼函數必須放到標準的模組(Module)中,而不能放在類別模組或表單代碼中;
 
 2、AddressOf運算子只能用於自訂的過程、函數或屬性,不能將其用於Declare語句聲明的外部函數,也不能用於類型庫中的函數;
 
 3、寫在AddressOf後面的過程、函數和屬性必須與有關的聲明和過程在同一個工程中;
  4、由於回呼函數要與系統直接互動,所以調試十
分困難,如果回呼函數中有錯誤,可能會引起非法操作,致使VB運行環境崩潰。

  在VB中用回呼函數處理工作列提示區訊息的具體步驟如
下:

  (1)在啟動表單的Form_Load()事件中加入以下代碼。

prevWndProc =
GetWindowLong(Me.hwnd, GWL_WNDPROC) '擷取系統確省的視窗訊息處理函數控制代碼
SetWindowLong
Me.hwnd, GWL_WNDPROC, AddressOf WndProc '指定WndProc為新的訊息處理函數
'加入表徵圖
Dim
nid As NOTIFYICONDATA
nid.cbSize = Len(nid)
nid.hwnd = Me.hwnd
nid.uID
= 9998
nid.uFlags = NIF_ICON + NIF_TIP + NIF_MESSAGE
nid.hIcon =
Me.Icon
nid.uCallbackMessage = WM_USER + 100 '定義訊息編號
Shell_NotifyIcon
NIM_ADD, nid '

  (2)在模組中加入回呼函數WndProc的代碼

Function
WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long,
ByVal lParam As Long) As Long
If Msg = WM_USER + 100 Then
''該訊息等於調用Shell_NotifyIcon時定義的uCallbackMessage
If lParam =
WM_LBUTTONDOWN Or lParam = WM_RBUTTONDOWN Then
'當按下滑鼠左鍵或右鍵時快顯功能表
frmCaution.PopupMenu
frmCaution.mnuaa
End If
End If
'其它的訊息交給系統處理,prevWndProc為原來的視窗消
息處理函數的控制代碼
WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam,
lParam)
End Function

  執行以上的代碼時,API函數GetWindowLong()、
SetWindowLong()和CallWindowProc()的聲明需要先加入到模組中,這些聲明可通過VB所帶的“API文本瀏覽器”獲得。

 
 四. 執行個體分析:一個定時音樂提醒程式


  對於一個從事電腦工作的人來說,長時間坐在電腦前面
工作是常有的事。持續的螢幕注視往往使得眼睛十分疲勞。最好是能每隔一段時間休息一下。但電腦工作尤其是編程往往會使人全神貫注,忘記了時間。我們可以
設計一個定時音樂提醒程式,讓它每隔一段時間就自動提醒自己休息一會兒。

  下面就結合前述的工作列編程思想給出具體的程式實現。該程式
具有每隔一段時間就播放一段音樂提醒和到某個特定時刻播放音樂提醒的功能,並可以由使用者自訂提醒時間、提醒內容以及音效。

  1、建立
一個工程,並加入五個表單,分別命名為frmCaution、frmTipMess、frmSound、frmChangTime和frmAbout
。其中frmcaution為顯示提醒訊息的啟動表單,frmtipmess為使用者自訂提醒內容的表單,frmsound為使用者自訂提醒聲音的窗
體,frmchangtime為使用者自訂提醒時間方式的表單,frmabout為“關於”資訊顯示表單。
 
  2、在
frmcaution上加入一個菜單“mnuaa”,在“mnuaa”下加入菜單“設定提醒時間……”、“設定提醒訊息……”、“音效……”、“關
於……”、“退出”。菜單“mnuaa”就作為當單擊表徵圖時的快顯功能表。在frmcaution中加入一個panel,命名為“pnlmessage”,
用於顯示訊息。在frmcaution中加入一個多媒體控制項,命名為“mm”,用於播放音樂。在frmcaution中加入一個時間控制項“Time1”。

 
 3、在工程中加入一個標準模組mdlCommon,並在其中放置如下代碼:

'API函式宣告
Declare Function
Shell_NotifyIcon Lib "shell32.dll" Alias "Shell_NotifyIconA" (ByVal
dwMessage As Long, lpData As NOTIFYICONDATA) 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
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
Public 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

Public prevWndProc As Long
'原有的視窗訊息處理函數
Public Message As String '訊息內容
Public TipInterval As
Integer '提示時間間隔
Public TipTime As String '提示時間
Public Time As
Integer '累計時間

Function WndProc(ByVal hwnd As Long, ByVal Msg As
Long, ByVal wParam As Long, ByVal lParam As Long) As Long
If Msg =
WM_USER + 100 Then
If lParam = WM_LBUTTONDOWN Or lParam =
WM_RBUTTONDOWN Then
'當按下滑鼠左鍵或右鍵時快顯功能表
frmCaution.PopupMenu
frmCaution.mnuaa
End If
End If
'其它的訊息交給系統處理,prevWndProc為原來的視窗訊息
處理函數的控制代碼
WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam,
lParam)
End Function
以上程式限於篇幅略去了資料結構和常量的定義。該定義可從“API文本瀏覽器”中獲得。

 
 4、編寫frmcaution的Form_Load()過程。

Private Sub Form_Load()
Load
frmSound
prevWndProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
'擷取系統確省的視窗訊息處理函數控制代碼
SetWindowLong Me.hwnd, GWL_WNDPROC, AddressOf
WndProc '指定WndProc為新的訊息處理函數
'加入表徵圖
Dim nid As NOTIFYICONDATA
nid.cbSize
= Len(nid)
nid.hwnd = Me.hwnd
nid.uID = 9998
nid.uFlags =
NIF_ICON + NIF_TIP + NIF_MESSAGE
nid.hIcon = Me.Icon
nid.uCallbackMessage
= WM_USER + 100 '定義訊息編號
Shell_NotifyIcon NIM_ADD, nid
'設定顯示介面
pnlMessage.Left
= (Me.ScaleWidth - pnlMessage.Width) / 2
pnlMessage.Top =
(Me.ScaleHeight - pnlMessage.Height) / 2
TipInterval = 30
'提醒時間間隔預設為30分鐘
TipTime = "" '提醒時間預設為空白
Time = 0
Message =
"親愛的主人,建議您先休息5分鐘!"
mm.Filename = frmSound!filSound.List(0)
End Sub

 
 5、編寫frmcaution的Form_Unload()過程。

Private Sub Form_Unload(Cancel
As Integer)
Dim nid As NOTIFYICONDATA
'恢複原來的視窗訊息處理函數
SetWindowLong
Me.hwnd, GWL_WNDPROC, prevWndProc
'刪除表徵圖
nid.cbSize = Len(nid)
nid.hwnd
= Me.hwnd
nid.uID = uID
Shell_NotifyIcon NIM_DELETE, nid
mm.Command
= "close"
End Sub
6、編寫Timer1_Timer()過程。
Private Sub
Timer1_Timer()
If TipInterval <> 0 Then '若設定了提醒間隔
Time =
Time + 1 '累計時間加1秒
If Time >= TipInterval * 60 Then '提醒時間間隔已到
pnlMessage.Caption
= Message
Timer1.Enabled = False
mm.Filename = mm.Filename
mm.Command
= "open"
mm.Command = "play"
Time = 0
frmCaution.Show
'視窗總顯
示在最前
SetWindowPos Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or
SWP_NOMOVE
End If
End If
If TipTime <> "" Then '若設定了定時
Dim
NowTime As Date
Dim DestTime As Date
NowTime = Format(Now(),
"hh:nn:ss")
DestTime = Format(TipTime, "hh:nn:ss")
If NowTime =
DestTime Then '定時時間已到
pnlMessage.Caption = Message
Timer1.Enabled =
False
mm.Filename = mm.Filename
mm.Command = "open"
mm.Command
= "play"
frmCaution.Show
SetWindowPos Me.hwnd, HWND_TOPMOST, 0,
0, 0, 0, SWP_NOSIZE Or SWP_NOMOVE
End If
End If
End Sub

 
 以上就給出了定時音樂提醒程式的大致過程。該程式運行時,確省情況下每隔30分鐘就會跳出一個提醒視窗,同時播放一段音樂。當使用者單擊工作列提示區中的
表徵圖就會彈出一個菜單,然後使用者可以選擇需要執行的功能。該程式的一些其它功能如“設定提醒時間形式”、“設定音效”等因與本文主題沒多少聯絡在此不再細
述。
定時音樂提醒程式在 6.0中文企業版、Windows98環境下調試通過。讀者若需要完整的來源程式請E-mail 與筆者聯絡。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.