如何实现程序缩小后,显示在右下角一个图标?

ren20 2001-05-07 03:01:00
类似杀毒软件,缩小后,在右下角有一个标志。
...全文
663 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
chief 2001-05-08
  • 打赏
  • 举报
回复
to ren20:
因為我的程式關于trayicon的代碼只是极小一部分,讓你看可能也比較麻煩,以下是我找的一篇文章,相信對你會有幫助,其中有如何動畫圖標的說明,你看看吧:

在任务栏状态区显示应用程序图标

数据结构:

有关的数据由NOTIFYICONDATA结构描述:

typedef struct _NOTIFYICONDATA
{
DWORD cbSize; //结构的大小,必须设置
HWND hWnd; //接受回调消息的窗口的句柄
UINT uID; //应用程序定义的图标标志
UINT uFlags; //标志,可以是NIF_ICON、NIF_MESSAGE、NIF_TIP或其组合
UINT uCallbackMessage;//应用程序定义的回调消息标志
HICON hIcon; //图标句柄
char szTip[64]; //提示字串
} NOTIFYICONDATA, *PNOTIFYICONDATA;

函数说明

由Shell_NotifyIcon()函数向系统发送添加、删除、更改图标的消息。

WINSHELLAPI BOOL WINAPI Shell_NotifyIcon(DWORD dwMessage,PNOTIFYICONDATA pnid);

DwMessage为所发送消息的标志:
NIM_ADD 添加图标到任务栏通知区;
NIM_DELETE 删除任务栏通知区的图标;
NIM_MODIFY 更改任务栏通知区的图标、回调消息标志、回调窗口句柄或提示字串;
pnid为NOTIFYICONDATA结构的指针。

回调信息的获得及处理

如果一个任务栏图标有应用程序定义的回调消息,那么当这个图标有鼠标操作时,系统将给hWnd所标志的窗口发送下列的消息:
messageID = uCallbackMessage
wParam = uID
lParam = mouse event(例如WM_LBUTTONDOWN)

通过这种方式,系统通知应用程序用户对图标的操作。如果一个应用程序生成了两个以上的图标,那么你可以根据wParam来判断是哪个图标返回的鼠标操作。通常,标准的Win95任务栏图标有以下鼠标操作响应:

当鼠标停留在图标上时,系统应显示提示信息tooltip;
当使用鼠标右键单击图标时,应用程序应显示快捷菜单;
当使用鼠标左键双击图标时,应用程序应执行快捷菜单的缺省菜单项。

在Microsoft Windows环境中,0x8000到0xBFFF的消息是保留的,应用程序可以定义自定义消息。

关于消息处理的详细内容,请参考下一部分。

源码及实现

在本文中关于任务栏图标的类叫做CTrayIcon,这个类由CCmdTarget(或CObject)类派生,它有如下的成员变量和成员函数:

// TrayIcon.h
// CTrayIcon command target

class CTrayIcon : public CCmdTarget
{
public:
NOTIFYICONDATA m_nid;//NOTIFYICONDATA结构,你的图标要用的啊
BOOL m_IconExist;//标志,看看图标是不是已经存在了
CWnd* m_NotificationWnd;//接受回调消息的窗口,有它就不必经常AfxGetMainWnd了
public:
CWnd* GetNotificationWnd() const;//得到m_NotificationWnd
BOOL SetNotificationWnd(CWnd* pNotifyWnd);//设置(更改)m_NotificationWnd
CTrayIcon();//构造函数
virtual ~CTrayIcon();//析构函数
BOOL CreateIcon(CWnd* pNotifyWnd, UINT uID, HICON hIcon,
LPSTR lpszTip, UINT CallBackMessage);//在任务栏上生成图标
BOOL DeleteIcon();//删除任务栏上的图标
virtual LRESULT OnNotify(WPARAM WParam, LPARAM LParam);//消息响应函数
BOOL SetTipText(UINT nID);//设置(更改)提示字串
BOOL SetTipText(LPCTSTR lpszTip);//设置(更改)提示字串
BOOL ChangeIcon(HICON hIcon);//更改图标
BOOL ChangeIcon(UINT nID);//更改图标
BOOL ChangeIcon(LPCTSTR lpszIconName);//更改图标
BOOL ChangeStandardIcon(LPCTSTR lpszIconName);//更改为标准图标
......
};

