开发者

How can I tell when a screen's WorkingArea changes (i.e. task bar is moved)?

开发者 https://www.devze.com 2022-12-28 12:40 出处:网络
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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消