А. Григорьев - О чём не пишут в книгах по Delphi Страница 39

Тут можно читать бесплатно А. Григорьев - О чём не пишут в книгах по Delphi. Жанр: Компьютеры и Интернет / Программирование, год -. Так же Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте «WorldBooks (МирКниг)» или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
А. Григорьев - О чём не пишут в книгах по Delphi

А. Григорьев - О чём не пишут в книгах по Delphi краткое содержание

Прочтите описание перед тем, как прочитать онлайн книгу «А. Григорьев - О чём не пишут в книгах по Delphi» бесплатно полную версию:
Рассмотрены малоосвещённые вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные механизмы их работы, особенности для протоколов TCP и UDP и др. Большое внимание уделено разбору ситуаций возникновения ошибок и получения неверных результатов в "простом и правильном" коде. Отдельно рассмотрены особенности работы с целыми, вещественными и строковыми типами данных, а также приведены примеры неверных результатов, связанных с ошибками компилятора, VCL и др. Для каждой из таких ситуаций предложены методы решения проблемы. Подробно рассмотрен синтаксический анализ в Delphi на примере арифметических выражений. Многочисленные примеры составлены с учётом различных версий: от Delphi 3 до Delphi 2007. Прилагаемый компакт-диск содержит примеры из книги.Для программистов

А. Григорьев - О чём не пишут в книгах по Delphi читать онлайн бесплатно

А. Григорьев - О чём не пишут в книгах по Delphi - читать книгу онлайн бесплатно, автор А. Григорьев

 R: TRect;

begin

 POldPanelWndProc(Msg);

 if Msg.Msg = WM_NCHITTEST then

 begin

  // Вся хитрость обработки сообщения WM_NCHITTEST

  // заключается в правильном переводе экранных координат

  // в клиентские и в несколько муторной проверке попадания

  // мыши на сторону рамки или в ее угол. Дело упрощается

  // тем, что у панели нет неклиентской части, поэтому

  // верхний левый угол окна и верхний левый угол клиентской

  // части совпадают.

  Pt := PanelHole.ScreenToClient(Point(Msg.LParamLo, Msg.LParamHi));

  if Pt.X < BorderMouseSensivity then

   if Pt.Y < CornerMouseSensivity then Msg.Result := HTTOPLEFT

   else

    if Pt.Y >= PanelHole.Height - CornerMouseSensivity then

Msg.Result := HTBOTTOMLEFT

    else Msg.Result := HTLEFT

   else

    if Pt.X >= PanelHole.Width - BorderMouseSensivity then

     if Pt.Y < CornerMouseSensivity then Msg.Result := HTTOPRIGHT

     else

      if Pt.Y >= PanelHole.Height - CornerMouseSensivity then

       Msg.Result := HTBOTTOMRIGHT

      else Msg.Result := HTRIGHT

    else

     if Pt.Y < BorderMouseSensivity then

      if Pt.X < CornerMouseSensivity then Msg.Result := HTTOPLEFT

      else

       if Pt.X >= PanelHole.Width - CornerMouseSensivity then

        Msg.Result := HTTOPRIGHT

       else Msg.Result := HTTOP

     else

