2009-04-09 28 views
13

Tôi tạo một cửa sổ với CreateWindow() và hiển thị nó với ShowWindow(). Nhưng cửa sổ cha mà trên đó được tạo ra sẽ bị vô hiệu hóa cho đến khi người dùng trở về từ cửa sổ này, tức là nó sẽ mô phỏng hộp thoại phương thức.Tạo cửa sổ phương thức win32 với CreateWindow

Trả lời

3

Bạn cần xem xét ý nghĩa của một cửa sổ phương thức - về cơ bản, cha mẹ của cửa sổ bị tắt. Cách tự động duy nhất để làm điều này (mà tôi biết) là gọi DialogBox() để tạo một hộp thoại phương thức. Tuy nhiên, vì bạn muốn sử dụng CreateWindow(), thì tất cả những gì bạn cần làm là tự mình vô hiệu cửa sổ chính. Lý tưởng nhất, nó sẽ là tốt hơn để đi các tuyến đường hộp thoại (kể từ khi hệ điều hành biết chính xác những gì phải được thực hiện để tạo ra một cửa sổ phương thức), nhưng tôi cho rằng tùy chọn này là có nếu bạn phải sử dụng nó.

12

Modality, part 1: UI-modality vs code-modality giải thích cách thực hiện việc này và lý do bạn có thể không muốn.

+6

Theo quy tắc, tôi sẽ bỏ phiếu cho tất cả các tài liệu tham khảo Old New Thing. – Aardvark

+0

Tài liệu tham khảo cũ mới là tuyệt vời, nhưng quá tệ, đó là một liên kết chỉ trả lời. Bạn có thể muốn thuật lại một số nội dung từ bài viết theo từ của riêng bạn. – jrh

16

Đảm bảo bạn đặt hwndParent trong CreateWindow và sử dụng EnableWindow(hwndParent, FALSE) để tắt cha mẹ sau khi hiển thị cửa sổ bật lên. Sau đó bật phụ huynh với EnableWindow(hwndParent, TRUE) sau khi cửa sổ bật lên đã bị đóng.

+3

Bạn phải 'EnableWindow (hwndParent, TRUE)' * trước * cửa sổ bật lên bị đóng, xem [Thứ tự đúng để tắt và bật cửa sổ] (http://blogs.msdn.com/b/oldnewthing/archive/2004 /02/27/81155.aspx) –

2

Bạn cũng có thể chạy "vòng lặp tin nhắn phụ" giúp cửa sổ cha không hoạt động cho đến khi công việc của bạn kết thúc với hộp thoại "phương thức".

0

Được rồi, tôi chỉ vật lộn với cùng một vấn đề này. Tôi cần một hộp thoại nhanh mà cư xử như nó sẽ nếu tôi sử dụng DialogBox() nhưng tôi không muốn tạo một mẫu cho dự án cụ thể tôi đã sử dụng.

Điều tôi phát hiện ra là nếu bạn vô hiệu hóa cửa sổ cha của hộp thoại, bạn cũng vô hiệu hóa hộp thoại. Và bạn không thể bật hộp thoại đó mà không bật lại hộp thoại chính. Vì vậy, phương pháp đó sẽ không hoạt động.

Tôi cũng phát hiện ra rằng bạn không thể sử dụng SetCapture()/ReleaseCapture() vì sau đó cửa sổ con của hộp thoại sẽ không nhận được tin nhắn.

Tôi đã tìm được giải pháp hoạt động: Sử dụng bơm thông báo cục bộ, được điều khiển bởi PeekMessage() hoặc GetMessage(). Đây là mã làm việc cho tôi:

while (!m_bFinished) 
    { 
    BOOL bEat; 

    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
    { 
     if (msg.message == WM_CHAR) 
     { 
      if (msg.wParam == VK_ESCAPE) 
      { 
       m_bFinished = TRUE; 
       continue; 
      } 
     } 

     bEat = FALSE; 

     if (msg.message >= WM_MOUSEFIRST && 
      msg.message <= WM_MOUSELAST) 
     { 
      RECT rectMe; 

      pcMe->GetWindowRect(&rectMe); 
      if (!::PtInRect(&rectMe, msg.pt)) 
       bEat = TRUE; 
     } 

     if (!bEat) 
     { 
      ::TranslateMessage(&msg); 
      ::DispatchMessage(&msg); 
     } 
    } 
    } 

Điều này có hiệu quả là "ăn" bất kỳ thông điệp chuột nào nằm ngoài vùng ứng dụng của cửa sổ cho tất cả thư được gửi đến ứng dụng đó. Nó không cấm nhấp chuột bên ngoài ứng dụng, chỉ cần nhấp vào bất kỳ nơi nào bên trong ứng dụng không nằm trong vùng máy khách của cửa sổ "phương thức". Nếu bạn thêm một MessageBeep() khi bạn ăn một tin nhắn bạn sẽ nhận được hành vi chính xác giống như một hộp thoại thực sự phương thức.

m_bĐược hoàn thành là thành viên BOOL của lớp và được đặt nếu nút OK hoặc Hủy được truy cập trên "hộp thoại" và trong các điều kiện nhất định nằm ngoài phạm vi đoạn mã tại đây.

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