windows API 创建系统托盘图标

系统托盘在我们使用的程序中很普遍,下面我们来看一个很不错的例子,使用Win32 API实现,对理解系统托盘有些帮助。

[cpp] view plain copy print ?
  1. #include   
  2. #define IDR_PAUSE 12  
  3. #define IDR_START 13  
  4. /* 
  5. #include  
  6. #pragma   comment(lib,   "shell32.lib")  
  7. */  
  8. LPCTSTR szAppName = TEXT("服务程序");  
  9. LPCTSTR szWndName = TEXT("服务程序");  
  10. HMENU hmenu;//菜单句柄  
  11.   
  12. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)  
  13. {  
  14.     NOTIFYICONDATA nid;  
  15.     UINT WM_TASKBARCREATED;  
  16.     POINT pt;//用于接收鼠标坐标  
  17.     int xx;//用于接收菜单选项返回值  
  18.   
  19.     // 不要修改TaskbarCreated,这是系统任务栏自定义的消息  
  20.     WM_TASKBARCREATED = RegisterWindowMessage(TEXT("TaskbarCreated"));  
  21.     switch (message)  
  22.     {  
  23.     case WM_CREATE://窗口创建时候的消息.  
  24.         nid.cbSize = sizeof(nid);  
  25.         nid.hWnd = hwnd;  
  26.         nid.uID = 0;  
  27.         nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;  
  28.         nid.uCallbackMessage = WM_USER;  
  29.         nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);  
  30.         lstrcpy(nid.szTip, szAppName);  
  31.         Shell_NotifyIcon(NIM_ADD, &nid);  
  32.         hmenu=CreatePopupMenu();//生成菜单  
  33.         AppendMenu(hmenu,MF_STRING,IDR_PAUSE,"暂停服务");//为菜单添加两个选项  
  34.         AppendMenu(hmenu,MF_STRING,IDR_START,"恢复服务");  
  35.         break;  
  36.     case WM_USER://连续使用该程序时候的消息.  
  37.         if (lParam == WM_LBUTTONDOWN)  
  38.             MessageBox(hwnd, TEXT("Win32 API 实现系统托盘程序,双击托盘可以退出!"), szAppName, MB_OK);  
  39.         if (lParam == WM_LBUTTONDBLCLK)//双击托盘的消息,退出.  
  40.             SendMessage(hwnd, WM_CLOSE, wParam, lParam);  
  41.         if (lParam == WM_RBUTTONDOWN)  
  42.         {  
  43.             GetCursorPos(&pt);//取鼠标坐标  
  44.             ::SetForegroundWindow(hwnd);//解决在菜单外单击左键菜单不消失的问题  
  45.             EnableMenuItem(hmenu,IDR_PAUSE,MF_GRAYED);//让菜单中的某一项变灰  
  46.             xx=TrackPopupMenu(hmenu,TPM_RETURNCMD,pt.x,pt.y,NULL,hwnd,NULL);//显示菜单并获取选项ID  
  47.             if(xx==IDR_PAUSE) MessageBox(hwnd, TEXT("111"), szAppName, MB_OK);  
  48.             if(xx==IDR_START) MessageBox(hwnd, TEXT("222"), szAppName, MB_OK);  
  49.             if(xx==0) PostMessage(hwnd,WM_LBUTTONDOWN,NULL,NULL);  
  50.             //MessageBox(hwnd, TEXT("右键"), szAppName, MB_OK);  
  51.         }  
  52.         break;  
  53.     case WM_DESTROY://窗口销毁时候的消息.  
  54.         Shell_NotifyIcon(NIM_DELETE, &nid);  
  55.         PostQuitMessage(0);  
  56.         break;  
  57.     default:  
  58.         /* 
  59.         * 防止当Explorer.exe 崩溃以后,程序在系统系统托盘中的图标就消失 
  60.         * 
  61.         * 原理:Explorer.exe 重新载入后会重建系统任务栏。当系统任务栏建立的时候会向系统内所有 
  62.         * 注册接收TaskbarCreated 消息的顶级窗口发送一条消息,我们只需要捕捉这个消息,并重建系 
  63.         * 统托盘的图标即可。 
  64.         */  
  65.         if (message == WM_TASKBARCREATED)  
  66.             SendMessage(hwnd, WM_CREATE, wParam, lParam);  
  67.         break;  
  68.     }  
  69.     return DefWindowProc(hwnd, message, wParam, lParam);  
  70. }  
  71.   
  72. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,  
  73.                    LPSTR szCmdLine, int iCmdShow)  
  74. {  
  75.     HWND hwnd;  
  76.     MSG msg;  
  77.     WNDCLASS wndclass;  
  78.   
  79.     HWND handle = FindWindow(NULL, szWndName);  
  80.     if (handle != NULL)  
  81.     {  
  82.         MessageBox(NULL, TEXT("Application is already running"), szAppName, MB_ICONERROR);  
  83.         return 0;  
  84.     }  
  85.   
  86.     wndclass.style = CS_HREDRAW | CS_VREDRAW;  
  87.     wndclass.lpfnWndProc = WndProc;  
  88.     wndclass.cbClsExtra = 0;  
  89.     wndclass.cbWndExtra = 0;  
  90.     wndclass.hInstance = hInstance;  
  91.     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);  
  92.     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);  
  93.     wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);  
  94.     wndclass.lpszMenuName = NULL;  
  95.     wndclass.lpszClassName = szAppName;  
  96.   
  97.     if (!RegisterClass(&wndclass))  
  98.     {  
  99.         MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);  
  100.         return 0;  
  101.     }  
  102.   
  103.     // 此处使用WS_EX_TOOLWINDOW 属性来隐藏显示在任务栏上的窗口程序按钮  
  104.     hwnd = CreateWindowEx(WS_EX_TOOLWINDOW,  
  105.         szAppName, szWndName,  
  106.         WS_POPUP,  
  107.         CW_USEDEFAULT,  
  108.         CW_USEDEFAULT,  
  109.         CW_USEDEFAULT,  
  110.         CW_USEDEFAULT,  
  111.         NULL, NULL, hInstance, NULL);  
  112.   
  113.     ShowWindow(hwnd, iCmdShow);  
  114.     UpdateWindow(hwnd);  
  115.   
  116.     while (GetMessage(&msg, NULL, 0, 0))  
  117.     {  
  118.         TranslateMessage(&msg);  
  119.         DispatchMessage(&msg);  
  120.     }  
  121.     return msg.wParam;  
  122. }  


