การApplication.Run
โทรจะขับเคลื่อนปั๊มข้อความ Windows ของคุณซึ่งท้ายที่สุดแล้วจะช่วยเพิ่มพูนกิจกรรมทั้งหมดที่คุณสามารถขอได้ในForm
ชั้นเรียน (และอื่น ๆ ) ในการสร้างลูปเกมในระบบนิเวศนี้คุณต้องการฟังเมื่อปั๊มข้อความของแอปพลิเคชันว่างเปล่าและในขณะที่ยังว่างอยู่ให้ทำ "สถานะอินพุตกระบวนการ, อัปเดตลอจิกเกม, แสดงฉาก" ของลูปเกมต้นแบบ .
Application.Idle
เหตุการณ์ fires ครั้งทุกเวลาคิวข้อความของโปรแกรมประยุกต์ที่มีการอบและการประยุกต์ใช้จะถูกเปลี่ยนไปเป็นรัฐที่ไม่ได้ใช้งาน คุณสามารถขอเหตุการณ์ในตัวสร้างของฟอร์มหลักของคุณ:
class MainForm : Form {
public MainForm () {
Application.Idle += HandleApplicationIdle;
}
void HandleApplicationIdle (object sender, EventArgs e) {
//TODO: Implement me.
}
}
ถัดไปคุณจะต้องสามารถตรวจสอบว่าแอปพลิเคชันนั้นยังคงว่างอยู่หรือไม่ Idle
เหตุการณ์เดียวยิงครั้งเดียวเมื่อโปรแกรมประยุกต์ที่จะกลายเป็นไม่ได้ใช้งาน มันจะไม่ถูกไล่ออกอีกครั้งจนกว่าข้อความจะเข้าสู่คิวแล้วคิวจะหมดอีกครั้ง Windows Forms ไม่เปิดเผยวิธีการสอบถามสถานะของคิวข้อความ แต่คุณสามารถใช้บริการการเรียกแพลตฟอร์มเพื่อมอบหมายการสืบค้นไปยังฟังก์ชัน Win32 ดั้งเดิมที่สามารถตอบคำถามนั้นได้ การประกาศการนำเข้าสำหรับPeekMessage
และประเภทการสนับสนุนของมันดูเหมือนว่า:
[StructLayout(LayoutKind.Sequential)]
public struct NativeMessage
{
public IntPtr Handle;
public uint Message;
public IntPtr WParameter;
public IntPtr LParameter;
public uint Time;
public Point Location;
}
[DllImport("user32.dll")]
public static extern int PeekMessage(out NativeMessage message, IntPtr window, uint filterMin, uint filterMax, uint remove);
PeekMessage
โดยทั่วไปช่วยให้คุณดูข้อความถัดไปในคิว มันจะคืนค่าจริงหากมีอยู่จริงเป็นอย่างอื่น สำหรับวัตถุประสงค์ของปัญหานี้ไม่มีพารามิเตอร์ที่เกี่ยวข้องโดยเฉพาะ: เป็นเพียงค่าส่งคืนที่มีความสำคัญ วิธีนี้ช่วยให้คุณสามารถเขียนฟังก์ชั่นที่จะบอกคุณว่าแอปพลิเคชันยังคงว่างอยู่ (นั่นคือยังไม่มีข้อความในคิว):
bool IsApplicationIdle () {
NativeMessage result;
return PeekMessage(out result, IntPtr.Zero, (uint)0, (uint)0, (uint)0) == 0;
}
ตอนนี้คุณมีทุกสิ่งที่คุณต้องการในการเขียนลูปเกมทั้งหมดของคุณ:
class MainForm : Form {
public MainForm () {
Application.Idle += HandleApplicationIdle;
}
void HandleApplicationIdle (object sender, EventArgs e) {
while(IsApplicationIdle()) {
Update();
Render();
}
}
void Update () {
// ...
}
void Render () {
// ...
}
[StructLayout(LayoutKind.Sequential)]
public struct NativeMessage
{
public IntPtr Handle;
public uint Message;
public IntPtr WParameter;
public IntPtr LParameter;
public uint Time;
public Point Location;
}
[DllImport("user32.dll")]
public static extern int PeekMessage(out NativeMessage message, IntPtr window, uint filterMin, uint filterMax, uint remove);
}
นอกจากนี้วิธีการนี้ยังจับคู่ใกล้เคียงที่สุดเท่าที่จะเป็นไปได้ (ด้วยการพึ่งพา P / Invoke น้อยที่สุด) กับลูปเกมมาตรฐานของ Windows ซึ่งเป็นที่ยอมรับ:
while (!done) {
if (PeekMessage(&message, window, 0, 0, PM_REMOVE)){
TranslateMessage(&message);
DispatchMessage(&message);
}
else {
Update();
Render();
}
}