Flasher.cpp
上传用户:sbftbdw
上传日期:2007-01-03
资源大小:379k
文件大小:8k
源码类别:

远程控制编程

开发平台:

Visual C++

  1. //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  2. //
  3. //  This file is part of the VNC system.
  4. //
  5. //  The VNC system is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  18. //  USA.
  19. //
  20. // If the source code for the VNC system is not available from the place 
  21. // whence you received this file, check http://www.orl.co.uk/vnc or contact
  22. // the authors on vnc@orl.co.uk for information on obtaining it.
  23. // Flasher.cpp: implementation of the Flasher class.
  24. #include "stdhdrs.h"
  25. #include "vncviewer.h"
  26. #include "Flasher.h"
  27. #include "Exception.h"
  28. //////////////////////////////////////////////////////////////////////
  29. // Construction/Destruction
  30. //////////////////////////////////////////////////////////////////////
  31. #define FLASHER_CLASS_NAME "VNCviewer Flasher"
  32. #define FLASHFONTHEIGHT 80
  33. Flasher::Flasher(int port)
  34. {
  35. // Create a dummy window.  We don't use it for anything except
  36. // receiving socket events, so a seperate listening thread would
  37. // probably be easier!
  38. WNDCLASSEX wndclass;
  39. wndclass.cbSize = sizeof(wndclass);
  40. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  41. wndclass.lpfnWndProc = Flasher::WndProc;
  42. wndclass.cbClsExtra = 0;
  43. wndclass.cbWndExtra = 0;
  44. wndclass.hInstance = pApp->m_instance;
  45. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  46. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  47. wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  48. wndclass.lpszMenuName = (const char *) NULL;
  49. wndclass.lpszClassName = FLASHER_CLASS_NAME;
  50. wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  51. RegisterClassEx(&wndclass);
  52. m_hwnd = CreateWindow(FLASHER_CLASS_NAME,
  53. FLASHER_CLASS_NAME,
  54. WS_OVERLAPPEDWINDOW,
  55. CW_USEDEFAULT,
  56. CW_USEDEFAULT,
  57. 200, 200,
  58. NULL,
  59. NULL,
  60. pApp->m_instance,
  61. NULL);
  62. // record which client created this window
  63. SetWindowLong(m_hwnd, GWL_USERDATA, (LONG) this);
  64. // Select a font for displaying user name
  65. LOGFONT lf;
  66. memset(&lf, 0, sizeof(lf));
  67. lf.lfHeight = FLASHFONTHEIGHT;
  68. lf.lfWeight = FW_BOLD;
  69. lf.lfItalic = 1;
  70. lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
  71. lf.lfFaceName[0] = '';
  72. m_hfont = CreateFontIndirect(&lf);
  73. if (m_hfont == NULL) {
  74. log.Print(1, _T("FAILED TO SELECT FLASHER FONT!n"));
  75. }
  76. // Create a listening socket
  77.     struct sockaddr_in addr;
  78.     addr.sin_family = AF_INET;
  79.     addr.sin_port = htons(port);
  80.     addr.sin_addr.s_addr = INADDR_ANY;
  81.     m_sock = socket(AF_INET, SOCK_STREAM, 0);
  82. if (!m_sock) throw WarningException("Error creating Flasher socket");
  83.     
  84. try {
  85. int one = 1, res = 0;
  86. // If we use the SO_REUSEADDR option then you can run multiple daemons
  87. // because the bind doesn't return an error.  Only one gets the accept,
  88. // but when that process dies it hands back to another.  This may or may
  89. // not be desirable.  We don't use it.
  90. //int res = setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &one, sizeof(one));
  91. //if (res == SOCKET_ERROR) 
  92. // throw WarningException("Error setting Flasher socket options");
  93. res = bind(m_sock, (struct sockaddr *)&addr, sizeof(addr));
  94. if (res == SOCKET_ERROR)
  95. throw WarningException("Error binding Flasher socket");
  96. res = listen(m_sock, 5);
  97. if (res == SOCKET_ERROR)
  98. throw WarningException("Error when Flasher tries to listen");
  99. } catch (...) {
  100. closesocket(m_sock);
  101. m_sock = 0;
  102. throw;
  103. }
  104. // Send a message to specified window on an incoming connection
  105. WSAAsyncSelect (m_sock,  m_hwnd,  WM_SOCKEVENT, FD_ACCEPT | FD_CLOSE);
  106. }
  107. // convert a lower-case ASCII char to a value 0-255
  108. inline int scalechar(char c) {
  109. return ( ((c - 'a')+4) & 0x1f ) * 255 / 0x1f;
  110. }
  111. // We use this on each screen saver window running
  112. BOOL CALLBACK KillScreenSaverFunc(HWND hwnd, LPARAM lParam)   {
  113. PostMessage(hwnd, WM_CLOSE, 0, 0); 
  114. return TRUE; 
  115. }
  116. // Process window messages
  117. LRESULT CALLBACK Flasher::WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
  118. // This is a static method, so we don't know which instantiation we're 
  119. // dealing with. We use Allen Hadden's (ahadden@taratec.com) suggestion 
  120. // from a newsgroup to get the pseudo-this.
  121. Flasher *_this = (Flasher *) GetWindowLong(hwnd, GWL_USERDATA);
  122. switch (iMsg) {
  123. case WM_CREATE:
  124. return 0;
  125. case WM_SOCKEVENT:
  126. {
  127. assert(HIWORD(lParam) == 0);
  128. // A new socket created by accept might send messages to
  129. // this procedure. We can ignore them.
  130. if(wParam != _this->m_sock) {
  131. return 0;
  132. }
  133. switch(lParam) {
  134. case FD_ACCEPT:
  135. {
  136. SOCKET hNewSock;
  137. char username[256];
  138. hNewSock = accept(_this->m_sock, NULL, NULL);
  139. // make it blocking
  140. WSAAsyncSelect(hNewSock, hwnd, 0, 0);
  141. u_long blk = 0;
  142. int res = ioctlsocket(hNewSock, FIONBIO, &blk);
  143. assert(res == 0);
  144. CloseScreenSaver();
  145. // Se if the server's sending a user name
  146. int namelen = recv(hNewSock, username, 250, 0);
  147. if (namelen >= 0) 
  148. username[namelen] = 0;
  149. log.Print(2, _T("Flash for '%s'n"), username);
  150. closesocket(hNewSock);
  151. // flash
  152. // Get a DC for the root window
  153. HDC hrootdc = ::GetDC(NULL);
  154. HBRUSH holdbrush = (HBRUSH) SelectObject(hrootdc, 
  155. (HBRUSH) GetStockObject(BLACK_BRUSH));
  156. // Find the size.
  157. RECT rect;
  158. GetClipBox(hrootdc, &rect);
  159. int barwidth = (rect.right - rect.left) / 10;
  160. int barheight = max( 
  161. (rect.bottom - rect.top) / 10,
  162. FLASHFONTHEIGHT);
  163. HFONT oldfont = (HFONT) SelectObject(hrootdc, _this->m_hfont);
  164. // Flash the screen
  165. ::Beep(440,50);
  166. Rectangle(hrootdc, rect.left, rect.top, 
  167.   rect.right, barheight);
  168. Rectangle(hrootdc, rect.left,  rect.bottom-barheight, 
  169.   rect.right, rect.bottom);
  170. Rectangle(hrootdc, rect.left,  rect.top+barheight, 
  171.   barwidth, rect.bottom-barheight);
  172. Rectangle(hrootdc, rect.right-barwidth, rect.top+barheight, 
  173.   rect.right, rect.bottom-barheight);
  174. RECT topbar;
  175. SetRect(&topbar, rect.left, rect.top, 
  176.   rect.right, barheight);
  177. int i = 0;
  178. if (namelen > 0) {
  179. int oldmode = SetBkMode(hrootdc, TRANSPARENT);
  180. COLORREF oldcolor = SetTextColor(hrootdc, 
  181. RGB(scalechar(username[0])/(i+1), scalechar(username[1])/(i+1), scalechar(username[2])/(i+1)));
  182. DrawText(hrootdc, username, -1, &topbar, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  183. SetTextColor(hrootdc, oldcolor);
  184. SetBkMode(hrootdc, oldmode);
  185. }
  186. GdiFlush();
  187. SelectObject(hrootdc, holdbrush);
  188. ::Sleep(1000);
  189. SelectObject(hrootdc, oldfont);
  190. InvalidateRect(0, &rect, TRUE);
  191. ::ReleaseDC(NULL, hrootdc);
  192. break;
  193. }
  194. case FD_CLOSE:
  195. log.Print(2, _T("Flasher connection closedn"));
  196. DestroyWindow(hwnd);
  197. break;
  198. }
  199. return 0;
  200. }
  201. case WM_DESTROY:
  202. PostQuitMessage(0);
  203. return 0;
  204. }
  205. return DefWindowProc(hwnd, iMsg, wParam, lParam);
  206. }
  207. void Flasher::CloseScreenSaver() {
  208. // Which OS are we on?
  209. OSVERSIONINFO ovi;
  210. ovi.dwOSVersionInfoSize = sizeof(ovi);
  211. if (!GetVersionEx(&ovi)) return;
  212. switch (ovi.dwPlatformId) {
  213. case VER_PLATFORM_WIN32_WINDOWS:
  214. {
  215. // Windows 95
  216. HWND hsswnd = FindWindow ("WindowsScreenSaverClass", NULL);
  217. if (hsswnd != NULL)
  218. PostMessage(hsswnd, WM_CLOSE, 0, 0); 
  219. break;
  220. case VER_PLATFORM_WIN32_NT:
  221. {
  222. // Windows NT
  223. HDESK hdesk = OpenDesktop(
  224. TEXT("Screen-saver"),                       
  225. 0, FALSE, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS);
  226. if (hdesk) {
  227.                 if (EnumDesktopWindows(hdesk, (WNDENUMPROC) KillScreenSaverFunc, 0)) {
  228.     CloseDesktop(hdesk);
  229.                 }
  230.                 Sleep(1000);
  231. }
  232. }
  233. }
  234. }
  235. Flasher::~Flasher()
  236. {
  237. shutdown(m_sock, SD_BOTH);
  238. closesocket(m_sock);
  239. if (m_hfont != NULL) DeleteObject(m_hfont);
  240. }