Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.01.08;
Скачать: CL | DM;

Вниз

Как определить видимость дочернего окна?   Найти похожие ветки 

 
Aleksandr.   (2005-12-07 14:44) [0]

в MDI-приложении открыто несколько дочерних окон с таблицами данных.
Есть глобальные процедуры добавления данных, от дочерних окон не зависящие, в них при успешном добавлении всем дочерним окнам просто посылается сообщение с кодом таблицы.
В WndProc дочернего окна обработка этого сообщения осуществляется следующим образом - если окно является MainForm.ActiveMDIChild и код совпадает, то данные перечитываются, а если код совпадает, но окно не является ActiveMDIChild, то устанавливается флаг, чтобы они перечитались на FormActivate.
И выплыла одна проблема: если открыть два дочерних окна с разными таблицами, расположить их мозаикой, а затем при активном окне Child1 вызвать добавление данных в Table2, то в обработке WndProc с сообщением Код2 окно Child2 совершенно логично не будет считать себя активным и не перечитает данные до своей активации.
Возникает вопрос, как, чтобы не ломать логику, окну определить, что оно, не будучи ActiveMDIChild, видимо полностью или частично из-под верхнего MDIChild?


 
Игорь Шевченко ©   (2005-12-07 15:07) [1]


> Возникает вопрос, как, чтобы не ломать логику, окну определить,
>  что оно, не будучи ActiveMDIChild, видимо полностью или
> частично из-под верхнего MDIChild?


А не проще ли по активации обновляться ? Определить-то можно, я даже код могу дать, только вот сдается мне, что это кривое решение - обновлять, если видимо.

unit main;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 ExtCtrls;

type
 TfMain = class(TForm)
   Timer1: TTimer;
   procedure Timer1Timer(Sender: TObject);
 private
   procedure DisplayVisiblePortion();
   function CalcVisiblePortion() : Integer;
 end;

var
 fMain: TfMain;

implementation

{$R *.DFM}

function RectSquare (const Rect : TRect) : Integer;
begin
 with Rect do
   Result := (Right - Left) * (Bottom - Top);
 if Result < 0 then
   Result := - Result;
end;

type
 TRectArray = array[0..16384] of TRect;
 PRectArray = ^TRectArray;

function RgnSquare (Rgn : HRGN) : Integer;
var
 DataSize : DWORD;
 RgnData : PRGNDATA;
 Rectangles : PRectArray;
 I : Integer;
begin
 Result := 0;
 DataSize := GetRegionData(Rgn, 0, nil);
 if DataSize > 0 then begin
   GetMem(RgnData, DataSize);
   try
     GetRegionData(Rgn, DataSize, RgnData);
     Rectangles := PRectArray(@RgnData.Buffer);
     for I:=0 to Pred(RgnData^.rdh.nCount) do
       Inc(Result, RectSquare(Rectangles^[I]));
   finally
     FreeMem(RgnData, DataSize);
   end;
 end;
end;

function CalcSquarePortion (SquareWhole, SquarePart : Integer) : Integer;
begin
 if SquarePart >= SquareWhole then
   Result := 100
 else
   Result := Trunc((SquarePart / SquareWhole) * 100);
end;

function TfMain.CalcVisiblePortion: Integer;
var
 SiblingRect : TRect;
 Workarea : TRect;
 WinRect : TRect;
 Tmp : TRect;
 VisiblePortion : TRect;
 Sibling : HWND;
 WindowSquare : Integer;
 WindowRgn, Rgn, TmpRgn : HRGN;
begin
 if IsIconic(Handle) then begin
   Result := 0;
   Exit;
 end;
 Rgn := CreateRectRgn (0, 0, 0, 0);
 try
   SystemParametersInfo(SPI_GETWORKAREA, 0, @Workarea, 0);
   GetWindowRect(Handle, WinRect);
   WindowSquare := RectSquare(WinRect);
   IntersectRect(VisiblePortion, WinRect, WorkArea);
   Result := CalcSquarePortion(WindowSquare, RectSquare(VisiblePortion));
   if Result > 0 then begin
     WindowRgn := CreateRectRgnIndirect(VisiblePortion);
     try
       Sibling := GetWindow(Handle, GW_HWNDPREV);
       while (Sibling <> 0) and (Result > 0) do begin
         if IsWindowVisible(Sibling) and not IsIconic(Sibling) then begin
           GetWindowRect(Sibling, SiblingRect);
           IntersectRect(Tmp, VisiblePortion, SiblingRect);
           if not IsRectEmpty(Tmp) then begin
             TmpRgn := CreateRectRgnIndirect(Tmp);
             try
               if CombineRgn(Rgn, Rgn, TmpRgn, RGN_OR) = ERROR then
                 RaiseLastWin32Error();
             finally
               DeleteObject(TmpRgn);
             end;
           end;
           TmpRgn := CreateRectRgn(0, 0, 0, 0);
           if CombineRgn(TmpRgn, WindowRgn, Rgn, RGN_DIFF) = ERROR then
             RaiseLastWin32Error();
           Result := CalcSquarePortion(WindowSquare, RgnSquare(TmpRgn));
           DeleteObject(TmpRgn);
         end;
         Sibling := GetWindow(Sibling, GW_HWNDPREV);
       end;
     finally
       DeleteObject(WindowRgn);
     end;
   end;
 finally
   DeleteObject(Rgn);
 end;
end;

procedure TfMain.DisplayVisiblePortion;
begin
 Caption := Format ("%d%% percents visible", [CalcVisiblePortion()]);
end;

procedure TfMain.Timer1Timer(Sender: TObject);
begin
 DisplayVisiblePortion();
end;

end.


 
Aleksandr.   (2005-12-07 15:18) [2]

Игорь Шевченко © :

Спасибо за код, попробую применить его у себя. А насчет по активации обновляться - я рассуждал также, но тестировщики выдали требование, чтобы добавлении записи было видно, а то им непонятно происходящее - диалог они закрыли, а в таблице данных нет. А всякие там синие заголовки окон рассматривать - активны или нет, - им недосуг.


 
Rouse_ ©   (2005-12-07 15:18) [3]

Может быть лучше проверять - если дочернее окно не свернуто - то пусть перечитывает, или при большом их кол-ве заметные тормоза?


 
Aleksandr.   (2005-12-07 15:55) [4]

Rouse_ ©  :

Да, наборы данных очень большие, и одновременная перезагрузка нескольких окон даст очень большой тормоз.



Страницы: 1 вся ветка

Текущий архив: 2006.01.08;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.018 c
14-1134409257
Энди
2005-12-12 20:40
2006.01.08
Проблема спящего брадобрея


14-1134683046
Kerk
2005-12-16 00:44
2006.01.08
Знаменитый фильм с Тимошенко в главной роли :)


2-1134921456
Out84
2005-12-18 18:57
2006.01.08
Time


2-1135085690
sanich
2005-12-20 16:34
2006.01.08
Сортировка в DbGridEh


2-1135142913
Wood
2005-12-21 08:28
2006.01.08
Про Application.MessageBox...