if Pt.Y >= PanelHole.Height - BorderMouseSensivity then

       if Pt.X < CornerMouseSensivity then

        Msg.Result := HTBOTTOMLEFT

       else

        if Pt.X >= PanelHole.Width - CornerMouseSensivity then

         Msg.Result := HTBOTTOMRIGHT

        else Msg. Result := HTBOTTOM;

 end

 else if Msg.Msg = WM_SIZE then

 begin

  // Пересчитываем регион SetRegion;

  // Устанавливаем новые ограничения для размеров окна.

  // учитывающие новое положение дырки

  Constraints.MinWidth :=

   Width - ClientWidth + PanelHole.Left + MinHoleSize + HoleDistance;

  Constraints.MinHeight :=

   Height - ClientHeight + PanelHole.Top + MinHoleSize + HoleDistance;

 end

 else if Msg.Msg = WM_SIZING then

 begin

  // Копируем переданный прямоугольник в переменную R,

  // одновременно пересчитывая координаты из экранных

  // в клиентские

  R.TopLeft := ScreenToClient(PRect(Msg.LParam)^.TopLeft);

  R.BottomRight := ScreenToClient(PRect(Msg.LParam)^.BottomRight);

  // Если ширина слишком мала, проверяем, за какую

  // сторону тянет пользователь. Если за левую -

  // корректируем координаты левой стороны, если за

  // правую - ее координаты

  if R.Right - R.Left < MinHoleSize then

   if Msg.WParam in [WMSZ_BOTTOMLEFT, WMSZ_LEFT, WMSZ_TOPLEFT] then

    R.Left := R.Right - MinHoleSize

   else

    R.Right := R.Left + MinHoleSize;

    // Аналогично действуем, если слишком мала высота

    if R.Bottom - R.Top < MinHoleSize then

     if Msg.WParam in [WMSZ_TOP, WMSZ_TOPLEFT, WMSZ_TOPRIGHT] then

      R.Top := R.Bottom - MinHoleSize

     else R.Bottom := R.Top + MinHoleSize;

  // Сдвигаем стороны, слишком близко подошедшие

  // к границам окна

  if R.Left < HoleDistance then R.Left := HoleDistance;

  if R.Top < HoleDistance then R.Top := HoleDistance;

  if R.Right > ClientWidth - HoleDistance then

   R.Right := ClientWidth - HoleDistance;

  if R.Bottom > ClientHeight - HoleDistance then

   R.Bottom := ClientHeight - HoleDistance;

  // Копируем прямоугольник R, переводя его координаты

  // обратно в экранные

  PRect(Msg.LParam)^.TopLeft := ClientToScreen(R.TopLeft);

  PRect(Msg.LParam)^.BottomRight := ClientToScreen(R.BottomRight);

 end;

end;

Остается еще одна ситуация, когда границы "дырки" могут подойти к границам окна слишком близко: когда пользователь меняет не границы "дырки", а границы самого окна. Чтобы этого не случилось, нужно отслеживать изменения размеров окна и соответствующим образом менять размеры дырки — для этого нам потребуется изменить размеры панели и пересчитать регион. Пересчет региона необходим и в случае увеличения размеров окна: если его не пересчитать, получится, что часть окна не будет попадать в регион и будет отрезана. Все перечисленные действия выполняются в обработчике сообщения WM_SIZE окна (листинг 1.54).

Листинг 1.54. Обработчик сообщения WM_SIZE главного окна

procedure TFormHole.WMSize(var Msg: TWMSize);

begin

 inherited;

 // При уменьшении размеров окна уменьшаем размер дырки,

 // если границы окна подошли слишком близко к ней

 if PanelHole.Left + PanelHole.Width > ClientWidth - HoleDistance then

  PanelHole.Width := ClientWidth - HoleDistance - PanelHole.Left;

 if PanelHole.Top + PanelHole.Height > ClientHeight - HoleDistance then

  PanelHole.Height := ClientHeight - HoleDistance - PanelHole.Top;

 // На случай увеличения окна пересчитываем его регион,

 // иначе та часть, которая добавилась, окажется за его

 // пределами и будет отрезана SetRegion;

 // Пересчитываем координаты стрелок

 CalculateArrows;

 Invalidate;

end;

Напоследок добавим к программе один "бантик": красные стрелки по углам формы, за которые можно потянуть, чтобы изменить ее размер. Каждая стрелка будет представляться отдельным регионом. Координаты регионов должны быть привязаны к соответствующим углам окна, поэтому при изменении размеров окна эти координаты придется пересчитывать (в листинге 1.54 можно найти соответствующий вызов). Все стрелки выглядят одинаково, но являются зеркальным отражением друг друга. Чтобы рассчитывать координаты стрелок, мы зададим координаты одной нарисованной заранее стрелки в виде константы, а потом будем рассчитывать на основе этих данных координаты реальных стрелок, отражая их от нужной плоскости и добавляя требуемое смещение (листинг 1.55).

