头文件
#ifndef WIN_CONSOLE_TRAY
#define WIN_CONSOLE_TRAY
#include <iostream>
#include <string>
//windows下控制台托盘接口
#ifdef WIN32
#include <Windows.h>
#define TRAY_MSG_CLOSE 0x01
//消息回调,目前只回调了关闭消息
typedef void (*fTrayCallBack)(int nMsgType);
/* 功能:启动托盘
参数: hwnd 程序窗口
hicon 托盘图标
fCallBack 消息回调
szServerName 托盘提示文本
返回值:成功返回0,失败返回-1*/
long StartTray(HWND hwnd,HICON hIcon,fTrayCallBack fCallBack,std::string szServerName);
//停止托盘
long StopTray();
#endif
#endif //WIN_CONSOLE_TRAY
.cpp文件
#include "stdafx.h"
#include "WinConsoleTray.h"
#include "EC_GeneralError.h"
#include <commctrl.h>
#include <atltypes.h>
#include<cstring>
using namespace std;
#define SWM_SHOW WM_APP + 1
#define SWM_HIDE WM_APP + 2
#define SWM_EXIT WM_APP + 3
#define WM_NOTIFYICON (WM_USER+100)
#ifdef WIN32
fTrayCallBack m_fCallBack=NULL;
HANDLE m_hThread=NULL;
HWND m_hTrayWnd=NULL;
HWND m_hMainWnd=NULL;
NOTIFYICONDATA m_struNotifyIconData;
HICON m_hIcon=NULL;
std::string m_szServerName;
void ShowContextMenu(HWND hWnd);
LRESULT CALLBACK TrayWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
DWORD WINAPI TrayRun( LPVOID lpParam )
{
//创建托盘窗口
HWND hTrayWnd = ::CreateWindowA( "#32770", "1234", WS_OVERLAPPED, 0, 0, 2, 3, NULL, NULL, GetModuleHandleA(NULL),NULL );
if(hTrayWnd==NULL)
return -1;
m_hTrayWnd=hTrayWnd;
SetWindowLongA(hTrayWnd, GWL_WNDPROC, (LONG)TrayWndProc);
ShowWindow( hTrayWnd, SW_HIDE );
UpdateWindow(hTrayWnd);
//设置托盘通知
NOTIFYICONDATA struNotifyData;
struNotifyData.cbSize=sizeof(NOTIFYICONDATA);
struNotifyData.hIcon=m_hIcon;
struNotifyData.hWnd=hTrayWnd;
strcpy_s(struNotifyData.szTip, m_szServerName.c_str());
struNotifyData.uCallbackMessage=WM_NOTIFYICON;
struNotifyData.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
struNotifyData.uID=104;
Shell_NotifyIcon(NIM_ADD,&struNotifyData);
//气泡显示
struNotifyData.cbSize=sizeof(NOTIFYICONDATA);
struNotifyData.uFlags = NIF_INFO;
struNotifyData.uTimeout = 1000;
struNotifyData.dwInfoFlags = NIIF_INFO;
strcpy_s(struNotifyData.szTip, m_szServerName.c_str());
memset(struNotifyData.szInfo, 0, sizeof(struNotifyData.szInfo));
memset(struNotifyData.szInfoTitle, 0, sizeof(struNotifyData.szInfoTitle));
Shell_NotifyIcon(NIM_MODIFY, &struNotifyData);
m_struNotifyIconData=struNotifyData;
while(true)
{
MSG Msg;
ZeroMemory(&Msg, sizeof(MSG));
::GetMessage(&Msg, hTrayWnd, 0, 0);
::TranslateMessage(&Msg);
::DispatchMessage(&Msg);
}
return VMS_SUCCESS;
}
LRESULT CALLBACK TrayWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
BOOL isProcessFlag=0;
switch(uMsg)
{
case WM_NOTIFYICON:
{
switch(lParam)
{
case WM_RBUTTONUP:
{
//显示菜单
ShowContextMenu(hWnd);
isProcessFlag=TRUE;
}
break;
case WM_LBUTTONUP:
{
if(IsWindowVisible(m_hMainWnd))
ShowWindow(m_hMainWnd,SW_HIDE);
else
{
ShowWindow(m_hMainWnd,SW_SHOWNORMAL);
SetFocus(m_hMainWnd);
}
isProcessFlag=TRUE;
}
break;
default:
break;
}
}
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case SWM_SHOW:
{
ShowWindow(m_hMainWnd,SW_SHOWNORMAL);
SetFocus(m_hMainWnd);
}
break;
case SWM_HIDE:
ShowWindow(m_hMainWnd,SW_HIDE);
break;
case SWM_EXIT:
{
if(m_fCallBack!=NULL)
m_fCallBack(TRAY_MSG_CLOSE);
}
break;
default:
break;
}
break;
}
default:
break;
}
if(isProcessFlag)
return VMS_SUCCESS;
else
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
void ShowContextMenu(HWND hWnd)
{
POINT pt;
HMENU hMenu = CreatePopupMenu();
GetCursorPos(&pt);
if(hMenu)
{
if( IsWindowVisible(m_hMainWnd))
InsertMenu(hMenu, -1, MF_BYPOSITION, SWM_HIDE, "隐藏");
else
InsertMenu(hMenu, -1, MF_BYPOSITION, SWM_SHOW, "显示");
InsertMenu(hMenu, -1, MF_BYPOSITION, SWM_EXIT, "关闭");
SetForegroundWindow(hWnd);
TrackPopupMenu(hMenu, TPM_BOTTOMALIGN,pt.x, pt.y, 0, hWnd, NULL );
DestroyMenu(hMenu);
}
}
long RefreshTrayArea()
{
HWND hStatus=::FindWindow("Shell_TrayWnd",NULL); //得到任务栏句柄
if(hStatus==NULL)
return -1;
HWND hNotify=FindWindowEx(hStatus,NULL,"TrayNotifyWnd",NULL); //右下角区域
if(hNotify==NULL)
return -1;
HWND hNotify1=FindWindowEx(hNotify,NULL,"SysPager",NULL);
if(hNotify==NULL)
return -1;
HWND hNotify1_0=FindWindowEx(hNotify1,NULL,"ToolBarWindow32",NULL);//右下角区域(不包括时间)
if(hNotify1_0==NULL)
return -1;
DWORD pid = 0;
GetWindowThreadProcessId(hNotify1_0,&pid);
if(pid==NULL)
return -1;
HANDLE hProcess=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_ALL_ACCESS,true,pid);
if (hProcess==NULL)
return -1;
::SendMessage(hNotify1_0,WM_PAINT ,NULL,NULL);
RECT rect;
::GetWindowRect(hNotify1_0,&rect);
::InvalidateRect(hNotify1_0,&rect,false);
int iNum=::SendMessage(hNotify1_0,TB_BUTTONCOUNT ,NULL,NULL); //获取任务栏上图标个数
unsigned long n = 0;
TBBUTTON *pButton = new TBBUTTON;
wchar_t name[256] = {0};
TBBUTTON BButton;
unsigned long whd,proid;
for(int i=0; i<iNum; i++)
{
::SendMessage(hNotify1_0,TB_GETBUTTON,i,(LPARAM)(&BButton));
ReadProcessMemory(hProcess,&BButton,pButton,sizeof(TBBUTTON),&n);
if (pButton->iString != 0xffffffff)
ReadProcessMemory(hProcess,(void *)pButton->iString,name,255,&n);
whd=0;
ReadProcessMemory(hProcess,(void *)pButton->dwData,&whd,4,&n);
proid=NULL;
GetWindowThreadProcessId((HWND)whd,&proid);
if(proid==NULL)
::SendMessage(hNotify1_0,TB_DELETEBUTTON,i,0);
}
delete pButton;
return 0;
};
long StartTray(HWND hwnd,HICON hIcon,fTrayCallBack fCallBack,std::string szServerName)
{
//RefreshTrayArea();
//设置标题栏图标
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
m_fCallBack=fCallBack;
m_hIcon=hIcon;
m_hMainWnd=hwnd;
m_szServerName=szServerName;
DWORD dwThreadid;
m_hThread = CreateThread(NULL,0,TrayRun,NULL,0,&dwThreadid);
return VMS_SUCCESS;
}
long StopTray()
{
Shell_NotifyIcon(NIM_DELETE, &m_struNotifyIconData);
CloseHandle(m_hThread);
return 0;
}
#endif
调用程序demo:
HICON hIcon;
hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
StartTray(m_hWnd,hIcon,CallBackFunc,_T("Tray Call Back"));
退出时:
void CallBackFunc(int nMsgType)
{
switch (nMsgType)
{
case TRAY_MSG_CLOSE:
StopTray();
::SendMessage(::FindWindow(NULL,"handler"),WM_CLOSE,NULL,NULL);
窗口的名为handler
break;
default:
break;
}
}