65.9K
CodeProject is changing. Read more.
Home

Impersonate Linux's Multi-desktop Feature on Windows Platform

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (13 votes)

Mar 5, 2009

CPOL

1 min read

viewsIcon

40962

downloadIcon

1299

This is a tiny tool to create multi virtual desktop, and allows you to switch between them.

2.jpg

Introduction

The feature, multi desktops (workspace), is supported by KDE/GNOME on Linux, and it can also be found on Mac OSX.

This tiny tool can impersonate this feature on Windows platform.

Desktop Functions

There is a series of APIs to maintain desktops.

Function Description
CloseDesktop Closes an open handle to a desktop object.
CreateDesktop Creates a new desktop, associates it with the current window station of the calling process, and assigns it to the calling thread.
CreateDesktopEx Creates a new desktop, associates it with the current window station of the calling process, and assigns it to the calling thread.
EnumDesktops Enumerates all desktops associated with the current window station of the calling process.
EnumDesktopWindows Enumerates all top-level windows associated with the specified desktop.
GetThreadDesktop Retrieves a handle to the desktop assigned to the specified thread.
GetUserObjectInformation Gets information about a window station or desktop object.
GetUserObjectSecurity Gets security information for a window station or desktop object.
OpenDesktop Opens the specified desktop object.
OpenInputDesktop Opens the desktop that receives user input.
SetThreadDesktop Assigns the specified desktop to the calling thread.
SetUserObjectInformation Sets information about a window station or desktop object.
SetUserObjectSecurity Sets security information for a window station or desktop object.
SwitchDesktop Makes a desktop visible and activates it. This enables the desktop to receive input from the user.

How To Create a New Desktop 

The simple code below demonstrates how to create a new desktop.

// create the new desktop
SECURITY_ATTRIBUTES stSecurityAttr = {sizeof(SECURITY_ATTRIBUTES), 0, TRUE};
stSecurityAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
stSecurityAttr.bInheritHandle = TRUE;
HDESK hDesktop = ::CreateDesktop( lpszDesktopName
	, NULL
	, NULL
	, 0
	, GENERIC_ALL
	, &stSecurityAttr
	);
if( hDesktop == NULL )
{
	::MessageBox( m_hWnd, _T("Failed to create new desktop."), 
				_T("Error"), MB_ICONERROR | MB_OK);
	return;
}

// start the Windows Shell(explorer.exe) on the new created desktop
STARTUPINFO stStartInfo = {0};
stStartInfo.cb = sizeof(STARTUPINFO);
stStartInfo.lpDesktop = (LPTSTR)lpszDesktopName;
PROCESS_INFORMATION stProcInfo = {0};
CString strCmdLine = _T("explorer.exe");
BOOL bRet = ::CreateProcess( NULL
	, strCmdLine.GetBuffer()
	, NULL
	, NULL
	, TRUE
	, 0
	, NULL
	, NULL
	, &stStartInfo
	, &stProcInfo
	);
strCmdLine.ReleaseBuffer();
if( !bRet )
{
	::CloseDesktop(hDesktop);
	::MessageBox( m_hWnd, _T("Failed to launch the explorer.exe 
			in the new desktop."), _T("Error"), MB_ICONERROR | MB_OK);
	return;
}
::SwitchDesktop(hDesktop);

// sleep for 3 seconds for the shell ready
Sleep(3000);

// launch another instance on the new created shell
TCHAR tszBuffer[MAX_PATH] = {0};
GetModuleFileName( m_hInstance, tszBuffer, MAX_PATH);
bRet = ::CreateProcess( NULL
	, tszBuffer
	, NULL
	, NULL
	, TRUE
	, 0
	, NULL
	, NULL
	, &stStartInfo
	, &stProcInfo
	);
	
::CloseDesktop(hDesktop);

History

  • 5th March, 2009: Initial post