下面是成员函数的定义:

// TrayIcon.cpp
// CTrayIcon

CTrayIcon::CTrayIcon()
{//初始化参数
m_IconExist = FALSE;
m_NotificationWnd = NULL;
memset(&m_nid, 0, sizeof(m_nid));
m_nid.cbSize = sizeof(m_nid);//这个参数不会改变
}

CTrayIcon::~CTrayIcon()
{
if (m_IconExist)
DeleteIcon();//删除图标
}

BOOL CTrayIcon::CreateIcon(CWnd* pNotifyWnd, UINT uID, HICON hIcon,
LPSTR lpszTip, UINT CallBackMessage)
{
//确定接受回调消息的窗口是有效的
ASSERT(pNotifyWnd && ::IsWindow(pNotifyWnd->GetSafeHwnd()));

ASSERT(CallBackMessage >= WM_USER);//确定回调消息不发生冲突

ASSERT(_tcslen(lpszTip) <= 64);//提示字串不能超过64个字符

m_NotificationWnd = pNotifyWnd;//获得m_NotificationWnd

//设置NOTIFYICONDATA结构
m_nid.hWnd = pNotifyWnd->GetSafeHwnd();
m_nid.uID = uID;
m_nid.hIcon = hIcon;
m_nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
m_nid.uCallbackMessage = CallBackMessage;

//设置NOTIFYICONDATA结构的提示字串
if (lpszTip)
lstrcpyn(m_nid.szTip, lpszTip, sizeof(m_nid.szTip));
else
m_nid.szTip[0] = '\0';

//显示图标
m_IconExist = Shell_NotifyIcon(NIM_ADD, &m_nid);
return m_IconExist;
}

BOOL CTrayIcon::DeleteIcon()
{//删除图标
if (!m_IconExist)
return FALSE;
m_IconExist = FALSE;
return Shell_NotifyIcon(NIM_DELETE, &m_nid);
}

LRESULT CTrayIcon::OnNotify(WPARAM WParam, LPARAM LParam)
{//处理图标返回的消息
if (WParam != m_nid.uID)//如果不是该图标的消息则迅速返回
return 0L;

//准备快捷菜单
CMenu menu;
if (!menu.LoadMenu(IDR_POPUP))//你必须确定资源中有ID为IDR_POPUP的菜单
return 0;
CMenu* pSubMenu = menu.GetSubMenu(0);//获得IDR_POPUP的子菜单
if (!pSubMenu)
return 0;

if (LParam == WM_RBUTTONUP)
{//右键单击弹出快捷菜单

//设置第一个菜单项为缺省
::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE);
CPoint pos;
GetCursorPos(&pos);

//显示并跟踪菜单
m_NotificationWnd->SetForegroundWindow();
pSubMenu->TrackPopupMenu(TPM_RIGHTALIGN|TPM_LEFTBUTTON
|TPM_RIGHTBUTTON, pos.x, pos.y, m_NotificationWnd, NULL);
}
else if (LParam == WM_LBUTTONDOWN)
{//左键单击恢复窗口
m_NotificationWnd->ShowWindow(SW_SHOW);//恢复窗口
m_NotificationWnd->SetForegroundWindow();//放置在前面
}
else if (LParam == WM_LBUTTONDBLCLK)
{//左键双击执行缺省菜单项
m_NotificationWnd->SendMessage(WM_COMMAND,
pSubMenu->GetMenuItemID(0), 0);
}
return 1L;
}

BOOL CTrayIcon::SetTipText(LPCTSTR lpszTip)
{//设置提示文字
if (!m_IconExist)
return FALSE;

_tcscpy(m_nid.szTip, lpszTip);
m_nid.uFlags |= NIF_TIP;

return Shell_NotifyIcon(NIM_MODIFY, &m_nid);
}

