日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

设置WPF窗口相对于非WPF窗口的位置

發布時間:2025/4/16 asp.net 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设置WPF窗口相对于非WPF窗口的位置 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在前一個Post當中,指出了在WPF的WindowInteropHelper類中的一個BUG:通過WindowInteropHelper的Owner屬性不能實現把WPF窗口的Owner屬性設置為一個非WPF窗口的句柄。

在我的Post帖出后不到一天,在WPF SDK的Blog上,就針對這個BUG給出了一個非常完美的解決方案。既然不同通過設置WindowStartupLocation.CenterOwner來改變窗口的位置。那么我們就用WindowStartupLocation.Manual來手動計算設置窗口的位置。大致的代碼如下:

using System.Windows;
using System.Windows.Interop; // WindowInteropHelper

...

// Instantiate the owned WPF window
Window cw = new Window();

// Set the owned WPF window’s owner with the non-WPF owner window
IntPtr ownerWindowHandle = ...;
?
// Set the owned WPF window’s owner with the non-WPF owner window

WindowInteropHelper helper = new WindowInteropHelper(cw);
helper.Owner = ownerWindowHandle;

// Manually calculate Top/Left to appear centered
int nonWPFOwnerLeft = ...; ?// Get non-WPF owner’s Left
int nonWPFOwnerWidth = ...; ?// Get non-WPF owner’s Width
int nonWPFOwnerTop = ...; ?// Get non-WPF owner’s Top
int nonWPFOwnerHeight = ...; ?// Get non-WPF owner’s Height

cw.WindowStartupLocation = WindowStartupLocation.Manual;
cw.Left = nonWPFOwnerLeft + (nonWPFOwnerWidth - cw.Width) / 2;
cw.Top = nonWPFOwnerTop + (nonWPFOwnerHeight - cw.Height) / 2;

// Show the owned WPF window
cw.Show();

這段代碼理論上沒有什么問題呢?但是WPF是支持設備獨立的。因此,在非WPF Owner窗口的某些情況下可能會因為DPI的而不能正常工作。解決這個問題,可以利用HwndSource類進行窗口位置的設備獨立計算:

using System.Windows; // Window, WindowStartupLocation, Point
using System.Windows.Interop; // WindowInteropHelper, HwndSource
using System.Windows.Media; // Matrix

...

// Instantiate the owned WPF window
CenteredWindow cw = new CenteredWindow();

// Get the handle to the non-WPF owner window
IntPtr ownerWindowHandle = ...; // Get hWnd for non-WPF window
?
// Set the owned WPF window’s owner with the non-WPF owner window
WindowInteropHelper helper = new WindowInteropHelper(cw);
helper.Owner = ownerWindowHandle;
?

// Center window
// Note - Need to use HwndSource to get handle to WPF owned window,
//??????? and the handle only exists when SourceInitialized has been
//??????? raised

cw.SourceInitialized += delegate
{
??? // Get WPF size and location for non-WPF owner window
??? int nonWPFOwnerLeft = ...; // Get non-WPF owner’s Left
??? int nonWPFOwnerWidth = ...; // Get non-WPF owner’s Width
??? int nonWPFOwnerTop = ...; // Get non-WPF owner’s Top
??? int nonWPFOwnerHeight = ...; // Get non-WPF owner’s Height

??? // Get transform matrix to transform non-WPF owner window
??? // size and location units into device-independent WPF?
??? // size and location units

??? HwndSource source = HwndSource.FromHwnd(helper.Handle);
??? if (source == null) return;
??? Matrix matrix = source.CompositionTarget.TransformFromDevice;
??? Point ownerWPFSize = matrix.Transform(
????? new Point(nonWPFOwnerWidth, nonWPFOwnerHeight));
??? Point ownerWPFPosition = matrix.Transform(
????? new Point(nonWPFOwnerLeft, nonWPFOwnerTop));

??? // Center WPF window
??? cw.WindowStartupLocation = WindowStartupLocation.Manual;
??? cw.Left = ownerWPFPosition.X + (ownerWPFSize.X - cw.Width) / 2;
??? cw.Top = ownerWPFPosition.Y + (ownerWPFSize.Y - cw.Height) / 2;

};

