【发布时间】:2018-06-10 05:46:49
【问题描述】:
我尝试将窗口应用程序放在系统托盘上,它工作正常。当我尝试修改它并使用控制台应用程序时,它不起作用。我在万维网上搜索并找到了一个答案,说明如果您能获得控制台的句柄,它将起作用。我是winapi的新手,有人可以帮助我吗?到目前为止,这是我的代码。
#define ID_TRAY_APP_ICON 1001
#define ID_TRAY_EXIT 1002
#define WM_SYSICON (WM_USER + 1)
#define IDI_ICON1 101
/*variables*/
UINT WM_TASKBAR = 0;
HWND Hwnd;
HMENU Hmenu;
NOTIFYICONDATA notifyIconData;
LPCWSTR szClassName = L"System Tray.";
const char* szTIP = "Decryptdcode!";
/*procedures */
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
void minimize();
void restore();
void InitNotifyIconData();
//int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
int main(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow = 0)
{
/*HWND Hwnd = GetConsoleHwnd();
std::cout << GetConsoleWindow() << std::endl;*/
HWND Hwnd2 = GetConsoleWindow();
HWND NewWindow;
std::cout << "Console Title = " << Hwnd << std::endl;
TCHAR currentTitle[512];
TCHAR newCurrentTitle[512];
GetConsoleTitle(currentTitle, sizeof(currentTitle) / sizeof(TCHAR));
std::cout << "Previous Title = " << currentTitle << std::endl;
SetConsoleTitle(_T("New Console Window Title"));
Sleep(40);
//Hwnd2 = FindWindow(NULL, currentTitle);
GetConsoleTitle(newCurrentTitle, sizeof(newCurrentTitle) / sizeof(TCHAR));
std::cout << "Previous Title = " << newCurrentTitle << std::endl;
Hwnd = GetConsoleWindow();
/* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
WM_TASKBAR = RegisterWindowMessageA("TaskbarCreated");
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof(WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
wincl.hIconSm = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
wincl.hbrBackground = (HBRUSH)(CreateSolidBrush(RGB(255, 255, 255)));
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx(&wincl))
return 0;
/* The class is registered, let's create the program*/
// Hwnd = CreateWindowEx(
// 0, /* Extended possibilites for variation */
// szClassName, /* Classname */
// szClassName, /* Title Text */
// WS_OVERLAPPEDWINDOW, /* default window */
// CW_USEDEFAULT, /* Windows decides the position */
// CW_USEDEFAULT, /* where the window ends up on the screen */
// 200, /* The programs width */
// 200, /* and height in pixels */
// HWND_DESKTOP, /* The window is a child-window to desktop */
// NULL, /* No menu */
// hThisInstance, /* Program Instance handler */
// NULL /* No Window Creation data */
//);
/*Initialize the NOTIFYICONDATA structure only once*/
InitNotifyIconData();
/* Make the window visible on the screen */
ShowWindow(Hwnd, nCmdShow);
//ShowWindow(Hwnd, SW_RESTORE);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage(&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
return messages.wParam;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_TASKBAR && !IsWindowVisible(Hwnd))
{
minimize();
return 0;
}
switch (message) /* handle the messages */
{
case WM_ACTIVATE:
Shell_NotifyIcon(NIM_ADD, ¬ifyIconData);
break;
case WM_CREATE:
ShowWindow(Hwnd, SW_HIDE);
Hmenu = CreatePopupMenu();
AppendMenu(Hmenu, MF_STRING, ID_TRAY_EXIT, TEXT("Exit The Demo"));
break;
case WM_SYSCOMMAND:
/*In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter
are used internally by the system. To obtain the correct result when testing the value of wParam,
an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.*/
switch (wParam & 0xFFF0)
{
case SC_MINIMIZE:
case SC_CLOSE:
minimize();
return 0;
break;
}
break;
// Our user defined WM_SYSICON message.
case WM_SYSICON:
{
switch (wParam)
{
case ID_TRAY_APP_ICON:
SetForegroundWindow(Hwnd);
break;
}
if (lParam == WM_LBUTTONUP)
{
restore();
}
else if (lParam == WM_RBUTTONDOWN)
{
// Get current mouse position.
POINT curPoint;
GetCursorPos(&curPoint);
SetForegroundWindow(Hwnd);
// TrackPopupMenu blocks the app until TrackPopupMenu returns
UINT clicked = TrackPopupMenu(Hmenu, TPM_RETURNCMD | TPM_NONOTIFY, curPoint.x, curPoint.y, 0, hwnd, NULL);
SendMessage(hwnd, WM_NULL, 0, 0); // send benign message to window to make sure the menu goes away.
if (clicked == ID_TRAY_EXIT)
{
// quit the application.
Shell_NotifyIcon(NIM_DELETE, ¬ifyIconData);
PostQuitMessage(0);
}
}
}
break;
// intercept the hittest message..
case WM_NCHITTEST:
{
UINT uHitTest = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam);
if (uHitTest == HTCLIENT)
return HTCAPTION;
else
return uHitTest;
}
case WM_CLOSE:
minimize();
return 0;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
void minimize()
{
// hide the main window
ShowWindow(Hwnd, SW_HIDE);
}
void restore()
{
ShowWindow(Hwnd, SW_SHOW);
}
void InitNotifyIconData()
{
memset(¬ifyIconData, 0, sizeof(NOTIFYICONDATA));
notifyIconData.cbSize = sizeof(NOTIFYICONDATA);
notifyIconData.hWnd = Hwnd;
notifyIconData.uID = ID_TRAY_APP_ICON;
notifyIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
notifyIconData.uCallbackMessage = WM_SYSICON; //Set up our invented Windows Message
notifyIconData.hIcon = (HICON)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1));
char output[256] = {};
//const WCHAR* wc = notifyIconData.szTip;
sprintf_s(output, "%ws", notifyIconData.szTip);
//strncpy(notifyIconData.szTip, szTIP, sizeof(szTIP));
strncpy_s(output, szTIP, sizeof(szTIP));
}
【问题讨论】:
-
您的应用程序究竟是如何运行的?您是否希望它作为长时间运行的应用程序运行(因此,系统托盘图标)并将控制台作为窗口?或者您是否希望用户从命令行运行它,并且系统托盘会一直存在,直到命令完成。知道这将产生正确的答案...换句话说,控制台应用程序使用系统托盘图标是非常不寻常的......
-
您正在为通知图标结构设置控制台窗口句柄。
WindowProcedure只会为属于您注册的窗口类的窗口调用,控制台窗口不是其中之一。所以托盘通知不起作用。 -
@selbie 我希望我的控制台应用程序在系统托盘中运行,直到用户退出它(结束进程)。即使我点击了关闭按钮,控制台窗口也必须保持在系统托盘中,当我从系统托盘双击它时,控制台应用程序将显示。
-
@VTT 是的。我想你是正确的。该代码不会将控制台应用程序视为窗口类。你有什么想法吗?
-
创建一个隐藏窗口来处理消息。
标签: c++ windows winapi console-application system-tray