===================================================
实例2:

//窗口过程
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static NOTIFYICONDATA nid;
	static LPCTSTR szAppName = TRAY_TITLE;
	static HMENU hmenu = NULL;//菜单句柄

	// 不要修改TaskbarCreated,这是系统任务栏自定义的消息
	UINT WM_TASKBARCREATED = RegisterWindowMessage(TEXT("TaskbarCreated"));
	switch (message)
	{
		//窗口创建时候的消息.
	case WM_CREATE:
	{
		nid.cbSize = sizeof(nid);
		nid.hWnd = hwnd;
		nid.uID = 0;
		nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
		nid.uCallbackMessage = WM_USER;
		nid.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MAIN));
		lstrcpy(nid.szTip, szAppName);
		lstrcpy(nid.szInfo, TRAY_START_TITLE);
		lstrcpy(nid.szInfoTitle, TRAY_TITLE);
		nid.dwInfoFlags = NIIF_INFO;

		Shell_NotifyIcon(NIM_ADD, &nid);

		hmenu = CreatePopupMenu();//生成菜单
		AppendMenu(hmenu, MF_STRING, IDR_EXIT, TRAY_MENU_EXIT_TITLE);

		break;
	}
		//连续使用该程序时候的消息.
	case WM_USER:
	{
		if (lParam == WM_LBUTTONDOWN)
		{
			MessageBox(hwnd, TRAY_START_TITLE, szAppName, MB_OK);
		}
		if (lParam == WM_RBUTTONDOWN)
		{
			POINT pt;//用于接收鼠标坐标

			GetCursorPos(&pt);//取鼠标坐标
			::SetForegroundWindow(hwnd);//解决在菜单外单击左键菜单不消失的问题
			int xx = TrackPopupMenu(hmenu, TPM_RETURNCMD, pt.x, pt.y, NULL, hwnd, NULL);//显示菜单并获取选项ID
			if (xx == IDR_EXIT)
			{
				SendMessage(hwnd, WM_CLOSE, wParam, lParam);
			}
		}
		break;
	}
		//窗口销毁时候的消息.
	case WM_DESTROY:
	{
		Shell_NotifyIcon(NIM_DELETE, &nid);
		PostQuitMessage(0);
		break;
	}

	default:
	{
		/*
		* 防止当Explorer.exe 崩溃以后,程序在系统系统托盘中的图标就消失
		*
		* 原理:Explorer.exe 重新载入后会重建系统任务栏。当系统任务栏建立的时候会向系统内所有
		* 注册接收TaskbarCreated 消息的顶级窗口发送一条消息,我们只需要捕捉这个消息,并重建系
		* 统托盘的图标即可。
		*/
		if (message == WM_TASKBARCREATED)
		{
			SendMessage(hwnd, WM_CREATE, wParam, lParam);
		}

		break;
	}
	}

	return DefWindowProc(hwnd, message, wParam, lParam);
}

