Недавно я добавил окно в свое приложение WPF, которое можно состыковать до края рабочего стола как «панель приложений». Код, который я использую для док-станции, получен из сообщения this stackoverflow.Окно App Bar Window отскакивает от стыковки, затем переходит в положение стыковки
Программа имеет три пользовательских настроек, связанных с этим окном. Один из них - это край, где окно состыковано, а два других - значения свойств Left
& Top
. Идея состоит в том, что когда окно закрывается или программа выключается, окно возобновляется в том же состоянии и местоположении, когда программа перезагружается.
Проблема, с которой я сталкиваюсь, заключается в том, что когда программа открывается, окно сначала отображается в случайном месте на экране (возможно, координаты, назначенные ему Windows при создании окна), а затем он перемещается в пристыкованное положение. Другие программы, которые я видел, которые имеют функциональность панели приложений, например Trillian, рисуются в пристыкованной позиции с самого начала. Это немного смущает, чтобы окно двигалось так.
Вот код из окна:
private void AppBarWindow_Activated(object sender, EventArgs e) {
if (Settings.Default.AppBarWindowEdge != ABEdge.None) {
AppBarFunctions.SendShellActivated(this);
}
}
private void AppBarWindow_Closing(object sender, CancelEventArgs e) {
Settings.Default.AppBarWindowLeft = Left;
Settings.Default.AppBarWindowTop = Top;
Settings.Default.Save();
AppBarFunctions.SetAppBar(this, ABEdge.None);
// Other, app specific code . . .
}
private void AppBarWindow_LocationChanged(object sender, EventArgs e) {
if (Settings.Default.AppBarWindowEdge != ABEdge.None) {
AppBarFunctions.SendShellWindowPosChanged(this);
}
}
private void AppBarWindow_SourceInitialized(object sender, EventArgs e) {
if (Settings.Default.AppBarWindowEdge != ABEdge.None) {
SizeWindow(Settings.Default.AppBarWindowEdge == ABEdge.None ? ABEdge.Left : ABEdge.None);
}
}
private void AppBarWindow_SizeChanged(object sender, SizeChangedEventArgs e) {
if (Settings.Default.AppBarWindowEdge != ABEdge.None) {
AppBarFunctions.SendShellWindowPosChanged(this);
}
}
private void SizeWindow(ABEdge originalEdge) {
// App specific code to compute the window's size . . .
if (originalEdge != Settings.Default.AppBarWindowEdge) {
AppBarFunctions.SetAppBar(this, Settings.Default.AppBarWindowEdge);
}
Settings.Default.AppBarWindowLeft = Left;
Settings.Default.AppBarWindowTop = Top;
Settings.Default.Save();
}
Я добавил функции для вызова SHAppBarrMessage
, когда окно активируется, или когда его положение и изменение размера, как я прочитал в this acrticle. Вызовы, похоже, не влияют на поведение, поэтому я могу удалить их.
Я знаю, что события SourceInitialized
и Loading
вызываются до отображения окна, но после того, как оконный дескриптор и макет & пройдены. Однако оказывается, что окно отображается до вызова AppBarFunctions.SetAppBar
, поэтому я вижу, что оно появляется, а затем перемещается на место.
Я также попытался переместить окно в пристыкованное положение, установив свойства Left
и Top
на значения, сохраненные в настройках конструктора окна. Это тоже не сработало. На самом деле это было хуже, так как окно было сначала нарисовано в пристыкованном положении, а затем, по-видимому, было отодвинуто от края рабочего стола, чтобы освободить место для него, а затем снова переместилось в пристыкованное место.
Как я могу получить это окно, чтобы появиться в пристыкованном положении при запуске и не двигаться дальше?
Edit:
Я думаю, что я нашел причину этой проблемы. В коде класса AppBarFunctions
есть комментарий, в методе ABSetPos
, перед тем, как он планирует вызов метода DoResize
в окне Dispatcher
окна (пользовательский интерфейс). Комментарий гласит:
// This is done async, because WPF will send a resize after a new appbar is added.
// if we size right away, WPFs resize comes last and overrides us.
Таким образом, очевидно WPF или Windows, перемещает окно из пространства резервируется для окна, а затем переместить его обратно в Я добавил много точек трассировки в моем коде & I. может видеть, что окно не отображается до тех пор, пока не будет сделан этот шаг (тот, который указан в комментарии в коде). После визуализации окна он перемещается в пристыкованное положение по моему коду.
Класс AppBarFunctions
уже добавляет крючок процедуры окна для wathcing для сообщений из оболочки. Если я добавлю чек для WM_WINDOWPOSCHANGED, могу ли я как-то остановить обработку сообщения?Или, может быть, я могу изменить значения свойств и Top
для перемещения, выполняемого Windows/WPF, чтобы окно заканчивалось там, где я хочу?