2008-12-22 6 views
5

Tôi muốn hiển thị hộp thoại không mod trên màn hình và hiển thị một số thông tin trong đó.Làm thế nào tôi có thể hiển thị một hộp thoại và thông tin hiển thị vô dụng trong đó ngay lập tức?

Tuy nhiên nếu tôi sử dụng nó theo cách sau đây, nó có một số vấn đề:

function() 
{ 
showdialog(XXX). 
//heavy work. 
update the dialog.. 
//heavy work. 
update the dialog... 
} 

Dường như hộp thoại xuất hiện, nhưng nó không rút ra bất kỳ thông tin trong đó. Nó chỉ vẽ tất cả thông tin khi hàm kết thúc.

Làm cách nào tôi có thể sửa đổi hộp thoại không modeless để hộp thoại này sẽ hiển thị thông tin ngay lập tức?

Trả lời

5

Có một vài điều bạn có thể làm.

(1) Bạn có thể bài hộp thoại nhắn từ bên trong CDialog :: OnInitDialog phương pháp và sau đó xử lý các chức năng lâu trong xử lý thông điệp rằng thông điệp được đăng. Bằng cách đó, hộp thoại đầu tiên sẽ được hiển thị và sau đó chức năng dài sẽ chạy.

(2) Tùy chọn thứ hai là đảm bảo vòng lặp tin nhắn nhận được một số thời gian xử lý. Vì vậy, nếu chức năng dài của bạn là một số loại vòng lặp chỉ cần thêm các cuộc gọi thường xuyên để các ProcessMessages để đảm bảo hàng đợi thông điệp được giữ trống:

void ProcessMessages() 
{ 
    MSG msg; 
    CWinApp* pApp = AfxGetApp(); 
    while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) 
    { 
     pApp->PumpMessage(); 
    } 
} 

Edit: Nó chắc chắn là có thể sử dụng đề là như vậy một tình huống, nhưng làm như vậy không phải lúc nào cũng không có rủi ro và phức tạp.

Sử dụng đề với một giao diện phương tiện phải đối phó với nhiều hàng đợi thông điệp mà sau đó có nghĩa là sử dụng của API như PostThreadMessage và giới thiệu một bộ mới của vấn đề cần được cảnh giác.

Đối với một ví dụ về một vấn đề như tham khảo liên kết này:

http://msdn.microsoft.com/en-us/library/ms644946(VS.85).aspx

đâu nói:

Tin nhắn được gửi bởi PostThreadMessage là không liên quan đến một cửa sổ. Theo quy tắc chung là , các thư không phải là được liên kết với một cửa sổ không được là được gửi bởi hàm DispatchMessage . Do đó, nếu người nhận luồng đang trong một vòng lặp phương thức (được sử dụng bởi Hộp thư hoặc Hộp thoại), các thông báo sẽ bị mất. Để chặn thư chủ đề trong khi ở chế độ phương thức, hãy sử dụng móc cụ thể theo chủ đề.

Tôi sử dụng phương pháp thông báo quá trình trong Zeus IDE và hoạt động rất tốt tại đảm bảo GUI vẫn đáp ứng với người dùng. Nó cũng có lợi thế là rất dễ thực hiện.

+2

IMO Hàm ProcessMessage() là cách thêm phản hồi vào ứng dụng MFC. – Hapkido

+2

Tôi cũng sẽ sử dụng tùy chọn ProcessMessage;) – jussij

+0

Tôi rất không đồng ý. 1) Một phương thức giao diện người dùng không nên thực hiện nhiều tác phẩm "khác", các mối quan ngại phải được tách riêng. 2) Một chuỗi công nhân đơn giản có thể được sử dụng trong hầu hết các tình huống này, không cần nhiều bơm. Tại sao bạn đang cố gắng để scare OP đi từ chủ đề? –

2

Theo nguyên tắc, các phép tính nặng không bao giờ được đặt trong luồng GUI. Vì nó là một hộp thoại vô dụng, hộp thoại sẽ không sở hữu vòng lặp tin nhắn.Giải pháp ProcessMessage() sẽ hoạt động, nhưng IMO không đúng cách. Đề xuất của tôi là: 1) Tạo ra một chuỗi mới trong OnInitDialog() 2) Có các thông điệp bài đăng riêng biệt gửi đến hộp thoại khi có điều gì đó thú vị xảy ra. Một trong những điều thú vị là công việc được thực hiện.

Lưu ý, tuy nhiên, điều này có nghĩa là bạn cần thực hiện đồng bộ hóa phù hợp.

4

Trong OnInitDialog, bắt đầu một chuỗi công nhân để thực hiện các tính toán. Đăng thông báo của người dùng từ chuỗi công nhân để cập nhật hộp thoại.

Đây là vượt trội so với việc thực hiện ProcessMessages vì ​​nhiều lý do:

  • Mã cho làm các tính toán có thể được tách ra khỏi các mã giao diện người dùng, nơi mà nó không thuộc về.

  • Giao diện người dùng vẫn đáp ứng trong khi các tính toán thực tế đang được thực hiện. ProcessMessages cho phép nhiều cập nhật giao diện người dùng trong suốt quá trình tính toán đơn lẻ, nhưng giao diện người dùng vẫn sẽ bị chặn trong quá trình tính toán thực tế.

đang Dialog:

#define WM_NEW_COUNT (WM_USER + 0x101) 

BEGIN_MESSAGE_MAP() 
    ON_MESSAGE(WM_NEW_COUNT, OnNewCount) 
END_MESSAGE_MAP() 

BOOL CMyDialog::OnInitDialog() 
{ 
    CWinThread* pThread = AfxBeginThread(MyCountFunc, this->GetSafeHwnd()); 
    return TRUE; 
} 

LRESULT CMyDialog::OnNewCount(WPARAM wParam, LPARAM) 
{ 
    int newCount = (int)wParam; 

    // m_count is DDX member, e.g. for label 
    m_count = newCount; 

    UpdateData(FALSE); 

    return 0; 
} 

Các sợi nhân:

UINT MyCountFunc(LPVOID lParam) 
{ 
    HWND hDialogWnd = (HWND)lParam; 

    for (int i=0; i < 100; ++i) 
    { 
     PostMessage(hDialogWnd, WM_NEW_COUNT, i, NULL); 
    } 
} 
1

Đừng cố gắng làm công việc nặng nhọc của bạn tất cả cùng một lúc. Để hộp thoại tự đăng một tin nhắn trong phạm vi WM_APP trong OnInitDialog. Trình xử lý WM_APP có thể thực hiện một phần công việc nặng nhọc, sau đó thực hiện một PostMessage khác và trả về. Bằng cách này, bạn cho phép máy bơm thông báo xử lý các thông điệp cửa sổ ở giữa các phần xử lý của bạn.