创建一个简易的虚拟桌面

文字性的描述留到后续文章再交代,还是先放一个小小的'大招',毕竟眼镜看见的东西,比起抽象的东西,更能引起初学者的注意,

如果你对这个感兴趣的话,这里有个链接,你可以去看看,

<<白话windows之 会话、工作站、桌面、窗口之间的关系>>
                 http://bbs.pediy.com/showthread.php?t=173271


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链接的解释

Window Station and Desktop Functions

该页面给出的是一族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中的东西和之前一样,没有变化

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值