虛擬一個案頭,然後在虛擬桌面啟動explorer進程,使用者可以用"ALT+Q"來切換現有案頭與這個虛擬桌面,使用者需要運行什麼軟體,自己在虛擬桌面開啟就是了。原理很簡單,實現同樣也很簡單,下面是代碼:
#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) ;
}