การเข้าใจพฤติกรรมของ Process.MainWindowHandle
ใน C#
เมื่อทำงานกับ C# และแอปพลิเคชัน .NET คุณอาจพบกับพฤติกรรมที่ไม่คาดคิดเกี่ยวกับ Process.MainWindowHandle
คุณสมบัตินี้ควรอ้างถึงหน้าต่างหลักของกระบวนการ ซึ่งปกติคือหน้าต่างที่สร้างขึ้นเมื่อเริ่มต้น อย่างไรก็ตาม นักพัฒนาหลายคนสังเกตว่ามัน似ว่าจะเปลี่ยนแปลงในระหว่างการทำงาน ซึ่งตรงข้ามกับสิ่งที่เอกสารของ Microsoft แนะนำ มาเจาะลึกเข้าไปในการทำความเข้าใจปรากฏการณ์นี้และสิ่งที่อาจเกิดขึ้นเบื้องหลัง
ความสับสนที่ปรากฏ
ตามเอกสาร MSDN หน้าต่างหลักถูกกำหนดให้เป็นหน้าต่างแรกที่สร้างขึ้นเมื่อกระบวนการเริ่มต้น มันแนะนำว่าในขณะที่หน้าต่างเพิ่มเติม เช่น หน้าต่างโมดอลและหน้าต่างระดับสูง สามารถปรากฏขึ้นหลังจากนั้น หน้าต่างแรกควรคงอยู่เป็นหน้าต่างหลักเสมอ
แม้จะมีเช่นนี้ หากคุณได้ทำการดีบักแอปพลิเคชันและสังเกตเห็น MainWindowHandle
คุณอาจพบว่า ค่าของมันดูเหมือนจะเปลี่ยนแปลงไปอย่างไม่คาดคิด ความสับสนสูงสุดเกิดขึ้นเมื่อมีการตระหนักว่า ในบางการโต้ตอบ เช่น การเปิดเมนูแบบเลื่อนลงในแอปพลิเคชัน Windows Forms ตัวจับของหน้าต่างดูเหมือนจะผันผวน
การตั้งค่าการทดสอบเพื่อติดตามการเปลี่ยนแปลง
เพื่อทำความเข้าใจพฤติกรรมนี้ให้ดีขึ้น นักพัฒนาคนหนึ่งได้สร้างแอปพลิเคชัน WinForms ที่ง่ายซึ่งติดตาม MainWindowHandle
ของกระบวนการ Visual Studio (DEVENV
) ด้านล่างนี้คือแกนหลักของการดำเนินการ ซึ่งทำการตรวจสอบ MainWindowHandle
ทุก ๆ 100 มิลลิวินาที:
IntPtr oldHWnd = IntPtr.Zero;
void GetMainwindowHandle()
{
Process[] processes = Process.GetProcessesByName("DEVENV");
if (processes.Length != 1)
return;
IntPtr newHWnd = processes[0].MainWindowHandle;
if (newHWnd != oldHWnd)
{
oldHWnd = newHWnd;
textBox1.AppendText(processes[0].MainWindowHandle.ToString("X") + "\r\n");
}
}
private void timer1Tick(object sender, EventArgs e)
{
GetMainwindowHandle();
}
โค้ดนี้เรียกใช้ตัวจับเวลาเพื่อตรวจสอบการเปลี่ยนแปลงใน MainWindowHandle
อย่างต่อเนื่อง น่าสนใจว่าการคลิกที่องค์ประกอบ UI บางอย่างสามารถเปลี่ยนแปลงตัวจับได้จริง
การตรวจสอบปัญหาหลัก
ความสับสนเกี่ยวกับ MainWindowHandle
ที่เปลี่ยนแปลงอาจมาจากวิธีที่ .NET กำหนดว่าอะไรคือหน้าต่างหลัก เมื่อเราตรวจสอบซอร์สโค้ดของ .NET เราสามารถเปิดเผยวิธีการทำงานภายในว่า:
private bool IsMainWindow(IntPtr handle)
{
return (!(NativeMethods.GetWindow(new HandleRef(this, handle), 4) != IntPtr.Zero)
&& NativeMethods.IsWindowVisible(new HandleRef(this, handle)));
}
วิธีนี้ตรวจสอบว่าหน้าต่างเป็นหน้าต่างระดับสูงที่สามารถมองเห็นได้ ซึ่งหมายความว่าเมื่อมีหน้าต่างระดับสูงที่มองเห็นได้หลายอัน หน้าต่างแรกที่พบซึ่งตรงตามเกณฑ์นี้จะกลายเป็นหน้าต่างหลัก ดังนั้น หากมีหน้าต่างอื่นเปิดที่เทคนิคแล้วเป็น ‘หน้าต่างแรก’ ที่มองเห็นได้ MainWindowHandle
อาจเปลี่ยนไปที่หน้าต่างใหม่
สรุปและข้อคิด
สุดท้ายนี้ พฤติกรรมของ Process.MainWindowHandle
อาจไม่ตรงตามเอกสารเสมอไป ดูเหมือนว่าค่าของมันอาจเปลี่ยนขึ้นอยู่กับความสามารถในการมองเห็นและกิจกรรมของหน้าต่างอื่น ๆ ที่จัดการโดยกระบวนการ ดังนั้นในขณะที่พัฒนาแอปพลิเคชันที่ใช้คุณสมบัตินี้ สิ่งสำคัญคือต้องคำนึงว่าตัวจับอาจไม่คงที่ดังที่คิดไว้ในตอนแรก
ดังนั้น ครั้งต่อไปที่คุณสังเกตเห็นการเปลี่ยนแปลงที่ไม่คาดคิดใน MainWindowHandle
ของแอปพลิเคชันของคุณ ให้จำไว้ว่า การจัดการหน้าต่างที่มองเห็นได้ของ .NET อาจนำไปสู่พฤติกรรมที่น่าประหลาดใจนี้ อย่าลืมให้แน่ใจว่าแอปพลิเคชันของคุณจัดการกับความละเอียดซับซ้อนดังกล่าวได้อย่างราบรื่น