BOOL CTrayIcon::SetTipText(UINT nID)
{//设置提示文字
CString szTip;
VERIFY(szTip.LoadString(nID));

return SetTipText(szTip);
}
BOOL CTrayIcon::ChangeIcon(HICON hIcon)
{//更改图标
if (!m_IconExist)
return FALSE;

m_nid.hIcon = hIcon;
m_nid.uFlags |= NIF_ICON;

return Shell_NotifyIcon(NIM_MODIFY, &m_nid);
}

BOOL CTrayIcon::ChangeIcon(UINT nID)
{//更改图标
HICON hIcon = AfxGetApp()->LoadIcon(nID);
return ChangeIcon(hIcon);
}

BOOL CTrayIcon::ChangeIcon(LPCTSTR lpszIconName)
{//更改图标
HICON hIcon = AfxGetApp()->LoadIcon(lpszIconName);
return ChangeIcon(hIcon);
}

BOOL CTrayIcon::ChangeStandardIcon(LPCTSTR lpszIconName)
{//更改为标准图标
HICON hIcon = AfxGetApp()->LoadStandardIcon(lpszIconName);
return ChangeIcon(hIcon);
}

BOOL CTrayIcon::SetNotificationWnd(CWnd * pNotifyWnd)
{//设置接受回调消息的窗口
if (!m_IconExist)
return FALSE;

//确定窗口是有效的
ASSERT(pNotifyWnd && ::IsWindow(pNotifyWnd->GetSafeHwnd()));

m_NotificationWnd = pNotifyWnd;
m_nid.hWnd = pNotifyWnd->GetSafeHwnd();
m_nid.uFlags |= NIF_MESSAGE;

return Shell_NotifyIcon(NIM_MODIFY, &m_nid);
}

CWnd* CTrayIcon::GetNotificationWnd() const
{//返回接受回调消息的窗口
return m_NotificationWnd;
}


三点补充:
关于使用回调消息的补充说明:

首先,在MainFrm.cpp中加入自己的消息代码;
// MainFrm.cpp : implementation of the CMainFrame class
//
#define MYWM_ICONNOTIFY WM_USER + 10//定义自己的消息代码

第二步增加消息映射和函数声明,对于自定义消息不能由ClassWizard添加消息映射,只能手工添加。
// MainFrm.cpp : implementation of the CMainFrame class
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
//其他的消息映射
......
//}}AFX_MSG_MAP
ON_MESSAGE(WM_ICONNOTIFY,OnNotify)
END_MESSAGE_MAP()
并且在头文件中添加函数声明
// MainFrm.h
afx_msg LRESULT OnNotify(WPARAM WParam, LPARAM LParam);

第三步增加消息处理函数定义
LRESULT CMainFrame::OnNotify(WPARAM WParam, LPARAM LParam)
{
return trayicon.OnNotify(WParam, LParam);//调用CTrayIcon类的处理函数
}

如何隐藏任务栏上的按钮:

可以使用下列两种方法:
1.在CreateWindowEx函数中使用WS_EX_TOOLWINDOW窗口式样(相反的如果要确保应用程序在任务栏上生成按钮,可以使用WS_EX_APPWINDOW窗口式样)。 The problem with this is that the window decorations are as for a small floating toolbar, which isn't normally what's wanted.
2.生成一个空的隐藏的top-level窗口,并使其作为可视窗口的父窗口。
3.在应用程序的InitInstance()函数中使用SW_HIDE式样调用ShowWindow()函数。
//pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->ShowWindow(SW_HIDE);
pMainFrame->UpdateWindow();

如何动画任务栏上的图标:

在TrayIcon类中加入下列两个函数:

BOOL CTrayIcon::SetAnimateIcons(HICON* hIcon, UINT Number)
{//设置动画图标
ASSERT(Number >= 2);//图标必须为两个以上
ASSERT(hIcon);//图标必须不为空

m_AnimateIcons = new HICON[Number];
CopyMemory(m_AnimateIcons, hIcon, Number * sizeof(HICON));
m_AnimateIconsNumber = Number;
return TRUE;
}

BOOL CTrayIcon::Animate(UINT Index)
{//动画TrayIcon
UINT i = Index % m_AnimateIconsNumber;
return ChangeIcon(m_AnimateIcons[i]);
}