int CWinMain::CreateMainWin()
{
	WNDCLASS wndclass;								// 定义窗口类结构变量  
	HWND hwnd;										// 定义窗口句柄  
	MSG msg;										// 定义消息结构变量  
	HINSTANCE hInstance = GetModuleHandle(NULL);	//本实例句柄

	/* 定义窗口类的各属性 */
	wndclass.style = CS_HREDRAW | CS_VREDRAW;						// 改变窗口大小则重画  
	wndclass.lpfnWndProc = WndProc;									// 窗口函数为 WndProc  
	wndclass.cbClsExtra = 0;										// 窗口类无扩展  
	wndclass.cbWndExtra = 0;										// 窗口实例无扩展  
	wndclass.hInstance = hInstance;									// 注册窗口类实例句柄  
	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);				// 用箭头光标  
	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);	// 背景为白色  
	wndclass.lpszMenuName = NULL;									// 窗口默认无菜单  
	wndclass.lpszClassName = L"window 窗口创建 ";					// 窗口类名为 window 窗口创建  

	/* 注册窗口类 */
	if (!RegisterClass(&wndclass)) return 0;

	/* 创建窗口 */
	hwnd = CreateWindow(L"window 窗口创建 ", // 窗口类名 window 窗口创建  
		L"window 窗口创建 ",					// 窗口名 window 窗口创建  
		WS_OVERLAPPEDWINDOW,				// 重叠式窗口  
		CW_USEDEFAULT, CW_USEDEFAULT,		// 左上角屏幕坐标默认值  
		CW_USEDEFAULT, CW_USEDEFAULT,		// 窗口宽度和高度默认值  
		NULL,								// 此窗口无父窗口  
		NULL,								// 此窗口无主菜单  
		hInstance,							// 创建此窗口的实例句柄  
		NULL);								// 此窗口无创建参数  

	/* 显示并更新窗口 */
	ShowWindow(hwnd, SW_HIDE);	// 显示窗口  
	UpdateWindow(hwnd);			// 更新窗口的客户区  

	/* 消息循环 */
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);	// 键盘消息转换  
		DispatchMessage(&msg);	// 派送消息给窗口函数  
	}

	return msg.wParam;			// 返回退出值  
}





你可能感兴趣的:(windows API 创建系统托盘图标)