2013-05-25 17 views
13

Trong bản demo của tôi kinda appSự khác nhau hợp lý giữa PostQuitMessage() và DestroyWindow() là gì?

case WM_CLOSE: 
    DestroyWindow(hndl); 
    return 0; 

case WM_CLOSE: 
    PostQuitMessage(0); 
    return 0; 

làm như vậy. Có gì khác đằng sau tấm rèm khi gọi mỗi cái? DestroyWindow có trực tiếp hơn không, khi PostQuitMessage phải đi qua vòng lặp getmessage trả về false?

+4

Hãy xem xét điều gì có thể xảy ra trong một ứng dụng có nhiều cửa sổ. 'DestroyWindow' phá hủy một cửa sổ. 'PostQuitMessage' ... đăng một thông điệp thoát: có nghĩa là nó cho biết toàn bộ ứng dụng muốn thoát. – jalf

+0

@jalf, tôi đã * chỉ * chỉnh sửa nội dung đó vào câu trả lời của tôi: p – chris

+0

@chris và tôi vừa mới bỏ phiếu cho câu trả lời của bạn. :) – jalf

Trả lời

14

DestroyWindow phá hủy cửa sổ (ngạc nhiên) và đăng một WM_DESTROY (bạn cũng sẽ nhận được WM_NCDESTROY) vào hàng đợi thư. Đây là hành vi mặc định của WM_CLOSE. Tuy nhiên, chỉ vì một cửa sổ bị phá hủy không có nghĩa là vòng lặp thông báo sẽ kết thúc. Điều này có thể là trường hợp có một cửa sổ cụ thể kết thúc ứng dụng khi đóng và những người khác không làm gì với ứng dụng khi đóng (ví dụ: trang tùy chọn).

PostQuitMessage đăng một số WM_QUIT vào hàng đợi thư, thường làm cho vòng lặp thư kết thúc. Ví dụ: GetMessage sẽ trả về 0 khi nó kéo ra WM_QUIT. Điều này thường được gọi trong trình xử lý WM_DESTROY cho cửa sổ chính của bạn. Đây không phải là hành vi mặc định; Bạn phải làm điều đó cho chính bản thân mình.

+0

hiểu rồi! Cảm ơn nhiều! –

+0

@rails_has_elegance, Rất vui được trợ giúp. Tốt hơn nhiều để có được sự nhầm lẫn ra khỏi con đường trước đó. – chris

14

Không có đoạn mã nào là chính xác. Việc đầu tiên sẽ làm những gì các thủ tục cửa sổ mặc định đã làm khi nó xử lý tin nhắn WM_CLOSE như vậy là thừa. Nhưng nếu không làm cho ứng dụng thoát, nó sẽ tiếp tục chạy và bạn thường phải ép buộc trình gỡ lỗi dừng lại với Debug + Stop Debugging. Nếu bạn chạy nó mà không có một trình gỡ lỗi thì bạn sẽ để lại quá trình đang chạy nhưng không có một cửa sổ để bạn không thể biết nó đang chạy. Sử dụng tab Taskmgr.exe, Quy trình để xem các quy trình zombie đó.

Đoạn thứ hai sẽ chấm dứt ứng dụng nhưng sẽ không dọn dẹp đúng cách vì bạn không chuyển thông điệp WM_CLOSE đến quy trình cửa sổ mặc định. Cửa sổ không bị phá hủy. Mặc dù hệ điều hành sẽ dọn dẹp cho bạn vì vậy tất cả sẽ kết thúc tốt đẹp, chỉ cần không có bất kỳ điểm thưởng nào cho sự sang trọng.

Cách thích hợp để thực hiện việc này là thoát khi cửa sổ chính của bạn bị hủy. Bạn sẽ biết điều đó từ thông báo WM_DESTROY được gửi khi điều đó xảy ra:

case WM_DESTROY: 
    PostQuitMessage(0); 
    return 0; 
+0

Cảm ơn bạn đã trả lời! Vì vậy, từ sự hiểu biết của tôi các DestroyWindow() chức năng trong WM_CLOSE kiểm tra nếu nó là cửa sổ ứng dụng chính (cửa sổ cha mẹ) sẽ được đóng lại, và nếu đúng, nó phát ra một tin nhắn WM_DESTROY. Nếu không, chỉ cửa sổ (con) được đóng và ứng dụng vẫn tiếp tục chạy. –

+3

Không, bất kỳ cửa sổ nào sẽ gửi WM_DESTROY khi nó bị hủy. Bản thân Windows không có ưu tiên đặc biệt cho một cửa sổ, nó cũng tốt với một ứng dụng không có cửa sổ nào cả. Vì vậy, công việc của bạn là quan tâm đến cửa sổ * cụ thể * gửi thông điệp đó. Và nếu nó là cửa sổ chính của bạn đã bị phá hủy và không có gì còn lại thì bạn nên thoát khỏi chương trình của bạn vì người dùng không thể làm bất cứ điều gì hữu ích nữa. Mà bạn làm bằng cách gọi PostQuitMessage khi bạn nhận được WM_DESTROY cho cửa sổ đó. –

+0

Tôi xin lỗi nếu tôi hiểu lầm, nhưng nếu hiệu quả mỗi khi một cửa sổ (ví dụ như con) đóng, nó sẽ gửi một WM_DESTROY, không phải lúc nào cũng có nghĩa là bạn thoát khỏi vòng lặp và thoát khỏi ứng dụng? Trường hợp của logic mà vấn đề PostQuitMessage (0) độc quyền nếu WM_DESTROY đến từ cửa sổ chính? –

0

PostQuitMessage không nhất thiết có nghĩa là kết thúc đơn đăng ký. Nó chỉ đơn giản là gửi WM_QUIT đến vòng lặp tin nhắn và cho phép bạn thoát khỏi vòng lặp tin nhắn, vì vậy trong hầu hết các trường hợp, điều này có nghĩa là kết thúc của ứng dụng. Tuy nhiên, trong một ứng dụng đa luồng, nếu bạn có vòng lặp tin nhắn cho mỗi luồng được tạo, PostQuitMessage chỉ đóng luồng đó. Là một lưu ý phụ, nếu bạn cần nhiều dòng mã hơn để thực thi sau vòng lặp thông báo (chẳng hạn như dọn dẹp thêm), PostQuitMessage là một cách tốt hơn để đi, vì DestroyWindow phá hủy cửa sổ mà không phải thông qua thông báo lặp lại, bỏ qua bất kỳ mã làm sạch nào còn lại sau vòng lặp tin nhắn. Một số có thể gọi nó là một thực hành mã hóa không tốt, nhưng đôi khi bạn không thể tránh được những tình huống như thế.

Các vấn đề liên quan