在应用程序中添加相应的菜单和函数(请参考下面的例子):

void CMainFrame::OnMenuAnimate()
{//动画TrayIcon,设置图标及定时器
SetTimer(1, 500, NULL);
HICON hIcon[3];
hIcon[0] = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
hIcon[1] = AfxGetApp()->LoadIcon(IDR_MYTURNTYPE);
hIcon[2] = AfxGetApp()->LoadStandardIcon(IDI_HAND);
trayicon.SetAnimateIcons(hIcon, 3);
}

void CMainFrame::OnTimer(UINT nIDEvent)
{//动画TrayIcon
UINT static i;
i += 1;
trayicon.Animate(i);

CMDIFrameWnd::OnTimer(nIDEvent);
}

winhand 2001-05-07
  • 打赏
  • 举报
回复
软吗我有呀,就是用cstrayicon实现的,如果需要的可以找我.其实这种东西在上面很多的
ren20 2001-05-07
  • 打赏
  • 举报
回复
chief:

代码也让我看看吧,谢谢
chief 2001-05-07
  • 打赏
  • 举报
回复
哈,我剛好有個程序有相關的code,貼給你:
1--- //初始化
NOTIFYICONDATA nid;
nid.hWnd=this->GetSafeHwnd(); //響應消息的窗口句柄
strcpy(nid.szTip,""); //提示tip
nid.uCallbackMessage=WM_TRAYICONMSG; //自定義消息
nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;
nid.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME); //顯示于托盤區的圖標句柄
nid.uID=ID_TRAY; //分配給這個托盤圖標的句柄
nid.cbSize=sizeof(nid);
2--- //增加圖標至托盤區
::Shell_NotifyIcon(NIM_ADD,&nid);
3--- //從托盤區刪除圖標
::Shell_NotifyIcon(NIM_DELETE,&nid);
4--- 在程序中加上自定義消息WM_TRAYICONMSG的映射,以響應用戶在圖標上的MOUSE點 擊,其中LPARAM指明了消息類型,如WM_LBUTTONDOWN...
了解以上這些已可以做一些基本操作,其它的我就不多說了,你如果需要的話,我可以把我的程式碼給你。
starcbh 2001-05-07
  • 打赏
  • 举报
回复
shell_notifyicon(message,&tnid);
如add,delete等消息,tnid是一个结构,里面有各种参数!如icon,flags等!
具体就不说了。
AlphaOne 2001-05-07
  • 打赏
  • 举报
回复
Shell_NotifyIcon();
注意:这个函数里要传入一个自定义消息,例如:WM_USER + 100,
当有相应的鼠标事件发生时(例如:点击),你的窗口会收到这个消息,
只要你处理这个消息,即可相应执行操作。
pgfun 2001-05-07
  • 打赏
  • 举报
回复
shellNotifyIcon中第一个参数设为NIM_MODIFY既可动态修改图标
chendd2001 2001-05-07
  • 打赏
  • 举报
回复
问的好
smint 2001-05-07
  • 打赏
  • 举报
回复
还有其他参数用于加,改,删的.
ren20 2001-05-07
  • 打赏
  • 举报
回复
能不能是动态的,可以随时改变的?谢谢
再加30分
chen_jun_fen 2001-05-07
  • 打赏
  • 举报
回复
//回调消息
#define MYWM_NOTIFYICON WM_USER+1
//在任务栏状态区显示图标的消息
#define MYWM_SHOWAPPICONIC WM_USER+2

MainFrm.h 里 添 加 定 义 消 息 处 理 函 数 说 明, 该 部 分 看 起 来 如 下:
protected:
afs_msg void OnMyIconNotify( WPARAM wParam, LPARAM lParam );
// 手 工 加
afx_msg void OnShowAppIconic( WPARAM wParam, LPARAM lParam );
// 手 工 加
//}}AFX_MSG

DECLARE_MESSAGE_MAP()

