I have some windows docked to edges/corners of the working开发者_Python百科 area, and I need to know if/when the WorkingArea of the screen changes so I can update the position of those windows. I've attempted to tackle this before to no avail, as I recall.
One way would be to register your windows as an Application Desktop Toolbar (AppBar) http://msdn.microsoft.com/en-us/library/bb776821(VS.85).aspx Then the system will send you notifications when your window needs to be repositioned, resized etc. For example an AppBar receives a ABN_POSCHANGED notification from the system when something occurs that will affect the size/position/visiblity etc. of the AppBar.
You will need to interop to do this, here is a Code Project article on doing this with C#, though I have only done with C++ so I cannot vouch for the article, but it should be a fair starting point. http://www.codeproject.com/KB/dotnet/AppBar.aspx
I ended up just taking the very simple approach of running a DispatcherTimer
that ticks every two seconds and simply checks the current WorkingArea against the last-checked WorkingArea, sending an event if they are different.
1- Create a property in your form that saves the last location of the workingArea or last Screen (as in the code example).
2- Override LocationChanged in your form to check if the new location of the form is on a new WorkingArea. If so, the form is on a new Screen (working area).
protected override void OnLocationChanged(EventArgs e)
{
base.OnLocationChanged(e);
WorkingScreen = Screen.AllScreens.ToList().FirstOrDefault(s => s.WorkingArea == Screen.GetWorkingArea(this));
}
Screen _WorkingScreen = null;
Screen WorkingScreen
{
get { return _WorkingScreen; }
set
{
if (WorkingScreen != value)
{
_WorkingScreen = value;
// Screen changed or working area changed!!!!
}
}
}
This seems to be an undocumented feature, but i found that listening for WM_WININICHANGE in your WndProc will tell you when the taskbar is moved/resized.
However i doubt other AppBar changes will trigger this, but maybe you don't want to respond to those.
private rectangle prevWA;
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_WININICHANGE: // 0x1A
{
Debug.Print($"WM_WININICHANGE {m.LParam}");
if (m.LParam == IntPtr.Zero)
{
var newWA = Screen.FromPoint(this.Location + new Point(this.Width / 2, this.Height / 2)).WorkingArea;
if (newWA != prevWA)
{
Debug.Print($"Working Area Changed {prevWA}->{newWA}");
// code here
prewWA = newWA;
}
}
break;
}
}
base.WndProc(m); // allow form to process this message
}
note: i don't really code in C# so this may have errors.
精彩评论