发布时间:2025-12-09 21:10:21 浏览次数:4
转载请标明是引用于 http://blog.csdn.net/chenyujing1234
MsgWindow的构造函数就是创建一个窗口,窗口名称为"VNCTray",大小为10*10;
TrayIcon() : MsgWindow(_T("VNCTray")) {#ifdef NOTIFYICONDATA_V1_SIZEnid.cbSize = NOTIFYICONDATA_V1_SIZE;#elsenid.cbSize = sizeof(NOTIFYICONDATA);#endifnid.hWnd = getHandle();nid.uID = 0;nid.hIcon = 0;nid.uFlags = NIF_ICON | NIF_MESSAGE;nid.uCallbackMessage = WM_USER;}第三个构造函数:STrayIcon构造函数
STrayIcon(STrayIconThread& t) : thread(t),vncConfig(_T("vncconfig.exe"), isServiceProcess() ? _T("-noconsole -service") : _T("-noconsole")),vncConnect(_T("winvnc4.exe"), _T("-connect")) {// ***SetWindowText(getHandle(), _T("winvnc::IPC_Interface"));// ***SetTimer(getHandle(), 1, 3000, 0);PostMessage(getHandle(), WM_TIMER, 1, 0);PostMessage(getHandle(), WM_SET_TOOLTIP, 0, 0);}首先构造两对象
LaunchProcess vncConfig;LaunchProcess vncConnect;作用:在窗口收到消息WM_COMMAND,命令为ID_CONNECT时就连接服务端: CurrentUserToken token;if (token.isValid())vncConnect.start(isServiceProcess() ? (HANDLE)token : 0);elsevlog.error("Options: unknown current user"); void LaunchProcess::start(HANDLE userToken) {if (procInfo.hProcess && (WaitForSingleObject(procInfo.hProcess, 0) != WAIT_OBJECT_0))return;await();// - Create storage for the process startup informationSTARTUPINFO sinfo;memset(&sinfo, 0, sizeof(sinfo));sinfo.cb = sizeof(sinfo);// - Concoct a suitable command-lineTCharArray exePath;if (!tstrContains(exeName.buf, _T('\\'))) {ModuleFileName filename;TCharArray path; splitPath(filename.buf, &path.buf, 0);exePath.buf = new TCHAR[_tcslen(path.buf) + _tcslen(exeName.buf) + 2];_stprintf(exePath.buf, _T("%s\\%s"), path.buf, exeName.buf);} else {exePath.buf = tstrDup(exeName.buf);}// - Start the VNC server// Note: We specify the exe's precise path in the ApplicationName parameter,// AND include the name as the first part of the CommandLine parameter,// because CreateProcess doesn't make ApplicationName argv[0] in C programs.TCharArray cmdLine(_tcslen(exeName.buf) + 3 + _tcslen(params.buf) + 1);_stprintf(cmdLine.buf, _T("\"%s\" %s"), exeName.buf, params.buf);#ifdef _DEBUGDWORD flags = CREATE_NEW_CONSOLE;#elseDWORD flags = CREATE_NO_WINDOW;#endifBOOL success;if (userToken)success = CreateProcessAsUser(userToken, exePath.buf, cmdLine.buf, 0, 0, FALSE, flags, 0, 0, &sinfo, &procInfo);elsesuccess = CreateProcess(exePath.buf, cmdLine.buf, 0, 0, FALSE, flags, 0, 0, &sinfo, &procInfo);if (!success)throw rdr::SystemException("unable to launch process", GetLastError());// Wait for it to finish initialisingWaitForInputIdle(procInfo.hProcess, 15000);}然后,设置窗口名称为_T("winvnc::IPC_Interface"
然后开启定时器1,每3S触发一次;
最后给窗口发送WM_TIMER与WM_SET_TOOLTIP消息;
作用:WM_TIMER用于刷新图标状态
如果桌面不是输入桌面,那么就把图标关闭,如果(“当前桌面和名称”与"输入桌面名称“是否一致来判断);
如果桌面还是存在那么更新当前的图标状态。(激活或非激活)
if (rfb::win32::desktopChangeRequired()) {SendMessage(getHandle(), WM_CLOSE, 0, 0);return 0;}setIcon(thread.server.isServerInUse() ? thread.activeIcon : thread.inactiveIcon);return 0;WM_SET_TOOLTIP用于设置”工具提示信息“ case WM_SET_TOOLTIP:{rfb::Lock l(thread.lock);if (thread.toolTip.buf)setToolTip(thread.toolTip.buf);}
缩写为TLS。进程中的全局变量与函数内定义的静态(static)变量,是各个线程都可以访问的共享变量。在一个线程修改的内存内容,对所有线程都生效。这是一个优点也是一个缺点。说它是优点,线程的数据交换变得非常快捷。说它是缺点,一个线程死掉了,其它线程也性命不保; 多个线程访问共享数据,需要昂贵的同步开销,也容易造成同步相关的BUG。
如果需要在一个线程内部的各个 函数调用都能访问、但其它线程不能访问的 变量(被称为static memory local to a thread 线程局部 静态变量),就需要新的机制来实现。这就是TLS。 线程局部存储在不同的平台有不同的实现,可移植性不太好。幸好要实现 线程局部存储并不难,最简单的办法就是建立一个全局表,通过当前线程ID去查询相应的数据,因为各个线程的ID不同,查到的数据自然也不同了。 Win32 方法一:每个线程创建时系统给它分配一个 LPVOID指针的数组(叫做TLS数组),这个数组从C编程角度是隐藏着的不能直接访问,需要通过一些C API函数调用访问。首先定义 一些DWORD线程 全局变量或函数静态 变量,准备作为各个线程访问自己的TLS 数组的 索引变量。一个 线程使用TLS时,第一步在线程内调用TlsAlloc()函数, 为一个TLS数组索引变量与这个线程的TLS数组的某个槽(slot)关联起来,例如获得一个索引变量: global_dwTLSindex=TLSAlloc(); 注意,此步之后,当前线程实际**问的是这个TLS 数组索引变量的线程内的拷贝版本。也就说,不同线程虽然看起来用的是同名的TLS 数组索引变量,但实际上各个线程得到的可能是不同DWORD值。其意义在于,每个使用TLS的 线程获得了一个DWORD类型的 线程局部静态变量作为TLS 数组的索引变量。C/C++原本没有直接定义 线程局部静态变量的机制,所以在如此大费周折。 第二步,为当前线程动态分配一块内存区域(使用LocalAlloc() 函数调用),然后把指向这块内存区域的 指针放入TLS 数组相应的槽中(使用TlsValue()函数调用)。 第三步,在当前线程的任何函数内,都可以通过TLS 数组的索引变量,使用TlsGetValue()函数得到上一步的那块内存区域的 指针,然后就可以进行内存区域的读写操作了。这就实现了在一个线程内部这个范围处处可访问的变量。 最后,如果不再需要上述线程局部静态变量,要动态释放掉这块内存区域(使用LocalFree()函数),然后从TLS 数组中放弃对应的槽(使用TlsFree()函数)。 在VNC-4.0-winsrc开源代码中看到,它用了TSL的方法: (1)定义 static DWORD threadStorage = TlsAlloc(); 为一个TLS数组索引变量与这个线程的TLS数组的某个槽(slot)关联起来,例如获得一个索引变量: (2)设置值 WINBASEAPIBOOLWINAPITlsSetValue(__in DWORD dwTlsIndex,__in_opt LPVOID lpTlsValue);