需 在MainFrm.h 定 义 一 开 关 值, 记 录 程 序 窗 口 是 打 开 或 关 闭 状 态:
BOOL boolWndHadShow;
在MainFrm.cpp 里 实 现 消 息 映 射 和 消 息 处 理 函 数。 消 息 映 射 部 分 看 起 来 如 下:

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_MESSAGE(MYWM_NOTIFYICON, OnMyIconNotify)
ON_MESSAGE(MYWM_SHOWAPPICONIC, OnShowAppIconic)
ON_WM_SYSCOMMAND()
ON_WM_CLOSE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

---- 消 息 处 理 及 相 关 函 数 如 下 所 示:

//在任务栏状态区添加图标
BOOL MyTaskBarAddIcon(HWND hwnd,
UINT uID, HICON hicon, LPSTR lpszTip)
{
BOOL res;
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = hwnd;
tnid.uID = uID;
tnid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE;
tnid.uCallbackMessage = MYWM_NOTIFYICON;
tnid.hIcon = hicon;
if (lpszTip) lstrcpyn(tnid.szTip, lpszTip, sizeof(tnid.szTip));
else
tnid.szTip[0] = '\0';
res = Shell_NotifyIcon(NIM_ADD, &tnid);
if (hicon)
DestroyIcon(hicon);
return res;
}

//从任务栏状态区删除图标
BOOL MyTaskBarDeleteIcon(HWND hwnd, UINT uID)
{
BOOL res;
NOTIFYICONDATA tnid;
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = hwnd;
tnid.uID = uID;
res = Shell_NotifyIcon(NIM_DELETE, &tnid);
return res;
}

//处理图标回调消息MYWM_NOTIFYICON
void CMainFrame::OnMyIconNotify
( WPARAM wParam, LPARAM lParam )
{
UINT nID;
UINT uMouseMsg;
nID = (UINT)wParam;
uMouseMsg = (UINT) lParam;
if (uMouseMsg == WM_LBUTTONDOWN) //点击图标
{
if ( boolWndHadShow ) //如果窗口已打开,隐藏窗口
ShowWindow( SW_HIDE );
else //否则,显示窗口
ShowWindow( SW_SHOWNORMAL );
boolWndHadShow = ~boolWndHadShow;
}
}

//消息MYWM_SHOWAPPICONIC
处理函数,在任务栏显示图标并隐藏窗口
void CMainFrame::OnShowAppIconic
( WPARAM wParam, LPARAM lParam )
{
HICON theIcon = LoadIcon(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDR_MAINFRAME) );
MyTaskBarAddIcon(GetSafeHwnd(), 100, theIcon, _T("示范程序"));
ShowWindow( SW_HIDE );
boolWndHadShow = FALSE;
}

---- 当 程 序 关 闭 时, 需 把 图 标 从 任 务 样 状 态 区 删 除, 你 可 以 添 加 一 个 处 理WM_CLOSE 消 息 的 函 数 来 删 除 图 标。 通 过ClassWizard 来 添 加 处 理WM_CLOSE 的 函 数OnClose(), 该 函 数 如 下:

void CMainFrame::OnClose()
{
// TODO: Add your message handler
code here and/or call default
MyTaskBarDeleteIcon( GetSafeHwnd(), 100 );
CFrameWnd::OnClose();
}

---- 当 用 户 把 窗 口 最 小 化 时, 你 应 隐 藏 整 个 窗 口, 所 以 要 处 理ON_SYSCOMMAND 消 息。 首 先 在MainFrm.h 添 加 函 数 说 明, 如 第3 步 所 示; 然 后 在MainFrm.cpp 里 说 明 消 息 映 射 和 实 现 函 数。 消 息 映 射 如 前 面 所 示, 函 数 实 现 如 下:

void CMainFrame::OnSysCommand
( UINT nID, LPARAM lParam )
{
if ( nID==SC_MINIMIZE )
{
ShowWindow( SW_HIDE );
boolWndHadShow = FALSE;
}
else
CWnd::OnSysCommand( nID, lParam );
}

---- 5. 在InitInstance() 函 数 返 回 前, 添 加 一 语 句

m_pMainWnd- >PostMessage( MYWM_SHOWAPPICONIC );

在对话模式下也差不多了,希望这个程序能对你有所帮助 


--------------------------------------------------------------------------------

 

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