Impersonate Linux's Multi-desktop Feature on Windows Platform






4.87/5 (13 votes)
This is a tiny tool to create multi virtual desktop, and allows you to switch between them.

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