程序的核心代码: procedure SwitchToDesktop(const DesktopNumber: Integer); var DesktopName: string; DesktopHandle: HDESK; SysPath: array[0..MAX_PATH-1] of char; WinDir: string; Len: integer; StartInfo: STARTUPINFO; ProceInfo: PROCESS_INFORMATION; begin if DesktopNumber = 1 then DesktopName := 'Default' else DesktopName := 'NewDesktop' + IntToStr(DesktopNumber);
DesktopHandle := OpenDesktop( pchar(DesktopName), DF_ALLOWOTHERACCOUNTHOOK, True, DESKTOP_CREATEMENU or DESKTOP_CREATEWINDOW or DESKTOP_ENUMERATE or DESKTOP_HOOKCONTROL or DESKTOP_JOURNALPLAYBACK or DESKTOP_JOURNALRECORD or DESKTOP_READOBJECTS or DESKTOP_SWITCHDESKTOP or DESKTOP_WRITEOBJECTS);
if DesktopHandle = 0 then begin DesktopHandle := CreateDesktop(PChar(DesktopName), nil, nil, DF_ALLOWOTHERACCOUNTHOOK, DESKTOP_CREATEMENU or DESKTOP_CREATEWINDOW or DESKTOP_ENUMERATE or DESKTOP_HOOKCONTROL or DESKTOP_JOURNALPLAYBACK or DESKTOP_JOURNALRECORD or DESKTOP_READOBJECTS or DESKTOP_SWITCHDESKTOP or DESKTOP_WRITEOBJECTS, nil); if DesktopHandle = 0 then begin MessageBox(Application.Handle, pchar(SysErrorMessage(GetLastError)), pchar('Error'), MB_ICONERROR); Exit; end; Len := GetWindowsDirectory(@SysPath, MAX_PATH); SetString(WinDir,pchar(@SysPath),Len); ZeroMemory(@StartInfo, SizeOf(STARTUPINFO)); StartInfo.cb := sizeof(STARTUPINFO); StartInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; StartInfo.wShowWindow := SW_SHOW; StartInfo.lpDesktop := PChar(DesktopName); if not CreateProcess(PChar(WinDir + '\explorer.exe'), nil, nil, nil, True, 0, nil, nil, StartInfo, ProceInfo) then begin MessageBox(Application.Handle, pchar(SysErrorMessage(GetLastError)), pchar('Error'), MB_ICONERROR); CloseDeskTop(DesktopHandle); Exit; end; end;
SwitchDesktop(DesktopHandle); end;
再谈下缺陷: 没有关闭虚拟的Desktop及其运行的Explorer进程 ProceInfo和DesktopHandle是需要存放起来的以便最后释放 if ProceInfo.hProcess <> 0 then begin TerminateProcess(ProceInfo.hProcess, 0); end; if DesktopHandle <> 0 then begin CloseDesktop(DesktopHandle); end;