views:

684

answers:

2

Is it possible to reserve a screen area near an edge of the screen for your app in Windows 7? It would behave similar to the Windows taskbar (i.e. maximized windows would not overlap with it).

I'm writing a taskbar app with proper support for multiple monitors. The primary purpose is to show a taskbar on each screen containing only the apps on that screen. None of the existing solutions (Ulltramon, DisplayFusion) I know of work for Win 7, and none are open source.

C# code would be nice, but any hints are appreciated as well.

+3  A: 

I'm unsure of how to do this directly in C#, but in native code you can call SystemParametersInfo with SPI_SETWORKAREA. This is how apps like the taskbar, sidebar, and so on can prevent maximized windows from overlapping them.

http://msdn.microsoft.com/en-us/library/ms724947.aspx is the documentation for SystemParametersInfo.

http://social.msdn.microsoft.com/forums/en-US/winforms/thread/9fe831e5-ccfb-4e8d-a129-68c301c83acb/ shows P/Invoke signatures for this method.

Michael
I would have said that it's impossible to do this _perfectly_, because there are ways around it. Full screen and kiosk, and directx apps, for example, will ignore this.But then I realized that since he's building an app that's "like the taskbar", allowing the same work-arounds as the taskbar is perfectly appropriate.
Joel Coehoorn
He specifically said "Maximized windows", and maximizing a window will respect this setting. Without even jumping to DX, you can manually position a window outside the work area.
Michael
+3  A: 

I feel silly answering my own question, but thanks to Michael's hint, I found an appropriate C# code sample.

using System;
using System.Runtime.InteropServices;

public class WorkArea
{
  [System.Runtime.InteropServices.DllImport("user32.dll",  EntryPoint="SystemParametersInfoA")]
  private static extern Int32 SystemParametersInfo(Int32 uAction, Int32 uParam, IntPtr lpvParam, Int32 fuWinIni);

  private const Int32 SPI_SETWORKAREA = 47;
  public WorkArea(Int32 Left,Int32 Right,Int32 Top,Int32 Bottom)
  {
    _WorkArea.Left = Left;
    _WorkArea.Top = Top;
    _WorkArea.Bottom = Bottom;
    _WorkArea.Right = Right;
  }

  public struct RECT
  {
    public Int32 Left;
    public Int32 Right;
    public Int32 Top;
    public Int32 Bottom;
  }

  private RECT _WorkArea;
  public void SetWorkingArea()
  {
    IntPtr ptr = IntPtr.Zero;
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(_WorkArea));
    Marshal.StructureToPtr(_WorkArea,ptr,false);
    int i = SystemParametersInfo(SPI_SETWORKAREA,0,ptr,0);
  }
}
dbkk