суббота, 27 апреля 2013 г.

Ещё правки в VCL (9)


procedure TScrollingWinControl.WMSize(var Message: TWMSize);
var
  NewState: TWindowState;
////////////////////////////////////////////////////////////////////////////////
//
// Дата изменений:                                                           {V}
//   26/11/2004                                                              {V}
// Причина изменений:                                                        {V}
//                                                                           {V}
// ***************************** ОКРУЖЕНИЕ ********************************* {V}
// Есть форма, на которой находятся два компонента, один с Align = alNone,   {V}
// другой с Align = alClient.                                                {V}
//                                                                           {V}
// ***************************** ПРОБЛЕМА ********************************** {V}
// При восстановлении окна у компонента, у которого Align = alClient не      {V}
// рисовались полосы прокрутки, в случае когда на форме в правом нижнем углу {V}
// находился компонент с Align = alNone.                                     {V}
//                                                                           {V}
// *************************** ЧТО ПРОСХОДИЛО ****************************** {V}
// 1. После восстановления окна компонент с Align = alNone уходил за пределы {V}
//    клиентской области формы, у формы появлялись полосы прокрутки;         {V}
// 2. TControl.AlignControls вызываемая по WM_SIZE, перед размещением        {V}
//    компонентов, вычисляет клиентскую область используя                    {V}
//    TControl.AdjustClientRect (virtual), которая перекрыта у               {V}
//    TScrollingWinControl и учитывает скроллеры окна:                       {V}
//
//    Rect := Bounds(-HorzScrollBar.Position, -VertScrollBar.Position,
//      Max(HorzScrollBar.Range, ClientWidth), Max(ClientHeight,
//      VertScrollBar.Range));
//    inherited AdjustClientRect(Rect);
//
// 3. Учитывая, что до восстановления окна компонент с Align = alNone        {V}
//    находился в правом, нижнем углу получается, что после вычисления       {V}
//    клиентская область до восстановления и после восстановления осталась   {V}
//    такой же и для компонента с Align = alClient размер окна не            {V}
//    изменился (AdjustClientRect до и после одинаковая);                    {V}
// 4. Далее происходит размещение компонента Align = alNone не на основе     {V}
//    AdjustClientRect, а на основе клиентской области windows ClientRect.   {V}
//    Его перемещают, в соответствии с его Anchors, в пределы клиентской     {V}
//    области формы и скроллеры исчезают;                                    {V}
// 5. AdjustClientRect изменилась, но компоненты которые уже разместили об   {V}
//    этом не узнали;                                                        {V}
//                                                                           {V}
// ****************************** РЕЗЮМЕ *********************************** {V}
// Поэтому реакция на изменение размеров происходит в цикле, и если на       {V}
// выходе размер вычисляемой клиентской области изменился то нужно           {V}
// переразместить компоненты;                                                {V}
//
////////////////////////////////////////////////////////////////////////////////
   lBeforeClientRect : TRect;                                                {V}
   lAfterClientRect  : TRect;                                                {V}
   lCycleCount : Integer;
////////////////////////////////////////////////////////////////////////////////
begin
////////////////////////////////////////////////////////////////////////////////
 lCycleCount := 0;
 repeat                                                                      {V}
  Inc(lCycleCount);
  lBeforeClientRect := GetClientRect;                                        {V}
  AdjustClientRect(lBeforeClientRect);                                       {V}
////////////////////////////////////////////////////////////////////////////////
  Inc(FAutoRangeCount);
  try
    inherited;
    NewState := wsNormal;
    case Message.SizeType of
      SIZENORMAL: NewState := wsNormal;
      SIZEICONIC: NewState := wsMinimized;
      SIZEFULLSCREEN: NewState := wsMaximized;
    end;
    Resizing(NewState);
  finally
    Dec(FAutoRangeCount);
  end;
  FUpdatingScrollBars := True;
  try
    CalcAutoRange;
  finally
    FUpdatingScrollBars := False;
  end;
  if FHorzScrollBar.Visible or FVertScrollBar.Visible then
    UpdateScrollBars;
////////////////////////////////////////////////////////////////////////////////
  lAfterClientRect := GetClientRect;                                         {V}
  AdjustClientRect(lAfterClientRect);                                        {V}
 until EqualRect(lBeforeClientRect, lAfterClientRect)                        {V}
       or (lCycleCount > 8); // устраняем зависание - http://mdp.garant.ru/pages/viewpage.action?pageId=300033419&focusedCommentId=333546939#comment-333546939
////////////////////////////////////////////////////////////////////////////////
end;

Комментариев нет:

Отправить комментарий