// Show WPF owned window
cw.Show();

在上面的代碼中需要注意的是HwndSource的使用。這個類需要一個窗口句柄,因此它的代碼被放在一個SourceInitialized的事件委派函數中執行。

最后,除了上面這種方法,其實我們還可以用Win32 API函數來實現,在ATL的CWindow類中,就有這樣的一個函數,我直接把放在下面,有興趣的朋友參考其中的實現原理:?

?

BOOL?CenterWindow(HWND?hWndCenter?=?NULL)?throw()
{
????ATLASSERT(::IsWindow(m_hWnd));

????
//?determine?owner?window?to?center?against
????DWORD?dwStyle?=?GetStyle();
????
if(hWndCenter?==?NULL)
????
{
????????
if(dwStyle?&?WS_CHILD)
????????????hWndCenter?
=?::GetParent(m_hWnd);
????????
else
????????????hWndCenter?
=?::GetWindow(m_hWnd,?GW_OWNER);
????}


????
//?get?coordinates?of?the?window?relative?to?its?parent
????RECT?rcDlg;
????::GetWindowRect(m_hWnd,?
&rcDlg);
????RECT?rcArea;
????RECT?rcCenter;
????HWND?hWndParent;
????
if(!(dwStyle?&?WS_CHILD))
????
{
????????
//?don't?center?against?invisible?or?minimized?windows
????????if(hWndCenter?!=?NULL)
????????
{
????????????DWORD?dwStyleCenter?
=?::GetWindowLong(hWndCenter,?GWL_STYLE);
????????????
if(!(dwStyleCenter?&?WS_VISIBLE)?||?(dwStyleCenter?&?WS_MINIMIZE))
????????????????hWndCenter?
=?NULL;
????????}


????????
//?center?within?screen?coordinates
????????::SystemParametersInfo(SPI_GETWORKAREA,?NULL,?&rcArea,?NULL);
????????
if(hWndCenter?==?NULL)
????????????rcCenter?
=?rcArea;
????????
else
????????????::GetWindowRect(hWndCenter,?
&rcCenter);
????}

????
else
????
{
????????
//?center?within?parent?client?coordinates
????????hWndParent?=?::GetParent(m_hWnd);
????????ATLASSERT(::IsWindow(hWndParent));

????????::GetClientRect(hWndParent,?
&rcArea);
????????ATLASSERT(::IsWindow(hWndCenter));
????????::GetClientRect(hWndCenter,?
&rcCenter);
????????::MapWindowPoints(hWndCenter,?hWndParent,?(POINT
*)&rcCenter,?2);
????}


????
int?DlgWidth?=?rcDlg.right?-?rcDlg.left;
????
int?DlgHeight?=?rcDlg.bottom?-?rcDlg.top;

????
//?find?dialog's?upper?left?based?on?rcCenter
????int?xLeft?=?(rcCenter.left?+?rcCenter.right)?/?2?-?DlgWidth?/?2;
????
int?yTop?=?(rcCenter.top?+?rcCenter.bottom)?/?2?-?DlgHeight?/?2;

????
//?if?the?dialog?is?outside?the?screen,?move?it?inside
????if(xLeft?<?rcArea.left)
????????xLeft?
=?rcArea.left;
????
else?if(xLeft?+?DlgWidth?>?rcArea.right)
????????xLeft?
=?rcArea.right?-?DlgWidth;

????
if(yTop?<?rcArea.top)
????????yTop?
=?rcArea.top;
????
else?if(yTop?+?DlgHeight?>?rcArea.bottom)
????????yTop?
=?rcArea.bottom?-?DlgHeight;

????
//?map?screen?coordinates?to?child?coordinates
????return?::SetWindowPos(m_hWnd,?NULL,?xLeft,?yTop,?-1,?-1,
????????SWP_NOSIZE?
|?SWP_NOZORDER?|?SWP_NOACTIVATE);
}

本文轉自賴儀靈博客園博客,原文鏈接:http://www.cnblogs.com/YilingLai/archive/2007/05/15/746706.html,如需轉載請自行聯系原作者。

總結

以上是生活随笔為你收集整理的设置WPF窗口相对于非WPF窗口的位置的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。