Win32 API 实现系统托盘程序

托盘程序就是运行在系统托盘区域的程序,显示为桌面右下角显示区域的一个小图标。通常托盘程序带有几种功能:托盘菜单,托盘图标,气泡提示,托盘提示。例如QQ收到消息后,会在系统右下角显示闪动QQ图标。

主程序Tray.cpp

#include <windows.h>
#include "resource.h"

#define WM_TRAY (WM_USER + 100)
#define WM_TASKBAR_CREATED RegisterWindowMessage(TEXT("TaskbarCreated"))

#define APP_NAME	TEXT("托盘程序")
#define APP_TIP		TEXT("Win32 API 实现系统托盘程序")

NOTIFYICONDATA nid;		//托盘属性
HMENU hMenu;			//托盘菜单

//实例化托盘
void InitTray(HINSTANCE hInstance, HWND hWnd)
{
	nid.cbSize = sizeof(NOTIFYICONDATA);
	nid.hWnd = hWnd;
	nid.uID = IDI_TRAY;
	nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
	nid.uCallbackMessage = WM_TRAY;
	nid.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TRAY));
	lstrcpy(nid.szTip, APP_NAME);

	hMenu = CreatePopupMenu();//生成托盘菜单
	//为托盘菜单添加两个选项
	AppendMenu(hMenu, MF_STRING, ID_SHOW, TEXT("提示"));
	AppendMenu(hMenu, MF_STRING, ID_EXIT, TEXT("退出"));

	Shell_NotifyIcon(NIM_ADD, &nid);
}

//演示托盘气泡提醒
void ShowTrayMsg()
{
	lstrcpy(nid.szInfoTitle, APP_NAME);
	lstrcpy(nid.szInfo, TEXT("收到一条消息!"));
	nid.uTimeout = 1000;
	Shell_NotifyIcon(NIM_MODIFY, &nid);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_TRAY:
		switch(lParam)
		{
		case WM_RBUTTONDOWN:
			{
				//获取鼠标坐标
				POINT pt; GetCursorPos(&pt);

				//解决在菜单外单击左键菜单不消失的问题
				SetForegroundWindow(hWnd);

				//使菜单某项变灰
				//EnableMenuItem(hMenu, ID_SHOW, MF_GRAYED);	

				//显示并获取选中的菜单
				int cmd = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, NULL, hWnd,
					 NULL);
				if(cmd == ID_SHOW)
					MessageBox(hWnd, APP_TIP, APP_NAME, MB_OK);
				if(cmd == ID_EXIT) 
					PostMessage(hWnd, WM_DESTROY, NULL, NULL);
			}
			break;
		case WM_LBUTTONDOWN:
			MessageBox(hWnd, APP_TIP, APP_NAME, MB_OK);
			break;
		case WM_LBUTTONDBLCLK:
			break;
		}
		break;
	case WM_DESTROY:
		//窗口销毁时删除托盘
		Shell_NotifyIcon(NIM_DELETE, &nid);
		PostQuitMessage(0);
		break;
	case WM_TIMER:
		ShowTrayMsg();
		KillTimer(hWnd, wParam);
		break;
	}
	if (uMsg == WM_TASKBAR_CREATED)
	{
		//系统Explorer崩溃重启时,重新加载托盘
		Shell_NotifyIcon(NIM_ADD, &nid);
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, 
	LPSTR /*lpCmdLine*/, int iCmdShow)
{
	HWND hWnd;
	MSG msg;
	WNDCLASS wc = { 0 };
	wc.style = NULL;
	wc.hIcon = NULL;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.hbrBackground = NULL;
	wc.lpszMenuName = NULL;
	wc.lpszClassName = APP_NAME;
	wc.hCursor = NULL;

	if (!RegisterClass(&wc)) return 0;

	hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, APP_NAME, APP_NAME, WS_POPUP, CW_USEDEFAULT,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

	ShowWindow(hWnd, iCmdShow);
	UpdateWindow(hWnd);

	InitTray(hInstance, hWnd);			//实例化托盘
	SetTimer(hWnd, 3, 1000, NULL);		//定时发消息,演示气泡提示功能

	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

资源头文件 resource.h

#define IDI_TRAY	101
#define ID_SHOW		40001
#define ID_EXIT		40002

资源文件 resource.rc

#include "resource.h"

IDI_TRAY ICON DISCARDABLE "ico.ico"

编译很简单,使用 Visual Studio建立一个空项目,建好以上3个文件,再找一个ico图标,保存为ico.ico,即可编译。

你可能感兴趣的:(Win32 API 实现系统托盘程序)