2010-06-08 28 views
13

Nhiều lần sau thời đại Windows 98, chúng tôi đã trải qua một số hộp thoại mất Z-Order của họ và di chuyển trở lại biểu mẫu trước.Delphi - Cách ngăn Biểu mẫu/MsgBox di chuyển dưới biểu mẫu trước?

Ví dụ:

Dialog1.ShowModal; 

Dialog1.OnClickButton() : ShowMessage('anything'); 

Khi MessageBox xuất hiện, đôi khi nó không có trọng tâm và được di chuyển dưới Dialog1. Người dùng bị nhầm lẫn về điều đó, họ nói: Ứng dụng của tôi bị đóng băng !!! Nhưng nếu họ sử dụng Alt + Tab để di chuyển đến ứng dụng khác và ngược lại, tiêu điểm sẽ trở về MessageBox và nó sẽ là cửa sổ nền trước.

Chúng tôi đã trải nghiệm điều này với các biểu mẫu ShowMessage, MessageBox, biểu mẫu bình thường và cũng QuickReport.

Có ai biết về điều này không? Nó là một lỗi Windows? Làm thế nào bạn có thể ngăn chặn nó? Làm thế nào để nắm bắt điều này?

Nhờ sự giúp đỡ của bạn: dd


Tôi thực sự cho rằng SAU Win98, vì vậy tất cả các HĐH (Win7 cũng) bị ảnh hưởng bởi sự cố này. Chúng tôi đã sử dụng Delphi 6 Prof, vì vậy các thuộc tính không hoạt động với các biểu mẫu Mặc định.

Ai đó nói rằng hộp thoại tin nhắn có thể điều khiển được với MessageBox + MB_APPLMODAL. Đây là tin tốt, nhưng chúng tôi có nhiều hình thức và thành phần cũ, công cụ của bên thứ ba.

Vì vậy, thật khó để tạo ra một ứng dụng hoàn toàn mới với việc thay thế các biểu mẫu.

Nhưng chúng tôi sẽ cố gắng thực hiện việc này.

Tôi nghĩ câu trả lời là vấn đề nửa ứng dụng và một nửa vấn đề với Windows. Nếu Windows đôi khi xử lý điều này, và đôi khi không - đó có vẻ là một lỗi Windows. Nhưng nếu chúng ta có thể ép buộc tạo cửa sổ phương thức tốt thì đó là lỗi lập trình.

Ai đó có thể giải thích cho tôi ý nghĩa của cờ WS_POPUP là gì? Nó có tác dụng phụ hay không?

Thanks: dd

+0

Tôi cũng thường gặp vấn đề này, tôi cũng chưa tìm thấy câu trả lời. Mong đợi những gì mọi người đã đưa ra. –

+0

Với phiên bản này, điều gì đang xảy ra? –

+0

bạn là Windows 98? Wow. Như Sertac hỏi, phiên bản Delphi là rất quan trọng. Delphi 2007 và sau đó có một giải pháp thay thế. –

Trả lời

13

Đó là những gì PopupMode and PopupParent properties là dành cho.

Ví dụ: bạn có thể làm:

Dialog1.PopupMode := pmExplicit; 
Dialog1.PopupParent := self; 
Dialog1.ShowModal; 

này lệnh cho Windows đúng Z-trật tự.

+0

