C++ 系统托盘关联菜单空白
我试图创建一个没有可见窗口的应用程序,只是一个托盘图标。我曾尝试在这里拼凑各种教程和答案,但没有能够比这更进一步。当我右键单击时,关联菜单将出现,但完全为空。我也不知道一旦我点击了什么,我会如何去检测它 最终目标是通过单击上下文菜单中的两个选项之一来切换DNS服务器C++ 系统托盘关联菜单空白,c++,windows,system-tray,C++,Windows,System Tray,我试图创建一个没有可见窗口的应用程序,只是一个托盘图标。我曾尝试在这里拼凑各种教程和答案,但没有能够比这更进一步。当我右键单击时,关联菜单将出现,但完全为空。我也不知道一旦我点击了什么,我会如何去检测它 最终目标是通过单击上下文菜单中的两个选项之一来切换DNS服务器 #include <Windows.h> #include <shellapi.h> #include <tchar.h> #include <WinUser.h> HINSTAN
#include <Windows.h>
#include <shellapi.h>
#include <tchar.h>
#include <WinUser.h>
HINSTANCE gInstance = NULL;
LRESULT CALLBACK pWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wx;
HWND hWnd;
ZeroMemory(&wx, sizeof(WNDCLASSEX));
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = pWndProc;
wx.hInstance = hInstance;
wx.lpszClassName = (LPCWSTR)"DNSChanger";
RegisterClassEx(&wx);
CreateWindowEx(0, (LPCWSTR)"DNSChanger", (LPCWSTR)"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
gInstance = hInstance;
MSG stMsg;
while (GetMessage(&stMsg, NULL, 0, 0) > 0)
{
TranslateMessage(&stMsg);
DispatchMessage(&stMsg);
}
return 0;
}
LRESULT CALLBACK pWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
NOTIFYICONDATA niData;
ZeroMemory(&niData, sizeof(NOTIFYICONDATA));
switch (uMsg)
{
case WM_CREATE:
{
niData.cbSize = sizeof(NOTIFYICONDATA);
niData.uID = 1;
niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
niData.hIcon = LoadIcon(gInstance, MAKEINTRESOURCE(IDI_SHIELD));
niData.hWnd = hWnd;
niData.uCallbackMessage = WM_USER + 1;
Shell_NotifyIcon(NIM_ADD, &niData);
}
return 0;
case WM_DESTROY:
{
niData.hWnd = hWnd;
Shell_NotifyIcon(NIM_DELETE, &niData);
}
return 0;
case WM_USER + 1:
{
switch (LOWORD(lParam))
{
case WM_RBUTTONUP:
{
POINT lpClickPoint;
HMENU hPopMenu;
UINT uFlag = MF_BYPOSITION | MF_UNCHECKED | MF_STRING;
GetCursorPos(&lpClickPoint);
hPopMenu = CreatePopupMenu();
InsertMenu(hPopMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, WM_USER + 1, _T("Exit"));
SetForegroundWindow(hWnd);
TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, lpClickPoint.x, lpClickPoint.y, 0, hWnd, NULL);
}
}
}
}
}
#包括
#包括
#包括
#包括
HINSTANCE=NULL;
LRESULT回调pWndProc(HWND-HWND、UINT-uMsg、WPARAM-WPARAM、LPARAM-LPARAM);
int APICENTRY WinMain(HINSTANCE HINSTANCE、HINSTANCE hPrevInstance、LPSTR lpCmdLine、int nCmdShow)
{
WNDCLASSEX wx;
HWND-HWND;
零内存(&wx,sizeof(WNDCLASSEX));
wx.cbSize=sizeof(WNDCLASSEX);
wx.lpfnWndProc=pWndProc;
wx.hInstance=hInstance;
wx.lpszClassName=(LPCWSTR)“DNSChanger”;
注册表类(&wx);
CreateWindowEx(0,(LPCWSTR)“DNSChanger”,(LPCWSTR)”,0,0,0,0,HWND_消息,NULL,NULL,NULL);
gInstance=hInstance;
MSG-stMsg;
while(GetMessage(&stMsg,NULL,0,0)>0)
{
翻译信息(&stMsg);
调度消息(&stMsg);
}
返回0;
}
LRESULT回调pWndProc(HWND-HWND、UINT-uMsg、WPARAM-WPARAM、LPARAM-LPARAM)
{
尼达塔;
零内存(&niData,sizeof(notifyiconda));
开关(uMsg)
{
案例WM_创建:
{
niData.cbSize=sizeof(notifyiconda);
niData.uID=1;
niData.uFlags=NIF_图标| NIF_消息| NIF_提示;
niData.hIcon=LoadIcon(ginInstance,MAKEINTRESOURCE(IDI_SHIELD));
niData.hWnd=hWnd;
niData.uCallbackMessage=WM_USER+1;
Shell\u NotifyIcon(NIM\u ADD和niData);
}
返回0;
案例WM_销毁:
{
niData.hWnd=hWnd;
Shell\u NotifyIcon(NIM\u DELETE和niData);
}
返回0;
案例WM_用户+1:
{
开关(LOWORD(LPRAM))
{
案例WM_RBUTTONUP:
{
点击点;
汉努hPopMenu;
UINT uFlag=MF_BYPOSITION | MF_UNCHECKED | MF_STRING;
GetCursorPos(&lpClickPoint);
hPopMenu=CreatePopupMenu();
插入菜单(hPopMenu,0xFFFFFFFF,MF|u BYPOSITION | MF|u STRING,WM_USER+1,_T(“退出”);
setforegroundindow(hWnd);
TrackPopupMenu(hPopMenu,TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN,lpClickPoint.x,lpClickPoint.y,0,hWnd,NULL);
}
}
}
}
}
不要像这样使用cast(LPCWSTR)“DNSChanger”
。这只会隐藏编译器错误。你的程序工作的唯一原因是因为这个错误在两个不同的地方重复,并且它会被取消
你的意思是写L“DNSChanger”
窗口过程必须返回DefWindowProc(hWnd、uMsg、wParam、lParam)代码>
在WM_DESTROY
中,必须包含PostQuitMessage(0)代码>如果要关闭应用程序
定义要在菜单中使用的新常量
const int IDM_EXIT = 100;
...
InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit");
菜单将发送IDM_退出命令作为WM_命令
消息的一部分。以下是一些建议的更改:
HINSTANCE gInstance = NULL;
const int IDM_EXIT = 100;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static NOTIFYICONDATA niData = { sizeof(NOTIFYICONDATA) };
switch(uMsg)
{
case WM_CREATE:
{
niData.uID = 1;
niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
niData.hIcon = LoadIcon(gInstance, IDI_SHIELD);
niData.hWnd = hWnd;
niData.uCallbackMessage = WM_USER + 1;
Shell_NotifyIcon(NIM_ADD, &niData);
return 0;
}
case WM_DESTROY:
{
niData.hWnd = hWnd;
Shell_NotifyIcon(NIM_DELETE, &niData);
PostQuitMessage(0);
return 0;
}
case WM_COMMAND:
{
if(LOWORD(wParam) == IDM_EXIT)
PostQuitMessage(0);
break;
}
case WM_USER + 1:
{
WORD cmd = LOWORD(lParam);
if (cmd == WM_RBUTTONUP || cmd == WM_LBUTTONUP)
{
POINT pt;
GetCursorPos(&pt);
HMENU hmenu = CreatePopupMenu();
InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit");
TrackPopupMenu(hmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, pt.x, pt.y, 0, hWnd, NULL);
}
break;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
gInstance = hInstance;
WNDCLASSEX wx = { sizeof(WNDCLASSEX) };
wx.lpfnWndProc = WndProc;
wx.hInstance = hInstance;
wx.lpszClassName = L"DNSChanger";
RegisterClassEx(&wx);
CreateWindowEx(0, L"DNSChanger", L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
谢谢这是固定的,我现在有退出选项,应该能够完成从这里休息!但是图标已经消失了…在任务栏上显示屏蔽图标之前,现在它只是一个空白,不确定哪些更改可能会影响到它…我还将MAKEINTRESOURCE(IDI_shield)
更改为IDI_shield
,因为IDI_shield
在“WinUser.h”
中定义为MAKEINTRESOURCE(32518)
,可能是先前的错误id导致了显示错误。您可能必须重新启动计算机以清除图标缓存。您仍然想提供自己的图标。不确定图标为何消失,但添加我自己的图标后没有任何问题。程序现在已经完成,谢谢帮助:)有一件事让我困惑,从debug更改为release意味着我必须从所有字符串中删除前导的“L”,以便对其进行编译…?在“项目属性”下,您已将“字符集”设置为“Unicode”,但对于ReleaseMode,它表示“未设置”。建议将它们都设置为Unicode