📄 daemon.cpp
字号:
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.//// This file is part of the VNC system.//// The VNC system is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,// USA.//// If the source code for the VNC system is not available from the place // whence you received this file, check http://www.uk.research.att.com/vnc or contact// the authors on vnc@uk.research.att.com for information on obtaining it.// Daemon.cpp: implementation of the Daemon class.#include "stdhdrs.h"#include "vncviewer.h"#include "Daemon.h"#include "Exception.h"#include "ClientConnection.h"#include "AboutBox.h"//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////#define DAEMON_CLASS_NAME "VNCviewer Daemon"Daemon::Daemon(int port){ // Create a dummy window WNDCLASSEX wndclass; wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wndclass.lpfnWndProc = Daemon::WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = pApp->m_instance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = (const char *) NULL; wndclass.lpszClassName = DAEMON_CLASS_NAME; wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wndclass); m_hwnd = CreateWindow(DAEMON_CLASS_NAME, DAEMON_CLASS_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, NULL, NULL, pApp->m_instance, NULL); // record which client created this window SetWindowLong(m_hwnd, GWL_USERDATA, (LONG) this); // Load a popup menu m_hmenu = LoadMenu(pApp->m_instance, MAKEINTRESOURCE(IDR_TRAYMENU)); // Create a listening socket struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = INADDR_ANY; m_sock = socket(AF_INET, SOCK_STREAM, 0); if (!m_sock) throw WarningException("Error creating Daemon socket"); try { int one = 1, res = 0; //res = setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &one, sizeof(one)); //if (res == SOCKET_ERROR) // throw WarningException("Error setting Daemon socket options"); res = bind(m_sock, (struct sockaddr *)&addr, sizeof(addr)); if (res == SOCKET_ERROR) throw WarningException("Error binding Daemon socket"); res = listen(m_sock, 5); if (res == SOCKET_ERROR) throw WarningException("Error when Daemon listens"); } catch (...) { closesocket(m_sock); m_sock = 0; throw; } // Send a message to specified window on an incoming connection WSAAsyncSelect (m_sock, m_hwnd, WM_SOCKEVENT, FD_ACCEPT); // Create the tray icon AddTrayIcon(); // A timer checks that the tray icon is intact m_timer = SetTimer( m_hwnd, IDT_TRAYTIMER, 15000, NULL);}void Daemon::AddTrayIcon() { log.Print(4, _T("Adding tray icon\n")); SendTrayMsg(NIM_ADD);}void Daemon::CheckTrayIcon() { log.Print(8, _T("Checking tray icon\n")); if (!SendTrayMsg(NIM_MODIFY)) { log.Print(4, _T("Tray icon not there - reinstalling\n")); AddTrayIcon(); };}void Daemon::RemoveTrayIcon() { log.Print(4, _T("Deleting tray icon\n")); SendTrayMsg(NIM_DELETE);}bool Daemon::SendTrayMsg(DWORD msg){ m_nid.hWnd = m_hwnd; m_nid.cbSize = sizeof(m_nid); m_nid.uID = IDR_TRAY; // never changes after construction // LoadIcon seems to mess up 16x16 images. Maybe we should use // LoadImage instead? m_nid.hIcon = LoadIcon(pApp->m_instance, MAKEINTRESOURCE(IDR_TRAY)); //m_nid.hIcon = (HICON)LoadImage(pApp->m_instance, // MAKEINTRESOURCE(IDR_TRAY), // IMAGE_ICON, 0, 0, // LR_DEFAULTCOLOR|LR_SHARED); m_nid.uFlags = NIF_ICON | NIF_MESSAGE; m_nid.uCallbackMessage = WM_TRAYNOTIFY; m_nid.szTip[0] = '\0'; // Use resource string as tip if there is one if (LoadString(pApp->m_instance, IDR_TRAY, m_nid.szTip, sizeof(m_nid.szTip))) { m_nid.uFlags |= NIF_TIP; } return (bool) (Shell_NotifyIcon(msg, &m_nid) != 0);}// Process window messagesLRESULT CALLBACK Daemon::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { // This is a static method, so we don't know which instantiation we're // dealing with. We have stored a pseudo-this in the window user data, // though. Daemon *_this = (Daemon *) GetWindowLong(hwnd, GWL_USERDATA); switch (iMsg) { case WM_CREATE: { return 0; } case WM_SOCKEVENT: { assert(HIWORD(lParam) == 0); // A new socket created by accept might send messages to // this procedure. We can ignore them. if(wParam != _this->m_sock) { return 0; } switch(lParam) { case FD_ACCEPT: { SOCKET hNewSock; hNewSock = accept(_this->m_sock, NULL, NULL); WSAAsyncSelect(hNewSock, hwnd, 0, 0); unsigned long nbarg = 0; ioctlsocket(hNewSock, FIONBIO, &nbarg); pApp->NewConnection(hNewSock); break; } case FD_READ: { unsigned long numbytes; ioctlsocket(_this->m_sock, FIONREAD, &numbytes); recv(_this->m_sock, _this->netbuf, numbytes, 0); break; } case FD_CLOSE: log.Print(5, _T("Daemon connection closed\n")); DestroyWindow(hwnd); break; } return 0; } case WM_COMMAND: switch (LOWORD(wParam)) { case ID_NEWCONN: pApp->NewConnection(); break; case IDC_OPTIONBUTTON: pApp->m_options.DoDialog(); break; case ID_CLOSEDAEMON: PostQuitMessage(0); break; case IDD_APP_ABOUT: ShowAboutBox(); break; } return 0; case WM_TRAYNOTIFY: { HMENU hSubMenu = GetSubMenu(_this->m_hmenu, 0); if (lParam==WM_LBUTTONDBLCLK) { // double click: execute first menu item ::SendMessage(_this->m_nid.hWnd, WM_COMMAND, GetMenuItemID(hSubMenu, 0), 0); } else if (lParam==WM_RBUTTONUP) { if (hSubMenu == NULL) { log.Print(2, _T("No systray submenu\n")); return 0; } // Make first menu item the default (bold font) ::SetMenuDefaultItem(hSubMenu, 0, TRUE); // Display the menu at the current mouse location. There's a "bug" // (Microsoft calls it a feature) in Windows 95 that requires calling // SetForegroundWindow. To find out more, search for Q135788 in MSDN. // POINT mouse; GetCursorPos(&mouse); ::SetForegroundWindow(_this->m_nid.hWnd); ::TrackPopupMenu(hSubMenu, 0, mouse.x, mouse.y, 0, _this->m_nid.hWnd, NULL); } return 0; } case WM_TIMER: _this->CheckTrayIcon(); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, iMsg, wParam, lParam);}Daemon::~Daemon(){ KillTimer(m_hwnd, m_timer); RemoveTrayIcon(); DestroyMenu(m_hmenu); shutdown(m_sock, SD_BOTH); closesocket(m_sock);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -