Men dialog oynalarini (CommonDialog va MessageBox) bog'layapman, shunda ular ko'rsatilgandan so'ng ularni ota-ona Form ichiga markazlashtira olaman. Hamma narsa MessageBox ga tegishli bo'lgan joziba kabi ishlaydi, lekin dialog oynasi CommonDialog (OpenFileDialog, SaveFileDialog, va hokazo...) dan meros bo'lganda, men olgan to'rtburchak har doim noto'g'ri bo'ladi va markazlashtirish buziladi. Bu dialog oynasi to'rtburchaklarini olish uchun foydalanadigan kod:
[DllImport("User32.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern Boolean GetWindowRect([In] IntPtr handle, [Out] out RECT rectangle);
[DllImport("Dwmapi.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
private static extern UInt32 DwmGetWindowAttribute([In] IntPtr handle, [In] DWMWINDOW_ATTRIBUTE attribute, [In, Out] IntPtr attributeValue, [In] UInt32 attributeSize);
[DllImport("Dwmapi.dll", CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
private static extern UInt32 DwmIsCompositionEnabled([Out, MarshalAs(UnmanagedType.Bool)] out Boolean enabled);
internal static Boolean AeroThemeEnabled
{
get
{
Boolean result = false;
if (Environment.OSVersion.Version.Major >= 6)
DwmIsCompositionEnabled(out result);
return result;
}
}
internal static Boolean GetRectangle(IntPtr windowHandle, out Rectangle rectangle)
{
RECT nativeRectangle;
if (AeroThemeEnabled)
{
IntPtr attributeValue = IntPtr.Zero;
UInt32 size = GetSize(typeof(RECT));
try
{
attributeValue = Marshal.AllocCoTaskMem((Int32)size);
UInt32 result = DwmGetWindowAttribute(windowHandle, DWMWINDOW_ATTRIBUTE.DWMWA_EXTENDED_FRAME_BOUNDS, attributeValue, size);
if (result == 0)
nativeRectangle = Marshal.PtrToStructure<RECT>(attributeValue);
else if (!GetWindowRect(windowHandle, out nativeRectangle))
{
rectangle = Rectangle.Empty;
return false;
}
}
finally
{
if (attributeValue != IntPtr.Zero)
Marshal.FreeCoTaskMem(attributeValue);
}
}
else if (!GetWindowRect(windowHandle, out nativeRectangle))
{
rectangle = Rectangle.Empty;
return false;
}
Int32 x = nativeRectangle.Left;
Int32 y = nativeRectangle.Top;
Int32 width = nativeRectangle.Right - x;
Int32 height = nativeRectangle.Bottom - y;
rectangle = new Rectangle(x, y, width, height);
return true;
}
Mening ish muhitimda (VS2013 va Framework 4.6.2 bilan Win7), yuqorida aytib o'tganimdek, GetRectangle usuli noto'g'ri to'rtburchaklar Width va Height qaytaradi, men markazlashtirishim kerak bo'lgan dialog oynasi CommonDialog dan meros bo'lganda. Sinovlar davomida men GetWindowRect va DwmGetWindowAttribute bir xil qiymatlarni qaytarishini bilib oldim, shuning uchun men amalga oshirgan asosiy vaqtinchalik yechim mutlaqo foydasiz. Bundan tashqari, men olingan to'rtburchak har doim haqiqiydan 40 piksel yoki kengroq ekanligini aniqladim (men uni skrinshotda o'lchaganman).
Endi bu meni aqldan ozishga majbur qilmoqda. Men tushuna oladigan yagona echimlar:
Oyna ishlov beruvchisi
CommonDialogga tegishli yoki yo'qligini aniqlang va bu holda to'rtburchak o'lchamini qo'lda tuzating. Qanday qilib bilmayman, chunkiGetClassNameMessageBoxvaCommonDialoguchun#32770ni qaytaradi. Shuningdek,GetWindowLongdialog oynasi turini aniqlashga imkon beradigan foydali ma'lumotlarni taqdim etishiga shubha qilaman.CommonDialogko'rsatilishi bilanoq o'lchamini qo'lda o'zgartiring, shunda men uning haqiqiy hajmini bilib olaman.
Boshqa har qanday taklif mamnuniyat bilan qabul qilinadi.
OpenFileDialogvaSaveFileDialogtashqari dialog oynasi. Buning sababi,CommonDialogklassiWM_INITDIALOGga ishlov berilgandaMoveToScreenCenterdeb nomlangan usulni bajaradi. Shunday qilib, agar sizSetWindowPosgaSWP_SHOWWINDOWbayrog'ini qo'shsangiz, to'satdan ekranning o'rtasiga o'tadigan mukammal markazlashtirilgan dialog oynasini aniq ko'rishingiz mumkin. - person Tommaso Belluzzo   schedule 02.12.2016