许多国产软件共存的bug!
为了说明这个问题,我测试了下面的软件,我的机器是p3-450,192mb,win2000:
天网防火墙2.4.8,
腾讯QQ简体标准版2000C Build 0305b
简体测试版QQ2000C Build 0510
金山公司的金山词霸2002,
foxmail 4.1
当上述程序运行后,它们会在屏幕的右下脚的托盘中增加一个小图标,当我们打开进程管理器时,把系统的explore.exe结束,这时windows下的任务栏和开始菜单就消失了,这是我们再能过进程管理器运行ie(我的是在D:\WINNT\explorer.exe),这时windows下的任务栏和开始菜单就又出现了,但是我们注意到原来的一些程序在屏幕的右下脚的托盘中增加一个小图标不见了,但是该程序的进程仍在进程管理器中可见,这是问题就出现了,我们的程序就无法在用户的控制下运行了。经测试上述软件除foxmail 4.1存活下回去,其它无一幸免。同时我还测试了一下国外的一软件,如诺顿,winmap等,做同样的测试,它们的程序图标在ie恢复后仍可出现在任务栏中。而且存在bug的程序远不止这些程序,只要是在屏幕的右下脚的托盘中增加一个小图标的程序80%都存在这个问题。我写这篇文章的目的就是要告诉大家,这个bug很容易修复的,以一个基于对话框的vc++6.0程序为例,
首行应在对话框类中加入如下变量。
NOTIFYICONDATA m_tnid;
再定义一个全局变量
#define MYWM_NOTIFYICON (WM_USER+100)
我们知道,写一个托盘程序就要在OnInitDialog()中加入如下代码就可以了
m_tnid.cbSize=sizeof(NOTIFYICONDATA);
m_tnid.hWnd=AfxGetMainWnd()->m_hWnd;
m_tnid.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
m_tnid.uCallbackMessage=MYWM_NOTIFYICON;
strcpy(m_tnid.szTip,"Only 1.99 $");
m_tnid.uID=IDR_MAINFRAME;
HICON hIcon;
hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_tnid.hIcon=hIcon;
::Shell_NotifyIcon(NIM_ADD,&m_tnid);
if(hIcon)::DestroyIcon(hIcon);
这时运行程序,就会在系统托盘中加入一个我们的图标, 但是我们退出程序时那个右下
脚的图标并不会消失,只有把鼠标移到图标那里图标才会消失。我们可以重载程序的
关闭窗口函数,在OnCancel() 函数中加入
NOTIFYICONDATA tnid;
tnid.cbSize=sizeof(NOTIFYICONDATA);
tnid.hWnd=AfxGetMainWnd()->m_hWnd;
tnid.uID=IDR_MAINFRAME;//保证删除的是我们的图标
Shell_NotifyIcon(NIM_DELETE,&tnid);
这时我们退出程序时,屏幕的右下脚的托盘中增加一个小图标也会随之消失。也许许多人包括我在内,都会觉得我样的程序就很完美了,但是当有时ie执行了非法操作被关闭时,我们重新恢复ie时刚才写过的程序的光标在任务栏中不见了。也许你会说我们的程序在任务栏中还有最小化的窗口,的确我们写是程序是这样的,但是我们测试的程序在最小化以后在任务栏中是没有窗口的如果是这样,当它们的小图标在屏幕的右下脚的托盘中消失后,一般情况下你是无法让它们再出来了。当然你是高手你可以自己写个程序,找到那个消失光标的程序的句柄,用一个showwindow让它出来,但是通常你不得不再用进程管理器重新结束那此程序的进程。这就是上述国产软件的通病。也许这样并不会造成什么损失,不过有一次我用sterm 1.0 bet时挂在上面2天,结果因为ie掉死了所以2天的48小时的时间就没有加到我的经验值里。不过现在的sterm 就没有这个bug了。那么我们该怎么解决这个问题呢。其实很简单。
在csdn的讨论中,经过 jiangsheng(蒋晟卧病中)的帮助,我得出结论
我们只要在全局const UINT WM_TASKBARCREATED =
::RegisterWindowMessage(_T("TaskbarCreated"));//这个消息是系统开始菜单,任务栏创建时发出的
再加上消息映射表
ON_REGISTERED_MESSAGE(WM_TASKBARCREATED,
OnTaskBarCreated)
OnTaskBarCreated()函数如下:
afx_msg void OnTaskBarCreated();
void CTianWangDlg::OnTaskBarCreated()
{
m_tnid.cbSize=sizeof(NOTIFYICONDATA);
m_tnid.hWnd=AfxGetMainWnd()->m_hWnd;
m_tnid.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
m_tnid.uCallbackMessage=MYWM_NOTIFYICON;
strcpy(m_tnid.szTip,"Only 1.99 $");
m_tnid.uID=IDR_MAINFRAME;
HICON hIcon;
hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_tnid.hIcon=hIcon;
::Shell_NotifyIcon(NIM_ADD,&m_tnid);
}
这时现运行我们的程序,重复开始的过程,当ie恢复时我们的图标又会在系统托盘中出现了。
我的Email是sunyuzhe@263.net 欢迎与大家讨论。