65.9K
CodeProject is changing. Read more.
Home

Faking Multiple Desktops

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.08/5 (7 votes)

Jan 26, 2006

CPOL

3 min read

viewsIcon

36428

downloadIcon

833

An application that simulates multiple desktops. Including the ability to transfer windows between desktops, which seems to be missing from Microsoft's implementation.

Sample Image - multipledesktops.gif

Introduction

In my mind, by far the coolest feature that a desktop manager can have is proper multiple (virtual) desktops (shallow, I know). So, Windows XP doesn't have this feature; ah well, there's a PowerTool that does it. Except - you can't change the desktop just by mousing off the edge, and more seriously, there doesn't appear to be any mechanism to transfer windows between desktops - which is very annoying, as things never open where you want them to.

Concept

I thought that the easiest way to do this is simply to show and hide windows in such a way as to give the impression of more than one desktop. About halfway through writing this, I discovered SwitchDesktop, which looked quite complicated, so I didn't bother trying it that way.

Technical Details

The program is an MFC Dialog App.

I found out how to list all the windows on the system and show and hide them from the tbarsort article. I ask Windows for handles to every window on the system using EnumWindows, and filter out the irrelevant ones.

bool ValidWindow(HWND hwnd)
{
  if (!IsWindowVisible(hwnd)) return false;
  if (GetWindowTextLength(hwnd) == 0) return false;
  if (GetAsyncKeyState(VK_LBUTTON) && 
           hwnd==GetForegroundWindow()) return false;
  char str[100];
  GetWindowText(hwnd,str,99);
  if(strncmp(str,"Desktop",100)==0) return false;
  if(strncmp(str,"Program Manager",100)==0) return false;
  return true;
}

BOOL CALLBACK AddToList(HWND hwnd,LPARAM ret)
{
  std::vector<HWND>* vecret=(std::vector<HWND>*)ret;
  if(ValidWindow(hwnd)) vecret->push_back(hwnd);
  return TRUE;
}

std::vector<HWND> WindowList()
{
  std::vector<HWND> windows;
  EnumWindows(AddToList,LPARAM(&windows));
  return windows;
}

Desktops can be switched by pressing the relevant button or with a keyboard shortcut, implemented with RegisterHotKey; for example, Win+1 is registered by:

RegisterHotKey(GetSafeHwnd(),1,MOD_WIN,'1');

For some reason, the MFC ClassWizard doesn't know about the WM_HOTKEY message, so it has to be added manually to the message map:

ON_MESSAGE(WM_HOTKEY,OnHotKey)

By far the hardest thing to do was to detect when the mouse touched the edge of the screen (which is when the desktops change). Eventually I found the MouseHookDlg project (although I can't currently find a reference for it), which shows how to install a global mouse hook. All I have to do is package the DLL with my app, and call the simple function API_SetHooks to register a mouse callback, and put a handler in the message map:

ON_REGISTERED_MESSAGE(UWM_MOUSEMOVE, OnHookMouseMove)

having first registered this mesage by:

UWM_MOUSEMOVE = RegisterWindowMessage(UWM_SHELL_HOOK_MSG);

Finally, I wanted it to be possible to drag windows off the side of the screen and have them come with you to the new desktop. I failed to find an actual way of checking if any windows are being dragged (I suspect it can be done with another global hook); instead, if the left mouse button is down as the desktops are switched, then the foreground window is transferred, hence the line:

if (GetAsyncKeyState(VK_LBUTTON) && hwnd==GetForegroundWindow()) return false;

in the ValidWindow above. This works well, but occasionally leads to accidental window transfers.

Conclusion

The program works fine, with one or two minor bugs (not bad for only a few hours' work). Occasionally, windows get transferred when not intended, and much worse, occasionally they get permanently hidden (don't do any absolutely vital work whilst using this program, there is a small chance that this will happen and you will be unable to save). I would be glad of suggestions for bug fixes, especially for improving the dragging detection; extra features are unlikely to get added. Blatant plug: visit my site for various games written using OpenGL with MFC or GLUT.