windows虚拟多桌面技术

Windows 10 发布后,微软终于在自家的操作系统里面内置了虚拟桌面功能,而这是 macOS 上早已标配的功能。

        这个功能确实有很强的需求,在没有虚拟桌面之前,对于主力设备是 Windows 的我来说,经常要频繁切换浏览器、日历软件、任务管理软件、聊天软件和邮件客户端……的窗口。窗口之间的重合交叠让人感到「邋遢」和不爽:

窗口重合交叠的屏幕

可以用windows的SysinternalsSuite工具包里面的Desktops.exe进行虚拟桌面的创建:

 

 

虚拟桌面能干什么

每个虚拟桌面可以被看成是一个独立的工作空间(Workspace)。

每创建一个虚拟桌面,就像打开了一个新的工作空间。在新的空间中,你能够开启一套完全不同的任务,而不用担心和以前的任务窗口混杂陈列。

创建的每个桌面是相互隔离的,也就是说如果一个程序如果实在无法隐藏程序界面,可以单独创建一个桌面并将程序的界面Switch过去即可,这样就可以“偷偷”在后台工作了。当然我们在做windows本地桌面应用的时候也可以利用多桌面技术,比如可以开辟一个干净的“桌面”进行一些私密的工作(比如玩游戏),之后可以快速的切换回来假装什么都没做 :) 

话不多说,下面是windows多桌面创建的代码:

// desktop.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"

#include <string>
#include <Windows.h>
#include <wininet.h>
#include <shlobj.h>
#include <AclAPI.h>
#include <UserEnv.h>
#include <WtsApi32.h>
#include <Sddl.h>

#define VIR_DESKTOP	L"VirDesktop"
#define SYSTEM_DEFAULT_DESKTOP	L"default"

#define I_WALLPAPER_STYTLE_NO_CHANGE	-1
#define I_WALLPAPER_STYTLE_CENTER		0	//居中
#define I_WALLPAPER_STYTLE_TILE			1	//平铺
#define I_WALLPAPER_STYTLE_STRETCH		2	//拉伸

bool set_desktop_picture(const std::wstring& str_img_path, int i_option, bool b_save)
{
	HRESULT hr = S_FALSE;
	hr = CoInitialize(NULL);
	bool b_inited_ok = false;
	if (hr == S_OK)
	{
		b_inited_ok = true;
	}
	IActiveDesktop* pIAD = NULL;
	hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pIAD);
	if (FAILED(hr))
	{
		if (b_inited_ok)
			CoUninitialize();
		return false;
	}

	hr = pIAD->SetWallpaper(str_img_path.c_str(), 0);

	if (FAILED(hr))
	{
		pIAD->Release();
		if (b_inited_ok)
			CoUninitialize();
		return false;
	}

	if (i_option > 0)
	{
		WALLPAPEROPT wp = { 0 };
		wp.dwSize = sizeof(WALLPAPEROPT);
		wp.dwStyle = i_option;
		hr = pIAD->SetWallpaperOptions(&wp, 0);
	}

	if (b_save)
	{
		hr = pIAD->ApplyChanges(AD_APPLY_ALL);
	}
	else
	{
		hr = pIAD->ApplyChanges(AD_APPLY_REFRESH);
	}

	if (FAILED(hr))
	{
		pIAD->Release();
		if (b_inited_ok)
			CoUninitialize();
		return false;
	}

	pIAD->Release();
	if (b_inited_ok)
		CoUninitialize();

	return true;
}

