一个虚拟桌面程序的实现
2008-06-17 10:02
288 查看
前几天为朋友写了一个小工具,主要是为了做到一键隐藏大智慧炒股软件,第一个版本是利用窗口查找,然后向窗口发送WM_SHOW消息完成的。实现原理虽然简单,但是不具备通用性,按我最初的设想要一键隐藏什么软件应该由用户定义,而不是每次都要定制。于是这个小工具的第二个版本诞生了,那就是为用户虚拟一个桌面,然后在虚拟桌面启动explorer进程,用户可以用"ALT+Q"来切换现有桌面与这个虚拟桌面,用户需要运行什么软件,自己在虚拟桌面打开就是了。原理很简单,实现同样也很简单,下面是代码:
/******************************************************************************* Module: SunBear.cpp Date: 2008/06/13 Notice: Copyright (C) 2008 常海龙 *******************************************************************************/ #include<afxwin.h> HINSTANCE hInst; //当前实例 TCHAR szAppName[] = TEXT ("VirtualDesk") ; //程序名称 HWND hwnd ; //主窗体句柄 HDESK hVirtualDesk; //虚拟桌面句柄 HDESK hCurrent; //当前桌面句柄 PROCESS_INFORMATION piExplor; //Explorer进程的PROCESS_INFORMATION结构 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); //每次运行首先检测注册表相关項,如果未发现,则设置开机自动运行 void SetStartup(HINSTANCE hInst) { HKEY hKey; DWORD DataType = REG_SZ; PCSTR data_run = "Software//Microsoft//Windows//CurrentVersion//Run"; long ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,data_run,0,KEY_ALL_ACCESS,&hKey); if(ret != ERROR_SUCCESS) { MessageBox(NULL,"无法打开注册表键","Error",0); return; } CString ProcessName; int len = GetModuleFileName(hInst,ProcessName.GetBuffer(256),256); if(len == 0) { MessageBox(NULL,"无法获取进程的当前目录","Error",0); return; } ProcessName.ReleaseBuffer(len); DWORD direcLen = ProcessName.GetLength() + 1; LPBYTE direc = new BYTE[direcLen]; ZeroMemory(direc,direcLen); ret = RegQueryValueEx(hKey,"VirtualDesk",0,0,direc,&direcLen); //如果键不存在或者键长度与目前的值长度不匹配则添加新键 if((ret != ERROR_SUCCESS )|| (direcLen != ProcessName.GetLength()+1)) { SetValue: DWORD KeyLength = ProcessName.GetLength() + 1; LPBYTE KeyValue = new BYTE[KeyLength]; ZeroMemory(KeyValue,KeyLength); for(int i=0;i<ProcessName.GetLength();i++) KeyValue[i] = ProcessName[i]; KeyValue[ProcessName.GetLength()] = 0; ret = RegSetValueEx(hKey,"VirtualDesk",0,REG_SZ,KeyValue,KeyLength); delete []KeyValue; } else { //如果键的内容与当前值不匹配同样进行更改 for(int i=0;i<ProcessName.GetLength();i++) { if(direc[i] != ProcessName[i]) goto SetValue; } } delete []direc; return; } //创建explorer进程的函数,如果创建了一个虚拟桌面,那么最好调用该函数 void StartExplorer() { STARTUPINFO si; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); si.lpDesktop = "Virtual"; ZeroMemory( &piExplor, sizeof(piExplor) ); if( !CreateProcess( NULL, // No module name (use command line). "explorer", // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. 0, // No creation flags. NULL, // Use parent's environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &piExplor ) // Pointer to PROCESS_INFORMATION structure. ) { MessageBox(NULL,"无法初始化Explorer","Error",0); ExitProcess(1); } } ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szAppName; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_APPLICATION); return RegisterClassEx(&wcex); } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // 将实例句柄存储在全局变量中 hwnd = CreateWindow(szAppName, TEXT ("SunBear"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL); if (!hwnd) { return FALSE; } return TRUE; } int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("SunBear") ; MSG msg ; SetStartup(hInstance); hVirtualDesk = CreateDesktop( "Virtual", NULL, NULL, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, NULL); hCurrent = GetThreadDesktop(GetCurrentThreadId()); MyRegisterClass(hInstance); if (!InitInstance (hInstance, iCmdShow)) { return FALSE; } StartExplorer(); //启动Explorer进程 if(!RegisterHotKey(hwnd, 0x0001,MOD_ALT ,'Q')) { //处理切换虚拟桌面 return TRUE; } if(!RegisterHotKey(hwnd, 0x0002, 0,VK_F8)) { //处理退出进程 return TRUE; } while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return 0; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc ; PAINTSTRUCT ps ; static HDESK hNow = hCurrent; switch (message) { case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: //在关闭虚拟桌面前要切换回当前桌面 SwitchDesktop(hCurrent); PostQuitMessage (0) ; return 0 ; case WM_HOTKEY: if(0x0001 == wParam) { if(hNow == hCurrent) { SwitchDesktop(hVirtualDesk); hNow = hVirtualDesk; } else { SwitchDesktop(hCurrent); hNow = hCurrent; } } if(0x0002 == wParam) { //用TerminateProcess终止explorer进程的时候,如果传递第二个参数为1 //那么操作系统不会在终止后自动唤醒explorer,如果为0,会重新启动 //explorer TerminateProcess(piExplor.hProcess,1); //关闭虚拟桌面 CloseDesktop(hVirtualDesk); SendMessage(hwnd,WM_CLOSE,0,0); } return 0; } return DefWindowProc (hwnd, message, wParam, lParam) ; }
相关文章推荐
- 使用API实现的一个增加系统桌面,并且可以任意切换的小程序.
- 用Qt实现一个桌面弹幕程序(十)-- -- 网页服务端的实现①
- win8 程序发送组合虚拟键值,不能实现桌面切换
- 用Qt实现一个桌面弹幕程序(九)-- -- 服务端的实现
- 来用Qt实现一个桌面弹幕程序吧
- 用Qt实现一个桌面弹幕程序(二)--实现一个弹幕①
- 用Qt实现一个桌面弹幕程序(八)-- -- 桌面客户端实现④
- 用Qt实现一个桌面弹幕程序(一)--前期准备
- 用Qt实现一个桌面弹幕程序(三)--实现一个弹幕②
- 用Qt实现一个桌面弹幕程序(五)-- -- 桌面客户端实现①
- 用Qt实现一个桌面弹幕程序(七)-- -- 桌面客户端实现③
- 只允许允许一个程序实例,即使是通过虚拟桌面方式连接过来的,也是只允许一个人运行。
- 用Qt实现一个桌面弹幕程序(六)-- -- 桌面客户端实现②
- 用Qt实现一个桌面弹幕程序(四)--实现一个弹幕③
- 只允许允许一个程序实例,即使是通过虚拟桌面方式连接过来的,也是只允许一个人运行。
- 分析一个小程序的实现
- 综合实例:用C语言实现一个自定义的shell程序
- 一个实现不记名投票的小程序
- 仅允许程序运行一个实例代码实现
- 用QML实现一个调色程序