1. 程式人生 > >建立一個簡易的虛擬桌面

建立一個簡易的虛擬桌面

文字性的描述留到後續文章再交代,還是先放一個小小的'大招',畢竟眼鏡看見的東西,比起抽象的東西,更能引起初學者的注意,

如果你對這個感興趣的話,這裡有個連結,你可以去看看,

1.用vs2013建立一個空專案,新增一個cpp檔案,

#include<windows.h>
TCHAR szAppName[] = TEXT("TEST");		//視窗類名
#define DESTOP_NAME  TEXT("MY_DESTOP")	//定義我要建立的桌面名稱

ATOM m_HotKeyId1;			//用於註冊ctrl+shift+F6  ,切換到原來的活動桌面
ATOM m_HotKeyId2;			//用於註冊ctrl+shift+F7	,將活動桌面切換到我們新建立的桌面,
ATOM m_HotKeyId3;			//用於正確退出程式,因為程式沒有相應介面且需要釋放一些資源
HDESK hDDesk;

HWINSTA  hWinStaThisProcess = GetProcessWindowStation( );			//程式執行起來,獲取系統為該程序設定的預設互動工作站
HDESK hDeskOriignInput = OpenInputDesktop(0,FALSE,GENERIC_ALL);		//程式執行起來,獲取系統為該執行緒設定的預設活動桌面
void OnHotKey(WPARAM wParam,LPARAM lParam)
{
	static 
	LRESULT lRes = 0;

	if(wParam == m_HotKeyId1)//熱鍵1被按下
	{
		// 該熱鍵按下時的處理
		SwitchDesktop(hDeskOriignInput);	//原活動桌面被顯現出來
		//MessageBox(0,TEXT("F6"),0,0);
	}
	else if(wParam == m_HotKeyId2)//熱鍵2被按下
	{
		SwitchDesktop(hDDesk);				//我們建立的桌面顯現出來
		//MessageBox(0,TEXT("F7"),0,0);
	}
	else if(wParam == m_HotKeyId3)//熱鍵2被按下
	{
		MessageBox(0,TEXT("程式退出"),0,0);
		PostQuitMessage(0);			//我們建立的桌面顯現出來
		//MessageBox(0,TEXT("F7"),0,0);
	}
	return ;
}
LRESULT		CALLBACK	WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
	switch(message)
	{
		case WM_HOTKEY:
		OnHotKey(wParam,lParam);
		return 0;
	}
	return DefWindowProc(hwnd,message,wParam,lParam);
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
	HWND hwnd;
	MSG	 msg;
	WNDCLASS	wndclass;

	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = szAppName;

	if(!RegisterClass(&wndclass))
	{
		MessageBox(NULL,TEXT("視窗註冊失敗!"),NULL,0);
		return 0;
	}
	hwnd = CreateWindow(
		szAppName,szAppName,
		WS_OVERLAPPEDWINDOW,
		0,0,
		0,0,
		NULL,NULL,hInstance,NULL
		);


<span style="white-space:pre">	</span>//在程序 預設的互動式工作站中建立 桌面,
	hDDesk = CreateDesktop(
		DESTOP_NAME,
		0,0,0,
		GENERIC_ALL,
		NULL
		);
	//設定與本執行緒相聯絡的桌面為 我們建立的桌面
	SetThreadDesktop(hDDesk);

	//填寫STARTUPINFO 結構體資訊,注意與平常建立程序的不同,這裡有了lpDesktop選項的設定,
	STARTUPINFO sti = {
		sizeof(sti)
	};
	sti.lpDesktop = DESTOP_NAME;

	PROCESS_INFORMATION pi = {0};
	CreateProcess(
		TEXT("C:\\Windows\\explorer.exe"),NULL,NULL,NULL,TRUE,0,NULL,NULL,&sti,&pi
		);

	/****************************************************************
				註冊3個熱鍵
	******************************************************************/

	//在全域性原子表中新增一項字串得到id一個,這一項跟   CTRL +SHIFT+F6 有關
	m_HotKeyId1 = GlobalAddAtomW(TEXT("HotKey1")) - 0xc000;
	//註冊得到的id與 熱鍵CTRL+SHIFT+F6 關聯起來
	RegisterHotKey(hwnd,m_HotKeyId1,MOD_CONTROL | MOD_SHIFT,VK_F6);

	//在全域性原子表中新增一項字串得到id一個,這一項跟   CTRL +SHIFT+F7 有關
	m_HotKeyId2 = GlobalAddAtomW(TEXT("HotKey2")) - 0xc000;
	//註冊得到的id與 熱鍵CTRL+SHIFT+F7 關聯起來
	RegisterHotKey(hwnd,m_HotKeyId2,MOD_CONTROL | MOD_SHIFT,VK_F7);


	//在全域性原子表中新增一項字串得到id一個,這一項跟   F7 有關
	m_HotKeyId3 = GlobalAddAtomW(TEXT("HotKey3")) - 0xc000;
	//註冊得到的id與 熱鍵F7 關聯起來
	RegisterHotKey(hwnd,m_HotKeyId3,0,VK_F7);


	/**********************************************************
	***********************************************************/


	//視窗訊息迴圈
	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	//F7 熱鍵按下,即退出,順便清理資源
	UnregisterHotKey(hwnd,m_HotKeyId1);
	GlobalDeleteAtom(m_HotKeyId1);

	UnregisterHotKey(hwnd,m_HotKeyId2);
	GlobalDeleteAtom(m_HotKeyId2);

	UnregisterHotKey(hwnd,m_HotKeyId3);
	GlobalDeleteAtom(m_HotKeyId3);

	CloseHandle(hDDesk);
	return msg.wParam;
}



2.可能會遇見的問題,

2.1SwitchDesktop失敗,GetLastError ()  返回  error_access_dinied   這個錯誤通常跟管理員許可權沒提權有關,但是這裡不是這樣的,

而是, 1.你建立的桌面不在互動工作站中, 

在這之前你得知道 你的程式, 系統預設給其對應的程序 關聯到   一個   互動式工作站,

2.怎樣將建立的桌面跟工作站產生   包含的邏輯關係   呢? 

通過  給程序SetProcessWinstation()關聯工作站  ,(這裡省略了這一步,因為我已經知道,程序和工作站的關聯關係了)

給執行緒SetThreadDesktop() 關聯桌面,這樣一來,

二者的關係是不是可以想象出有了聯絡了呢?

這裡的兩個函式忽略了引數,要是你有興趣的話可以看看下面msdn連結的解釋

該頁面給出的是一族windows api,這些api都比較好理解

2.2,           64位系統下,用vs2013 64位編譯的方式編譯,32位系統下,程式用32位編譯方式

2.3

STARTUPINFO sti = {
sizeof(sti)
};
sti.lpDesktop = DESTOP_NAME;

若是第一次啟動了這個程式的話,將會生成一個explorer.exe程序,此時若是在工作管理員中檢視,有2個explorer程序,若是關閉我們的程式,這個2explorer程序個不會受到
影響,當第二次執行我們的程式時,(未關機),會發現視窗2中的東西和之前一樣,沒有變化