我最近向WPF應用程序添加了一個窗口,該窗口可作爲「應用程序欄」停靠在桌面邊緣。我用來做對接的代碼來自this stackoverflow post。應用程序欄窗口從對接位置彈出,然後移動到對接位置
程序有三個與此窗口相關的用戶設置。一個是窗口對接的邊緣,另外兩個是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
屬性設置爲窗口構造函數中保存的值來將窗口移動到停靠位置。那也沒用。事實上,情況更糟,因爲窗戶首先被拉到停靠位置,然後顯然已從桌面邊緣移開以騰出空間,然後移回停靠位置。
如何讓這個窗口在啓動時出現在停靠的位置,而不是在之後移動?
編輯:
我想我找到了問題的原因。在AppBarFunctions
類代碼中,在ABSetPos
方法中,在它調度窗口的Dispatcher
(UI線程)上的DoResize
方法之前,有一條評論。註釋寫着:
// 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移動的窗口出來的空間被保留爲窗口,然後我將其移回在我加入了很多的跟蹤點在我的代碼&我。可以看到該窗口在該移動完成之後才被渲染(代碼中的註釋中提到的窗口)。窗口渲染後,它被我的代碼移動到停靠位置。
AppBarFunctions
類已經爲shell消息的wathcing添加了一個窗口過程掛鉤。如果我添加一個WM_WINDOWPOSCHANGED檢查,我可以以某種方式停止正在處理的消息?或者,也許我可以更改由Windows/WPF完成的移動的Left
和Top
屬性的值,以便窗口結束到我想要的位置?