Есть сервис. К нему надо приделать управление. Добавил вывод иконки в трей, она выводится, меняет состояние при изменении состояния службы. Но не выводит меню на иконке. В режиме приложения все работает...
Вот вырезки кода...
| Код | ... MyServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; // интерактивный ... void WINAPI ServiceCtrlHandler(DWORD Opcode) { switch(Opcode) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: ..... return; case SERVICE_CONTROL_CONTINUE: MyServiceStatus.dwCurrentState = SERVICE_RUNNING; break; ..... };
SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus); SetState(); }
HMENU GetMenu() { HMENU hRes = NULL; mKey hKey; HKEY hMainKey = HKEY_LOCAL_MACHINE; switch (state) { case S_RUNNING: hRes = LoadMenu(hInstance, MAKEINTRESOURCE(1)); HMENU hSub = GetSubMenu(hRes, 0); ... break; case S_STOPPED: hRes = LoadMenu(hInstance, MAKEINTRESOURCE(2)); HMENU hSub = GetSubMenu(hRes, 0); ... break; } return hRes; }
void SetState() { int newState = state; if (scService || isService ){ SC_HANDLE tmpSM; SC_HANDLE tmpSC = scService; if ( !scService ) { tmpSM = scService ? scService : OpenSCManager(h.host, NULL, GENERIC_READ | GENERIC_EXECUTE); tmpSC = OpenService(tmpSM, SERVICE_NAME, GENERIC_EXECUTE | GENERIC_READ); } SERVICE_STATUS ss; if (QueryServiceStatus(tmpSC, &ss)){ switch (ss.dwCurrentState) { case SERVICE_STOPPED: newState = S_STOPPED; break; case SERVICE_START_PENDING: newState = S_START_PENDING; break; case SERVICE_STOP_PENDING: newState = S_STOP_PENDING; break; case SERVICE_RUNNING: newState = S_RUNNING; break; } } if ( !scService ) { CloseServiceHandle(tmpSC); CloseServiceHandle(tmpSM); } }else{ newState = runState; } if (wantError && (newState == S_RUNNING)) wantError = FALSE; state = newState; if (_Shell_NotifyIcon){ // блок отрабатывает, проверял!!! ShowWindow(hWnd, SW_HIDE); NOTIFYICONDATA nf; nf.cbSize = sizeof(nf); nf.hWnd = hWnd; nf.uID = TRAYICON_ID; nf.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE; nf.uCallbackMessage = WM_USER; nf.hIcon = (state == S_RUNNING) ? IconRun : IconStop; char *s = StateText(); lstrcpyn(nf.szTip, s, sizeof(nf.szTip)); _Shell_NotifyIcon(NIM_MODIFY, &nf); } if (!fastTimer && ((state == S_START_PENDING) || (state == S_STOP_PENDING))){ KillTimer(hWnd, 1); SetTimer(hWnd, 1, 100, NULL); fastTimer = TRUE; } }
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { ..... case WM_USER: { UINT uID = (UINT)wParam; UINT uMouseMsg = (UINT)lParam; if (uID != TRAYICON_ID) break; switch (uMouseMsg) { case WM_LBUTTONDBLCLK: if (hMenu){ DestroyMenu(hMenu); hMenu = NULL; } hMenu = GetMenu(); if (hMenu) PostMessage(hwnd, WM_COMMAND, state ? ID_HOME : ID_START, 0); break; case WM_RBUTTONUP: { if (hMenu){ DestroyMenu(hMenu); hMenu = NULL; } hMenu = GetMenu(); if (hMenu){ SetActiveWindow(hwnd); SetForegroundWindow(hwnd); POINT pt; GetCursorPos(&pt); TrackPopupMenu(GetSubMenu(hMenu, 0), TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL); PostMessage(hwnd, WM_USER, 0, 0); } break; } } return TRUE; .... } return DefWindowProc(hwnd, uMsg, wParam, lParam); }
void InitWindow() { WNDCLASS wc; wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = 0; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = NULL; wc.lpszClassName = WND_CLASS; if (!RegisterClass(&wc)) return;
hWnd = CreateWindow(WND_CLASS, WND_CLASS, WS_CHILD, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, GetDesktopWindow(), NULL, hInstance, NULL); if (hWnd == NULL) return;
InitIcons(); if (_Shell_NotifyIcon){ ShowWindow(hWnd, SW_HIDE); NOTIFYICONDATA nf; nf.cbSize = sizeof(nf); nf.hWnd = hWnd; nf.uID = TRAYICON_ID; nf.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; nf.uCallbackMessage = WM_USER; nf.hIcon = IconStop; char *s = StateText(); lstrcpyn(nf.szTip, s, sizeof(nf.szTip)); _Shell_NotifyIcon(NIM_ADD, &nf); }else{ SetWindowText(hWnd, StateText()); ShowWindow(hWnd, SW_SHOWMINNOACTIVE); } }
int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE, LPSTR cmdLine, int) { hInstance = _hInstance; SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); ... SERVICE_TABLE_ENTRY srvTbl[2]; srvTbl[0].lpServiceName = SERVICE_NAME; srvTbl[0].lpServiceProc = ServiceMain; srvTbl[1].lpServiceName = NULL; srvTbl[1].lpServiceProc = NULL; ... SC_HANDLE scManager = NULL; HINSTANCE hShell = LoadLibrary("SHELL32.DLL"); if (hShell) *((FARPROC*)(&_Shell_NotifyIcon)) = GetProcAddress(hShell, "Shell_NotifyIconA"); HINSTANCE hUser = LoadLibrary("USER32.DLL"); if (hUser) *((FARPROC*)(&_SetMenuDefaultItem)) = GetProcAddress(hUser, "SetMenuDefaultItem"); InitWindow(); ... if (checkService){ isService = TRUE; if (StartServiceCtrlDispatcher(srvTbl)) return TRUE; int err = GetLastError() & 0xFFFF; if ((err != ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) && (err != ERROR_CALL_NOT_IMPLEMENTED)) return TRUE; isService = FALSE; } if (asService){ scManager = OpenSCManager(h.host, NULL, GENERIC_READ | GENERIC_EXECUTE); if (scManager == NULL){ if (GetLastError() == ERROR_ACCESS_DENIED){ CloseWindow(hWnd); return FALSE; } } } if (scManager) scService = OpenService(scManager, SERVICE_NAME, GENERIC_EXECUTE | GENERIC_READ); ...... return FALSE; }
|
Скрытое окно создается, иконка меняется, меню не вызывается... Может кто с этим сталкивался? Подскажите. |