Ồ, [tài liệu về điều này] (http://docwiki.embarcadero.com/VCL/en/Forms.TForm.PopupMode) không hữu ích chút nào! Nhưng hãy thử nó; nó hoạt động! –

+1

@Craig - sẽ không trợ giúp với các tin nhắn ShowMessage, MessageBox và ngoại lệ .. –

+0

@Sertac, đó là các chức năng tiện lợi xung quanh các cửa sổ thông thường. Bạn có thể thực hiện các thông báo ngoại lệ tùy chỉnh bằng cách xử lý 'Application.OnException'. Tương tự như vậy, nếu bạn cần một 'ShowMessage' tùy chỉnh, bạn có thể viết một. –

6

Đối với các phiên bản cũ của delphi (trước Delphi 2007), về các hình thức khác hơn là hình thức chính của bạn:

interface 
    TMyForm = Class(TForm) 
    protected 
    procedure CreateParams(var Para: TCreateParams); override; 
    end; 
... 
implementation 
... 
procedure TMyForm.CreateParams(var Para: TCreateParams); 
begin 
    inherited; 
    Para.Style := Para.Style or WS_POPUP; 
    { WinXP Window manager requires this for proper Z-Ordering } 
    // Para.WndParent:=GetActiveWindow; 
    Para.WndParent := Application.MainForm.Handle; 
end; 

Đối với hộp thư bao gồm MB_TOPMOST trong cờ của bạn:

Application.MessageBox(PChar(amessage), PChar(atitle), otherflags or MB_TOPMOST); 
+0

Tôi cũng có một giải pháp cho Dialogs được tạo bằng đơn vị VCL Dialogs, trước Delphi 2007. Nếu ai đó cần (đối với các phiên bản trước năm 2007), hãy hỏi một câu hỏi mới và tôi sẽ đăng mã đó. –

0

Tôi nhìn trang này và Câu hỏi thường gặp trong nửa giờ và vẫn không thể tìm thấy cách đăng nhận xét, vì vậy hãy tha thứ cho tôi vì vi phạm giao thức này.

Trước hết tôi muốn làm rõ rằng poster, IMHO, không sử dụng Windows 98. Anh ấy viết "sau thời đại Windows 98" mà tôi hiểu có nghĩa là anh gặp sự cố này với phiên bản Windows sau 98.

Vì tôi cũng gặp vấn đề này (CB2009), tôi muốn nhấn mạnh câu hỏi của người đăng "Có phải lỗi Windows không?", Mà tôi chưa thấy câu trả lời. Nếu đó là một lỗi Delphi/Builder, có thể có một cách để tránh nó? Tôi không thể thấy cách chặn tất cả các hộp thoại tiềm năng là một giải pháp khả thi, cũng không tránh sử dụng fsStayOnTop. Tôi có một hình thức cài đặt cần phải ở trên đầu trang của hình thức chính của tôi, nhưng các hình thức cài đặt có thể và sẽ bật lên hộp thoại trong điều kiện nhất định sẽ biến mất dưới hình thức cài đặt.

Sẽ rất hữu ích nếu tôi hiểu nơi hỗ trợ đặt hàng z bị sai, vì nó có thể cung cấp một đầu mối về cách tránh nó.

+0

Đây là một lỗi cửa sổ, theo nghĩa, thứ tự Z của các biểu mẫu của bạn không được bảo tồn bởi kiến ​​trúc của "trình quản lý cửa sổ" bên trong Windows trong Windows XP, sau một thời điểm nhất định. Nó không phải là một lỗi cửa sổ, theo nghĩa Windows API không đảm bảo rằng nó sẽ nhớ một số loại Z-Order cụ thể tồn tại, trừ khi bạn đã đặt liên kết cha-cửa sổ của bạn một cách chính xác bằng cách sử dụng CreateParams (như tôi đã chỉ ra trong câu trả lời của tôi). –

+0

Ngẫu nhiên bạn có thể không thấy bất kỳ văn bản nào (có thể là màu xám) hay một nút có nhãn "Thêm bình luận" không? –

+0

Có, nhưng chỉ cho bài đăng của riêng tôi. Có lẽ một người chỉ được phép bình luận trên các bài viết khác nếu một người có đủ điểm, nhưng sau đó tôi có thể gửi trả lời .. Vì vậy, tôi không thấy logic trong này. Cũng không phải lý do tại sao lỗi này tồn tại btw, có vẻ dễ dàng, đủ để làm cho nó đúng. –

0

Một thủ thuật tôi đã sử dụng thời gian gần đây đã áp dụng hai dòng mã trong quá trình tạo mỗi hình thức:

SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or 
    WS_EX_APPWINDOW or WS_EX_TOPMOST); 
SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopWindow); 

Xử lý là handle của form (Form1.Handle). Phần WS_EX_APPWINDOW làm cho mỗi cửa sổ xuất hiện trên thanh tác vụ, loại bỏ nó nếu bạn không muốn có hiệu ứng bổ sung đó.

Đối với hình thức chính của tôi, tôi sử dụng dòng này:

SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or 
    WS_EX_TOPMOST); 

tôi cũng sử dụng chức năng này để giúp xây dựng các hộp thoại tùy chỉnh của tôi (tôi đã tạo ra một chức năng mới cho mỗi phong cách của hộp thoại - lỗi, xác nhận, vv) :

function CustomDlg(const AMessage : string; const ADlgType: TMsgDlgType; 
    const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn) : TForm; 
begin 
    Result := CreateMessageDialog(AMessage, ADlgType, AButtons, ADefaultButton); 
    with Result do 
    begin 
     SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or 
     WS_EX_APPWINDOW or WS_EX_TOPMOST); 
     SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopwindow); 
     FormStyle := fsStayOnTop; 
     BringToFront; 
    end; 
end; 

phần FormStyle := fsStayOnTop; là không bắt buộc, tất nhiên, nhưng tôi sử dụng nó để đảm bảo xác nhận và báo lỗi hộp thoại của tôi là luôn hiển thị với người dùng.

Có vẻ như một chút công việc nhưng hiệu ứng ròng là tôi không còn phải lo lắng về các biểu mẫu vô tình ẩn sau các biểu mẫu khác.

+0

Tôi nên thêm rằng với 'SetWindowLong()' chức năng bạn không cần phải tạo ra các hình thức tùy chỉnh của riêng bạn và có thể làm điều này với bất kỳ hình thức hiện có bạn có. Nếu bạn đã tạo các biểu mẫu tùy chỉnh thì hãy ghi đè 'CreateParams()' là cách để đi. –

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