|
|||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionHaving a spare computer available, I decided to try out Mandrake Linux, just to see what its like (having never used linux before). I thought its desktop switching ability was interesting, and began wondering if it was possible to do the same thing on my Windows box. A quick search on MSDN revealed the Desktop API functions, which allowed me to do just that. According to the docs, this functionality has been available since Windows 2000 Professional, and since I'm using XP, I thought I would give it a go. When Windows loads, and you are logged in, a desktop is automatically created, called "default". Using the functions provided you can create, open, and switch desktops, unfortunately, deletion isn't provided (more on that later). Using the Desktop classCreating a DesktopCreating a desktop is a very easy task, as the code example below shows. Desktops can be created using either the instance, or the static members provided. // Instance method
Desktop desktop = new Desktop();
desktop.Create("myDesktop");
// Static method
Desktop desktop = Desktop.CreateDesktop("myDesktop");
Note: Desktop names cannot contain backslash characters. Using either of the methods will result in a Switching DesktopsSwitching desktops is just as easy as creating the desktop, all that is
required is a call to either the static method stating the desktop name, or the
instance method of an open // instance method.
Desktop desktop = new Desktop();
desktop.Open("myDesktop");
desktop.Show();
// static method.
Desktop.Show("myDesktop");
Opening Processes in DesktopsThe // instance method
Desktop desktop = Desktop.OpenDesktop("myDesktop");
Process p = desktop.CreateProcess("calc.exe");
// static method
Process p = Desktop.CreateProcess("calc.exe", "myDesktop");
A Deleting DesktopsDeleting a desktop is a little trickier. The only way to delete a desktop is
to kill all processes running on it, at which point, it is automatically
deleted. So far, I have been unable to get a list of processes running on a
desktop other than the input desktop (nor am I certain this is possible), but
what I have done, is provided the With this in mind, the only way to delete a desktop which has been accessed by the user is to be on the desktop, enumerate the processes, and kill them one-by-one. Making sure your application isn't killed off before it has a chance to jump desktops (unless you want it that way). Process[] processes = Desktop.GetInputProcesses();
Process thisProc = Process.GetCurrentProcess();
foreach(Process p in processes)
{
if (p.ProcessName != thisProc.ProcessName)
{
p.Kill();
}
}
Settings a Thread's DesktopThreads of your process can be moved between desktops, provided they do not have any hooks or windows in the current desktop. Desktop desktop = Desktop.OpenDesktop("myDesktop"); Desktop.SetCurrent(desktop); The code example above would move the calling thread into "myDesktop", but would fail if the thread has a window or a hook. Behind the Scenes
Creating a Desktop[DllImport("user32.dll")]
private static extern IntPtr CreateDesktop(string lpszDesktop,
IntPtr lpszDevice,
IntPtr pDevmode,
int dwFlags,
long dwDesiredAccess,
IntPtr lpsa);
The m_desktop = CreateDesktop(name, IntPtr.Zero, IntPtr.Zero, 0,
AccessRights, IntPtr.Zero);
The return value is a handle to the desktop, or Switching Desktops[DllImport("user32.dll")]
private static extern bool SwitchDesktop(IntPtr hDesktop);
The bool result = SwitchDesktop(m_desktop);
Opening Processes in Desktops[DllImport("kernel32.dll")]
private static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
bool bInheritHandles,
int dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
ref PROCESS_INFORMATION lpProcessInformation);
The // set startup parameters.
STARTUPINFO si = new STARTUPINFO();
si.cb = Marshal.SizeOf(si);
si.lpDesktop = m_desktopName;
PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
// start the process.
bool result = CreateProcess(null, path, IntPtr.Zero, IntPtr.Zero, true,
NORMAL_PRIORITY_CLASS, IntPtr.Zero, null, ref si, ref pi);
Specifying a return Process.GetProcessById(pi.dwProcessId);
Setting a Thread's Desktop[DllImport("user32.dll")]
private static extern bool SetThreadDesktop(IntPtr hDesktop);
The return SetThreadDesktop(desktop.DesktopHandle);
Example usageI have not provided an example application with the source, as it is very straight forward, and all members (except private) are XML commented. However, if you would like to see how this could be used in an application, try my website, where I have used it to make a small desktop switching application. History
|
||||||||||||||||||||||||||||||