Windows任务栏编程
Windows 95与Windows NT同Windows以前版本在人机界面上一个较为明显的区别在于增加了一条系统任务条,从而极大地方便了用户对系统间各个任务的管理。如果在程序中能够对任务条进行灵活地控制,那一定会使程序增色不少。本文将重点介绍任务条中状态区的编程要领。 任务条主要包括以下几个部分:起始菜单(Start menu),由Start button所弹出的菜单用于取得应用程序群组中的各个应用程序,对系统环境的设置,最近文档的管理等一些基本的系统命令;任务按钮(taskbar buttons),当应用程序创建一非拥有主窗口(unowned primarywi ndow即用WS-EX-AppWindow来填充CreateWindowEx函数的dwExStyle字段)时便会产生一任务按钮,用它可对各个窗口进行切换;快捷菜单( shortcut menu),用鼠标右键单击任务条即会产生一快捷菜单,可层叠,平铺各个窗口及设置任务条的属性;状态区(status area),当在任务条的属性页中选择显示时钟项就会看到状态区区域,在Windows 95 Plus!的系统管理、用M odem连Internet和当前的打印队列,都会发现在状态区中有非常形象的小图标指示当前程序所处的状态,用户可以选用如下方式与状态区的小图标进行交互,移动鼠标至图标上将会显示一信息泡(ToolTip),单击鼠标右键产生一快捷菜单,双击鼠标左键将执行快捷菜单中缺省命令。以下将详细介绍在状态区加入及删除图标的方法及状态区鼠标消息传递的机制。 首先介绍只有Windows 95与Windows NT才支持的在shellapi.h下的API Shell-NotifyI con。 WINSHELLAPI BOOL WINAPI Shell-Notifylcon( DWORD dwMessage,∥message identifier PnotifyIcondata pnid∥pointer to structure ); dwMessage可为NIM-Add,NIM-Delete,NIM-Modify分别指定在状态区是加或删或修改图标。pnid为指向NotifyConData结构的指针,其内容取决于dwMessage的设置。函数执行若成功则返回true,否则返回false.接下来介绍NotifyConData结构。 typedef struct-NotifyIconData {∥ nid DWORD cbSize; HWND hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; HICON hIcon; char szTip[64]; } NotifyIconData,*PNotifyIconData; cbSize为NotifyIconData结构的大小;hWnd为接收图标消息所在窗口的句柄;uID为同组图标的统一标识符;uFlags分别NIF-Icon、NIF-Message、NIF-Tip为指明其下三项是否为有效数据;uCallbackMessage为程序所定义的消息标识符,系统会将在图标所处的矩形区域的鼠标消息传递给hWnd所在窗口的uCallbackMessage消息;hIcon为图标句柄;szTip为信息泡的字符数组。 笔者在VC4.2利用MFC4.2及这个函数编写了一个实际的演示例子, 界面如图1。图1 功能为:当点中Enable或Disable的RadioBox时,Hide Button便使能,若按下则隐藏窗口口, 此时在状态区中便可看到相应的图标如图2。 图2 若鼠标左键按下图标,则更替交换DisableIcon与EnableIcon图标并置位各自的RadioBu tton以及显示各自EditBox中的信息泡字符串;若鼠标右键按下图标,则显示窗口,并置为最前。 以下为增、删、改图标函数具体实现的源码。 BOOL CTrayiconDlg::StatusArealcon(DWORD dwMessage,UINT u lD,HICON hlcon,PSTR pszTip) { BOOL res; NOTIFYICONDATA tnd; tnd.cbSize=sizeof(NOTIFYICONDATA); tnd.hWnd=this->m-hWnd; tnd.ulD=ulD; tnd.uFlags=NIF-MESSAGE|NIF-ICON|NIF-TIP; tnd.uCallbackMessage=WM-USER-NOTIFYICON; tnd.hIcon=hIcon; if(pszTip) lstrcpyn(tnd.szTip,pszTip,sizeof(tnd.szTip)); else tnd.szTip[0]=`\0'; res=Shell-Notifylcon(dwMessage,&tnd); return res; } 以下为接收图标消息具体实现的源码。 LRESULT CTrayiconDlg::OnMyNotifyicon(WPARAM wParam,LPARAM lParam) { UINT uSelect; switch(lParam) { case WM-LBUTTONDOWN: switch(wParam) {case IDICONTEAM: uSelect=lsDlgButtonChecked(IDC-ENABLERADIO)? IDC-DISABLERADIO:IDC-ENABLERADIO; CheckRadioButton(IDC-ENABLERAIO,IDC-DISABLERADIO,uSelect); GetDlgltemText(uSelect,m-Tip,64); if(uSelect==IDC-ENABLERADIO) { GetDlgltemText(IDC-EDITENABLE,m-Tip,64); StatusArealcon(NIM-MODIFY,IDHIDE,m-hlconEn,m-Tip); } else { GetDlgltemText(IDC-EDITDISABLE,m-Tip,64); StatusArealcon(NIM-MODIFY,IDHIDE,m-hlconDis,m-Tip); } break; default: break; } break; case WM-RBUTTONDOWN: ShowWindow(SW-SHOW); SetForegroundWindow(); break; default: break; } return 0; } 由于使用的是MFC,所以还需要做一些辅助性工作。定义用户自定义消息,并将该消息的各项声明加入到相应声明中去;并需要在窗口关闭时删除图标。这些内容相对简单,这里不再赘述。现在读者一定可以动手编写一个小的应用了,相信在看到自己的图标在系统的任务条的状态区中来回切换时,一定会因为深入切入系统而兴奋不已,体会一下这种感觉吧!