2009-03-14 27 views
8

Tôi cần một cách để điều khiển tùy chỉnh (xuống từ TCustomControl) để biết liệu nó có hiển thị hay không. Tôi không nói về tài sản .Visible; Tôi có nghĩa là có hay không nó thực sự được hiển thị trên màn hình vào lúc này. Có ai biết cách để làm điều này không?Làm thế nào tôi có thể biết liệu một điều khiển Delphi hiện có thể nhìn thấy?

+0

Bạn có nghĩa là nó có được bao phủ bởi một cửa sổ khác không? –

+0

Tôi có nghĩa là nó có được vẽ lên màn hình hay không. Được bảo hiểm có thể là một lý do. Khác có thể là nếu nó được đặt trên một biểu mẫu đã được tạo nhưng chưa được hiển thị. –

Trả lời

15

Một vài năm trước tôi đã có cùng một loại vấn đề đối với Biểu mẫu: Tôi đang tìm cách xác định xem Biểu mẫu có thực sự hiển thị (thậm chí chỉ một phần) cho người dùng hay không.
Đặc biệt khi được cho là hiển thị và Hiển thị là Đúng nhưng cửa sổ thực sự hoàn toàn nằm sau một cửa sổ khác.
Đây là mã, nó có thể được điều chỉnh cho một WinControl ...

{----------------------------------------------------------} 
function IsMyFormCovered(const MyForm: TForm): Boolean; 
var 
    MyRect: TRect; 
    MyRgn, TempRgn: HRGN; 
    RType: Integer; 
    hw: HWND; 
begin 
    MyRect := MyForm.BoundsRect;   // screen coordinates 
    MyRgn := CreateRectRgnIndirect(MyRect); // MyForm not overlapped region 
    hw := GetTopWindow(0);     // currently examined topwindow 
    RType := SIMPLEREGION;     // MyRgn type 

// From topmost window downto MyForm, build the not overlapped portion of MyForm 
    while (hw<>0) and (hw <> MyForm.handle) and (RType <> NULLREGION) do 
    begin 
    // nothing to do if hidden window 
    if IsWindowVisible(hw) then 
    begin 
     GetWindowRect(hw, MyRect); 
     TempRgn := CreateRectRgnIndirect(MyRect);// currently examined window region 
     RType := CombineRgn(MyRgn, MyRgn, TempRgn, RGN_DIFF); // diff intersect 
     DeleteObject(TempRgn); 
    end; {if} 
    if RType <> NULLREGION then // there's a remaining portion 
     hw := GetNextWindow(hw, GW_HWNDNEXT); 
    end; {while} 

    DeleteObject(MyRgn); 
    Result := RType = NULLREGION; 
end; 

function IsMyFormVisible(const MyForm : TForm): Boolean; 
begin 
    Result:= MyForm.visible and 
      isWindowVisible(MyForm.Handle) and 
      not IsMyFormCovered(MyForm); 
end; 
+0

Cảm ơn! Đó là chính xác những gì tôi đang tìm kiếm. –

2

Bạn có thể đính kèm mã vào sự kiện OnPaint không? Điều này được gọi là rất thường xuyên và tôi nghĩ rằng chỉ được gọi khi kiểm soát thực sự sẽ được sơn (ví dụ như có thể nhìn thấy theo cách bạn có ý nghĩa).

+0

Tôi sẽ đi với điều này như một chỉ báo tốt nhất. Bạn không bao giờ có thể chắc chắn vì trong Vista tất cả các ứng dụng đều vẽ ra một bitmap ngoài màn hình, sau đó được bao gồm trong card đồ họa với các lớp phủ, v.v. – mj2008

+0

Nhưng có lẽ nó vẫn được vẽ ra khỏi màn hình nếu nó được hiển thị trên màn hình tại thời điểm này ? –

+1

Tôi không nghĩ rằng nó an toàn để giả định rằng WM_PAINT sẽ chỉ xuất hiện khi những pixel đó sắp chạm màn hình. Với Desktop Desktop (http://msdn.microsoft.com/en-us/library/aa969540%28VS.85%29.aspx), Windows giữ một bộ nhớ đệm các cửa sổ được vẽ cho các hiệu ứng như Windows Flip (http: // www. microsoft.com/windows/windows-vista/features/flip-3d.aspx) có thể yêu cầu * tất cả * cửa sổ cùng một lúc. Bởi vì điều này, tôi hy vọng rằng có thể có một số bộ nhớ cache làm mới nền. –

1

Tôi nghĩ đây là những gì TWinControl.Showing dành cho. Tôi không chắc nó đáng tin cậy như thế nào.

+1

Nó không hoạt động cho một Mẫu chẳng hạn. Biểu mẫu có thể hoàn toàn nằm sau một biểu mẫu khác và vẫn hiển thị đúng. –

+0

Như tôi đã nói, tôi không biết nó kỹ lưỡng như thế nào. –

+2

Chỉ hiển thị cho bạn biết liệu tất cả các điều khiển chính có hiển thị hay không. Nó phân biệt một số tình huống trong chế độ thiết kế, trong đó f.e. các thành phần không hiển thị được hiển thị. Vì vậy, nó sẽ cho bạn biết liệu các thành phần nếu hiển thị tại thời điểm này sẽ được hiển thị. –

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