1. 程式人生 > >一個虛擬桌面程式的實現

一個虛擬桌面程式的實現

        前幾天為朋友寫了一個小工具,主要是為了做到一鍵隱藏大智慧炒股軟體,第一個版本是利用視窗查詢,然後向視窗傳送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) ;

}