bool set_desktop_picture(const std::wstring& str_img_path, std::wstring& str_old_img_path, int& i_old_option, int i_option, bool b_save)
{
	i_old_option = I_WALLPAPER_STYTLE_NO_CHANGE;
	str_old_img_path.clear();

	HRESULT hr = S_FALSE;
	bool b_inited_ok = false;
	hr = CoInitialize(NULL);
	if (hr == S_OK)
	{
		b_inited_ok = true;
	}
	IActiveDesktop* pIAD = NULL;
	hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pIAD);
	if (FAILED(hr))
	{
		if (b_inited_ok)
			CoUninitialize();
		return false;
	}

	wchar_t img[4096] = { 0 };
	hr = pIAD->GetWallpaper(img, 4096, AD_GETWP_LAST_APPLIED);
	if (FAILED(hr))
	{
		pIAD->Release();
		if (b_inited_ok)
			CoUninitialize();
		return false;
	}
	str_old_img_path = img;

	WALLPAPEROPT wp = { 0 };
	wp.dwSize = sizeof(WALLPAPEROPT);
	hr = pIAD->GetWallpaperOptions(&wp, 0);

	i_old_option = wp.dwStyle;
	hr = pIAD->SetWallpaper(str_img_path.c_str(), 0);

	if (i_option > 0)
	{
		WALLPAPEROPT wp = { 0 };
		wp.dwSize = sizeof(WALLPAPEROPT);
		wp.dwStyle = i_option;
		hr = pIAD->SetWallpaperOptions(&wp, 0);
	}
	if (b_save)
	{
		hr = pIAD->ApplyChanges(AD_APPLY_ALL);
	}
	else
	{
		hr = pIAD->ApplyChanges(AD_APPLY_REFRESH);
	}

	if (FAILED(hr))
	{
		pIAD->Release();
		if (b_inited_ok)
			CoUninitialize();
		return false;
	}
	pIAD->Release();
	if (b_inited_ok)
		CoUninitialize();

	//set_destop_picture_by_reg(str_img_path);
	return true;
}

bool get_desktop_picture(std::wstring& str_img_path, int& i_option)
{
	i_option = I_WALLPAPER_STYTLE_NO_CHANGE;
	str_img_path.clear();

	HRESULT hr = S_FALSE;
	bool b_inited_ok = false;
	hr = CoInitialize(NULL);
	if (hr == S_OK)
	{
		b_inited_ok = true;
	}
	IActiveDesktop* pIAD = NULL;
	hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pIAD);
	if (FAILED(hr))
	{
		if (b_inited_ok)
			CoUninitialize();
		return false;
	}

	wchar_t img[4096] = { 0 };
	hr = pIAD->GetWallpaper(img, 4096, AD_GETWP_LAST_APPLIED);
	if (FAILED(hr))
	{
		pIAD->Release();
		if (b_inited_ok)
			CoUninitialize();
		return false;
	}
	str_img_path = img;

	WALLPAPEROPT wp = { 0 };
	wp.dwSize = sizeof(WALLPAPEROPT);
	hr = pIAD->GetWallpaperOptions(&wp, 0);

	i_option = wp.dwStyle;

	pIAD->Release();
	if (b_inited_ok)
		CoUninitialize();

	return true;
}

bool set_destop_picture_by_reg(const std::wstring& str_img_path, bool b_save)
{
	// Change the wallpaper.
	UINT ui = SPIF_SENDWININICHANGE;
	if (b_save)
	{
		ui = ui | SPIF_UPDATEINIFILE;
	}
	SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)str_img_path.c_str(), ui);

	return true;
}

// bool  set_desktop_path(const std::wstring& str_path, std::wstring& str_old_path)
// {
// 	QRegEdit reg;
// 	str_old_path.clear();
// 	if (reg.OpenDir(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", true, HKEY_CURRENT_USER, KEY_READ | KEY_WRITE))
// 	{
// 		reg.GetStr(L"Desktop", str_old_path);
// 		return reg.SetStr(L"Desktop", str_path);
// 	}
// 
// 	return false;
// }

int create_desktop(const std::wstring& _str_desk_name)
{
	std::wstring str_desk_name = _str_desk_name;
	if (str_desk_name.empty())
	{
		str_desk_name = SYSTEM_DEFAULT_DESKTOP;
	}
	SECURITY_ATTRIBUTES attributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
	HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);

	if (hdesktop == NULL)
	{
		hdesktop = CreateDesktopW(str_desk_name.c_str(), NULL, NULL, 0, GENERIC_ALL, &attributes);
		if (hdesktop == NULL)
		{
			return -1;
		}

		BOOL bRet = FALSE;
		PSECURITY_DESCRIPTOR SecDes = NULL;
		bRet = ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("S:(ML;;NW;;;LW)"), SDDL_REVISION_1, &SecDes, NULL);
		if (bRet)
		{
			BOOL bSaclDefaulted = FALSE;
			BOOL bSaclPresent = FALSE;
			PACL SecACL = NULL;
			bRet = GetSecurityDescriptorSacl(SecDes, &bSaclPresent, &SecACL, &bSaclDefaulted);
			if (bRet)
			{
				SetSecurityInfo(hdesktop, SE_WINDOW_OBJECT, 0x10, NULL, NULL, NULL, SecACL);
			}
		}
	}

	CloseDesktop(hdesktop);
	return 0;
}

