一個虛擬桌面程式的實現
阿新 • • 發佈:2019-01-09
前幾天為朋友寫了一個小工具,主要是為了做到一鍵隱藏大智慧炒股軟體,第一個版本是利用視窗查詢,然後向視窗傳送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) ; }