Листинг 1.55. Расчет координат стрелок

// координаты верхней левой стрелки, отсчитанные от точки

// (0,0). Для получения координат реальных стрелок эти точки

// будут смещаться и отражаться

const

 ArrowTemplate: TArrowCoords = (

  (X:0; Y:0), (X:24; Y:0), (X:17; Y:7), (X:29; Y:19),

  (X:19; Y:29), (X:7; Y:17), (X:0; Y:24));

procedure TFomHole.CalculateArrows;

var

 Arrow: TArrowCoords;

 I: Integer;

begin

 // Вычисление региона левой верхней стрелки

 // Координаты просто смещаются на постоянную величину

 for I := 0 to High(Arrow) do

 begin

  Arrow[I].X := ArrowTemplate[I].X + ArrowOffset;

  Arrow[I].Y := ArrowTemplate[I].Y + ArrowOffset;

 end;

 // При необходимости уничтожаем старый регион

 if ArrowTopLeft <> 0 then DeleteObject(ArrowTopLeft);

 ArrowTopLeft :=

  CreatePolygonRgn(Arrow[0], Length(Arrow), WINDING);

 // Вычисление региона правой верхней стрелки

 // Координаты по X отражаются и смещаются

 // на постоянную величину относительно правого края окна

 for I := 0 to High(Arrow) do

 begin

  Arrow[I].X := ClientWidth - ArrowOffset - 1 - ArrowTemplate[I].X;

  Arrow[I].Y := ArrowTemplate[I].Y + ArrowOffset;

 end;

 if ArrowTopRight <> 0 then DeleteObject(ArrowTopRight);

 ArrowTopRight := CreatePolygonRgn(Arrow[0], Length(Arrow), WINDING);

 // Вычисление региона левой нижней стрелки

 // Координаты по Y отражаются и смещаются

 // на постоянную величину относительно нижнего края окна

 for I := 0 to High(Arrow) do

 begin

  Arrow[I].X := ArrowTemplate[I].X + ArrowOffset;

  Arrow[I].Y := ClientHeight - ArrowOffset - 1 - ArrowTemplate[I].Y;

 end;

 if ArrowBottomLeft <> 0 then DeleteObject(ArrowBottomLeft);

 ArrowBottomLeft := CreatePolygonRgn(Arrow[0], Length(Arrow), WINDING);

 // Вычисление региона правой нижней стрелки

 // Координаты по обеим осям отражаются и смещаются

 // на постоянную величину относительно правого нижнего угла окна

 for I := 0 to High(Arrow) do

 begin

  Arrow[I].X := ClientWidth - ArrowOffset - 1 - ArrowTemplate[I].X;

  Arrow[I].Y := ClientHeight - ArrowOffset - 1 - ArrowTemplate[I].Y;

 end;

 if ArrowBottomRight <> 0 then DeleteObject(ArrowBottomRight);

 ArrowBottomRight := CreatePolygonRgn(Arrow[0], Length(Arrow), WINDING);

end;

Следующий шаг — рисование стрелки на форме. Делается это очень просто (листинг 1.56).

Листинг 1.56. Рисование стрелок на форме

procedure TFormHole.FormPaint(Sender: TObject);

begin

 // Закрашиваем регионы стрелок

 Canvas.Brush.Style := bsSolid;

 Canvas.Brush.Color := clRed;

 FillRgn(Canvas.Handle, ArrowTopLeft, Canvas.Brush.Handle);

 FillRgn(Canvas.Handle, ArrowTopRight, Canvas.Brush.Handle);

 FillRgn(Canvas.Handle, ArrowBottomLeft, Canvas.Brush.Handle);

 FillRgn(Canvas.Handle, ArrowBottomRight, Canvas.Brush.Handle);

Перейти на страницу:
Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.
Комментарии / Отзывы
    Ничего не найдено.