int create_desktop_no_close(HDESK& hdesk_ret, const std::wstring& _str_desk_name)
{
	hdesk_ret = NULL;
	std::wstring str_desk_name = _str_desk_name;
	if (str_desk_name.empty())
	{
		str_desk_name = SYSTEM_DEFAULT_DESKTOP;
	}
	SECURITY_ATTRIBUTES attributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
	HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);

	if (hdesktop == NULL)
	{
		hdesktop = CreateDesktopW(str_desk_name.c_str(), NULL, NULL, 0, GENERIC_ALL, &attributes);
		if (hdesktop == NULL)
		{
			return -1;
		}

		BOOL bRet = FALSE;
		PSECURITY_DESCRIPTOR SecDes = NULL;
		bRet = ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("S:(ML;;NW;;;LW)"), SDDL_REVISION_1, &SecDes, NULL);
		if (bRet)
		{
			BOOL bSaclDefaulted = FALSE;
			BOOL bSaclPresent = FALSE;
			PACL SecACL = NULL;
			bRet = GetSecurityDescriptorSacl(SecDes, &bSaclPresent, &SecACL, &bSaclDefaulted);
			if (bRet)
			{
				SetSecurityInfo(hdesktop, SE_WINDOW_OBJECT, 0x10, NULL, NULL, NULL, SecACL);
			}
		}
	}
	hdesk_ret = hdesktop;
	return 0;
}

int change_to_desktop(const std::wstring& _str_desk_name)
{
	std::wstring str_desk_name = _str_desk_name;
	if (str_desk_name.empty())
	{
		str_desk_name = SYSTEM_DEFAULT_DESKTOP;
	}

	HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);
	if (hdesktop == NULL)
	{
		create_desktop_no_close(hdesktop, str_desk_name);
	}

	if (hdesktop != NULL)
	{
		if (SwitchDesktop(hdesktop))
		{
			CloseDesktop(hdesktop);
			return 0;
		}
		else
		{
			CloseDesktop(hdesktop);
			return -2;
		}
	}
	else
	{
		return -3;
	}

	return -4;
}

int change_thread_to_desktop(const std::wstring& _str_desk_name)
{
	std::wstring str_desk_name = _str_desk_name;
	if (str_desk_name.empty())
	{
		str_desk_name = SYSTEM_DEFAULT_DESKTOP;
	}

	HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);
	if (hdesktop == NULL)
	{
		create_desktop_no_close(hdesktop, str_desk_name);
	}

	if (hdesktop != NULL)
	{
		if (SetThreadDesktop(hdesktop))
		{
			CloseDesktop(hdesktop);
			return 0;
		}
		else
		{
			CloseDesktop(hdesktop);
			return -2;
		}
	}

	return -3;
}


int  run_exe(const std::wstring& str_img_path, const std::wstring& _str_desk_name)//str_desk_name为空表示切换到系统默认桌面
{
	std::wstring str_desk_name = _str_desk_name;
	if (str_desk_name.empty())
	{
		str_desk_name = SYSTEM_DEFAULT_DESKTOP;
	}

	HDESK hdesktop = OpenDesktopW(str_desk_name.c_str(), DF_ALLOWOTHERACCOUNTHOOK, TRUE, GENERIC_ALL);
	if (hdesktop == NULL)
	{
		create_desktop_no_close(hdesktop, str_desk_name);
	}

	if (hdesktop != NULL)
	{
		PROCESS_INFORMATION pInfo = { 0 };
		STARTUPINFO sInfo = { 0 };
		wchar_t name[1024] = { 0 };
		wcscpy_s(name, 1024, str_desk_name.c_str());
		sInfo.cb = sizeof(sInfo);
		sInfo.lpDesktop = name;
		sInfo.dwFlags = STARTF_USESHOWWINDOW;
		sInfo.wShowWindow = SW_SHOW;

		wchar_t cmd[2048] = { 0 };
		wcscpy_s(cmd, 2046, str_img_path.c_str());

		BOOL bRet = CreateProcess(NULL, cmd, NULL, NULL, TRUE,
			NULL, NULL, NULL, &sInfo, &pInfo);//MSDN上面说pszCurDir [in] Not supported; set to NULL,不然的话如果cmd参数传入多个参数,就会进程创建失败

		CloseDesktop(hdesktop);
		if (bRet == FALSE)
		{
			return -2;
		}
		return 0;
	}

	return -3;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值