C++界面库:在GDI上添加完全的alpha混合支持

C++界面库:在GDI上添加完全的alpha混合支持
    做完了小型WCF之后,就是小型的WPF了。之前那个完全避免用户大部分的错误使用导致的死锁的方案还有一点点的问题,所以先休息一下,做做别的。为了在C++上重现一套类似WPF的工具,首先要解决绘图部分。

    绘图的设备当然是需要可切换的,于是用bridge模式定义了大量的接口,这些接口用来创建画笔、画刷、字体和图形,然后图形用树的形式组织起来,最后放到一块跟窗口链接的画板上面,有需要的时候自动绘制。为了最快速地开始工作,我实现了一个GDI的绘图设备,以后有空再做DirectX的。但是我们知道GDI对alpha的支持是很弱的,只有一个叫alphablend的API用来贴bitmap,因此为了让画刷和画笔都能够支持alpha渐变、alpha位图和alpha颜色,做了很多的工作。下面是截图:

C++界面库:在GDI上添加完全的alpha混合支持_第1张图片

    之所以不用GDI+仅仅是因为我不喜欢。下面是利用GDI组合出上面的效果的那部分代码:
   1  #include  " VL_GDIRenderer.h "
   2 
   3  namespace  vl
   4  {
   5       namespace  interaction
   6      {
   7           namespace  renderer
   8          {
   9 
  10               enum  IndirectFillReason
  11              {
  12                  ifrDirectFill,
  13                  ifrLinearGradient,
  14                  ifrAlphaLinearGradient,
  15                  ifrAlphaBitmap,
  16              };
  17 
  18              IndirectFillReason GetIndirectFillReason( const  VL_IrBrushRec &  Brush)
  19              {
  20                   switch (Brush.BrushKind)
  21                  {
  22                   case  VL_IrBrushRec::bkSolid:
  23                       if (Brush.MainColor.A != 255 )
  24                      {
  25                           return  ifrAlphaBitmap;
  26                      }
  27                       else
  28                      {
  29                           return  ifrDirectFill;
  30                      }
  31                   case  VL_IrBrushRec::bkLinearGradient:
  32                       if (Brush.MainColor.A != 255   ||  Brush.GradientColor.A != 255 )
  33                      {
  34                           return  ifrAlphaLinearGradient;
  35                      }
  36                       else
  37                      {
  38                           return  ifrLinearGradient;
  39                      }
  40                   case  VL_IrBrushRec::bkBitmap:
  41                       if (Brush.Bitmap -> IsAlphaChannelBuilt())
  42                      {
  43                           return  ifrAlphaBitmap;
  44                      }
  45                       else
  46                      {
  47                           return  ifrDirectFill;
  48                      }
  49                   default :
  50                       return  ifrDirectFill;
  51                  }
  52              }
  53 
  54              VBool IsBrushAlpha( const  VL_IrBrushRec &  Brush)
  55              {
  56                   switch (GetIndirectFillReason(Brush))
  57                  {
  58                   case  ifrAlphaBitmap:
  59                       return   true ;
  60                   case  ifrAlphaLinearGradient:
  61                       return   true ;
  62                   default :
  63                       return   false ;
  64                  }
  65              }
  66 
  67              VL_IrColor MixColor( const  VL_IrColor &  ColorA ,  const  VL_IrColor &  ColorB , VDouble Ratio)
  68              {
  69                   return  VL_IrColor(
  70                      ColorA.R + Round(Ratio * (ColorB.R - ColorA.R)),
  71                      ColorA.G + Round(Ratio * (ColorB.G - ColorA.G)),
  72                      ColorA.B + Round(Ratio * (ColorB.B - ColorA.B)),
  73                      ColorA.A + Round(Ratio * (ColorB.A - ColorA.A))
  74                      );
  75              }
  76 
  77               void  SetColor(TRIVERTEX &  Vertex ,  const  VL_IrColor &  Color)
  78              {
  79                  Vertex.Red = Color.R << 8 ;
  80                  Vertex.Green = Color.G << 8 ;
  81                  Vertex.Blue = Color.G << 8 ;
  82                  Vertex.Alpha = Color.A << 8 ;
  83              }
  84 
  85  /* ********************************************************************************************************
  86  VL_GDIBrush
  87  ******************************************************************************************************** */
  88 
  89              VL_GDIBrush::VL_GDIBrush(VL_GDIFactory *  Factory ,  const  VL_IrBrushRec &  Brush)
  90              {
  91                  FFactory = Factory;
  92                  FInternalData = Brush;
  93                   switch (FInternalData.BrushKind)
  94                  {
  95                   case  VL_IrBrushRec::bkSolid:
  96                      FBrush = new  VL_WinBrush(RGB(FInternalData.MainColor.R,FInternalData.MainColor.G,FInternalData.MainColor.B));
  97                       if (FInternalData.MainColor.A != 255 )
  98                      {
  99                          VL_WinBitmap::Ptr Bitmap = new  VL_WinBitmap( 32 , 32 ,VL_WinBitmap::vbb32Bits, true );
 100                          Bitmap -> GetWinDC() -> SetBrush(FBrush);
 101                          Bitmap -> GetWinDC() -> FillRect( 0 , 0 , 32 , 32 );
 102                          Bitmap -> GenerateAlpha(FInternalData.MainColor.A);
 103                          Bitmap -> BuildAlphaChannel();
 104                          FInternalData.Bitmap = Bitmap;
 105                      }
 106                       break ;
 107                   case  VL_IrBrushRec::bkLinearGradient:
 108                       break ;
 109                   case  VL_IrBrushRec::bkBitmap:
 110                      FBrush = new  VL_WinBrush(FInternalData.Bitmap);
 111                       break ;
 112                   default :
 113                       throw  L " 内部错误 " ;
 114                  }
 115              }
 116 
 117               const  VL_IrBrushRec &  VL_GDIBrush::GetInternalData()
 118              {
 119                   return  FInternalData;
 120              }
 121 
 122              IVL_IrFactory *  VL_GDIBrush::GetFactory()
 123              {
 124                   return  FFactory;
 125              }
 126 
 127              VL_WinBrush::Ptr VL_GDIBrush::GetGDIBrush()
 128              {
 129                   return  FBrush;
 130              }
 131 
 132  /* ********************************************************************************************************
 133  VL_GDIPen
 134  ******************************************************************************************************** */
 135 
 136              VL_GDIPen::VL_GDIPen(VL_GDIFactory *  Factory ,  const  VL_IrBrushRec &  Brush ,  const  VL_IrPenRec &  Pen)
 137              {
 138                  FFactory = Factory;
 139                  FInternalBrush = Brush;
 140                  FInternalPen = Pen;
 141 
 142                  VInt EndCap = 0 ;
 143                  VInt Join = 0 ;
 144                   switch (FInternalPen.EndCap)
 145                  {
 146                   case  VL_IrPenRec::ecFlat:
 147                      EndCap = PS_ENDCAP_FLAT;
 148                       break ;
 149                   case  VL_IrPenRec::ecRound:
 150                      EndCap = PS_ENDCAP_ROUND;
 151                       break ;
 152                   case  VL_IrPenRec::ecSquare:
 153                      EndCap = PS_ENDCAP_SQUARE;
 154                       break ;
 155                   default :
 156                       throw  L " 内部错误 " ;
 157                  }
 158                   switch (FInternalPen.Join)
 159                  {
 160                   case  VL_IrPenRec::jBevel:
 161                      Join = PS_JOIN_BEVEL;
 162                       break ;
 163                   case  VL_IrPenRec::jMiter:
 164                      Join = PS_JOIN_MITER;
 165                       break ;
 166                   case  VL_IrPenRec::jRound:
 167                      Join = PS_JOIN_ROUND;
 168                       break ;
 169                   default :
 170                       throw  L " 内部错误 " ;
 171                  }
 172                  
 173                   switch (FInternalBrush.BrushKind)
 174                  {
 175                   case  VL_IrBrushRec::bkSolid:
 176                      FPen = new  VL_WinPen(PS_SOLID,EndCap,Join,FInternalPen.Weight,RGB(FInternalBrush.MainColor.R,FInternalBrush.MainColor.G,FInternalBrush.MainColor.B));
 177                       if (FInternalBrush.MainColor.A != 255 )
 178                      {
 179                          VL_WinBrush::Ptr SolidBrush = new  VL_WinBrush(RGB(FInternalBrush.MainColor.R,FInternalBrush.MainColor.G,FInternalBrush.MainColor.B));
 180                          VL_WinBitmap::Ptr Bitmap = new  VL_WinBitmap( 32 , 32 ,VL_WinBitmap::vbb32Bits, true );
 181                          Bitmap -> GetWinDC() -> SetBrush(SolidBrush);
 182                          Bitmap -> GetWinDC() -> FillRect( 0 , 0 , 32 , 32 );
 183                          Bitmap -> GenerateAlpha(FInternalBrush.MainColor.A);
 184                          Bitmap -> BuildAlphaChannel();
 185                          FInternalBrush.Bitmap = Bitmap;
 186                      }
 187                       break ;
 188                   case  VL_IrBrushRec::bkLinearGradient:
 189                      FPen = new  VL_WinPen(PS_SOLID,EndCap,Join,FInternalPen.Weight,RGB(FInternalBrush.MainColor.R,FInternalBrush.MainColor.G,FInternalBrush.MainColor.B));
 190                       break ;
 191                   case  VL_IrBrushRec::bkBitmap:
 192                      FPen = new  VL_WinPen(FInternalBrush.Bitmap,PS_SOLID,EndCap,Join,FInternalPen.Weight);
 193                       break ;
 194                   default :
 195                       throw  L " 内部错误 " ;
 196                  }
 197              }
 198 
 199              VL_GDIPen:: ~ VL_GDIPen()
 200              {
 201              }
 202 
 203               const  VL_IrPenRec &  VL_GDIPen::GetInternalPen()
 204              {
 205                   return  FInternalPen;
 206              }
 207 
 208               const  VL_IrBrushRec &  VL_GDIPen::GetInternalBrush()
 209              {
 210                   return  FInternalBrush;
 211              }
 212 
 213              IVL_IrFactory *  VL_GDIPen::GetFactory()
 214              {
 215                   return  FFactory;
 216              }
 217 
 218              VL_WinPen::Ptr VL_GDIPen::GetGDIPen()
 219              {
 220                   return  FPen;
 221              }
 222 
 223  /* ********************************************************************************************************
 224  VL_GDIFont
 225  ******************************************************************************************************** */
 226 
 227              VL_GDIFont::VL_GDIFont(VL_GDIFactory *  Factory ,  const  VL_IrFontRec &  Font)
 228              {
 229                  FFactory = Factory;
 230                  FInternalData = Font;
 231                  FFont = new  VL_WinFont(FInternalData.Name,FInternalData.Height,FInternalData.Width, 0 , 0 ,FInternalData.Bold ? 900 : 400 ,FInternalData.Italic,FInternalData.Underline,FInternalData.StrikeOut, true );
 232              }
 233 
 234              VL_GDIFont:: ~ VL_GDIFont()
 235              {
 236              }
 237 
 238               const  VL_IrFontRec &  VL_GDIFont::GetInternalData()
 239              {
 240                   return  FInternalData;
 241              }
 242 
 243              IVL_IrFactory *  VL_GDIFont::GetFactory()
 244              {
 245                   return  FFactory;
 246              }
 247 
 248              VL_WinFont::Ptr VL_GDIFont::GetGDIFont()
 249              {
 250                   return  FFont;
 251              }
 252 
 253  /* ********************************************************************************************************
 254  VL_GDIElement
 255  ******************************************************************************************************** */
 256 
 257              VL_WinDC *  VL_GDIElement::GetDC()
 258              {
 259                   return  FCanvas ? FCanvas -> GetDC(): 0 ;
 260              }
 261 
 262               void  VL_GDIElement::CreatePath()
 263              {
 264                  FCanvas -> GetDC() -> BeginPath();
 265                  DrawForPath();
 266                  FCanvas -> GetDC() -> EndPath();
 267              }
 268 
 269               void  VL_GDIElement::EnsureRegion()
 270              {
 271                   if (FEnvironmentModified)
 272                  {
 273                      FEnvironmentModified = false ;
 274                       if (FCanvas)
 275                      {
 276                           if (FPen)
 277                          {
 278                              FCanvas -> GetDC() -> SetPen(FPen -> GetGDIPen());
 279                              CreatePath();
 280                              FCanvas -> GetDC() -> WidenPath();
 281                              FBorderRegion = FCanvas -> GetDC() -> RegionFromPath();
 282                              CreatePath();
 283                              FContentRegion = new  VL_WinRegion(FCanvas -> GetDC() -> RegionFromPath(),FBorderRegion,RGN_DIFF);
 284                          }
 285                           else
 286                          {
 287                              CreatePath();
 288                              FContentRegion = FCanvas -> GetDC() -> RegionFromPath();
 289                          }
 290                          {
 291                              RECT Rect = { 0 , 0 , 0 , 0 };
 292                               if (FBorderRegion)
 293                              {
 294                                  Rect = FBorderRegion -> GetBoundRect();
 295                              }
 296                               else   if (FContentRegion)
 297                              {
 298                                  Rect = FContentRegion -> GetBoundRect();
 299                              }
 300                              FElementRectangle = VL_IrRect(VL_IrPoint(Rect.left,Rect.top),VL_IrPoint(Rect.right - Rect.left,Rect.bottom - Rect.top));
 301                          }
 302                          {
 303                              RECT Rect = { 0 , 0 , 0 , 0 };
 304                               if (FContentRegion)
 305                              {
 306                                  Rect = FContentRegion -> GetBoundRect();
 307                              }
 308                              FClientRectangle = VL_IrRect(VL_IrPoint(Rect.left,Rect.top),VL_IrPoint(Rect.right - Rect.left,Rect.bottom - Rect.top));
 309                          }
 310                      }
 311                  }
 312              }
 313 
 314               void  VL_GDIElement::EnvironmentModified(VL_GDICanvas *  Canvas)
 315              {
 316                   if (FCanvas  ||  Canvas)
 317                  {
 318                      FCanvas = Canvas;
 319                      FBorderRegion = 0 ;
 320                      FContentRegion = 0 ;
 321                      FElementRectangle = VL_IrRect();
 322                      FClientRectangle = VL_IrRect();
 323                      FEnvironmentModified = true ;
 324                       for (VInt i = 0 ;i < FChildren.GetCount();i ++ )
 325                      {
 326                          FChildren[i] -> EnvironmentModified(Canvas);
 327                      }
 328                  }
 329              }
 330 
 331              VL_WinRegion::Ptr VL_GDIElement::EnterClip(VL_WinRegion::Ptr CurrentClip , VL_WinRegion::Ptr Region)
 332              {
 333                  VL_WinRegion::Ptr Clip = CurrentClip ? new  VL_WinRegion(CurrentClip,Region,RGN_AND):Region;
 334                  FCanvas -> GetDC() -> ClipRegion(Clip);
 335                   return  Clip;
 336              }
 337 
 338               void  VL_GDIElement::LeaveClip(VL_WinRegion::Ptr CurrentClip)
 339              {
 340                   if (CurrentClip)
 341                  {
 342                      FCanvas -> GetDC() -> ClipRegion(CurrentClip);
 343                  }
 344                   else
 345                  {
 346                      FCanvas -> GetDC() -> RemoveClip();
 347                  }
 348              }
 349 
 350               void  VL_GDIElement::FillLinearGradient(VL_WinRegion::Ptr CurrentClip , VL_WinRegion::Ptr Region ,  const  VL_IrBrushRec &  Brush)
 351              {
 352                  RECT BoundRect = EnterClip(CurrentClip,Region) -> GetBoundRect();
 353                  VDouble Sin = sin(Brush.GradientAngle);
 354                  VDouble Cos = cos(Brush.GradientAngle);
 355                   if (Sin < 0 )
 356                  {
 357                      Cos =- Cos;
 358                      Sin =- Sin;
 359                  }
 360 
 361                  TRIVERTEX Vertices[ 4 ];
 362                  Vertices[ 0 ].x = BoundRect.left;
 363                  Vertices[ 0 ].y = BoundRect.top;
 364                  Vertices[ 1 ].x = BoundRect.right;
 365                  Vertices[ 1 ].y = BoundRect.top;
 366                  Vertices[ 2 ].x = BoundRect.left;
 367                  Vertices[ 2 ].y = BoundRect.bottom;
 368                  Vertices[ 3 ].x = BoundRect.right;
 369                  Vertices[ 3 ].y = BoundRect.bottom;
 370                  GRADIENT_TRIANGLE Triangles[ 2 ];
 371                  Triangles[ 0 ].Vertex1 = 0 ;
 372                  Triangles[ 0 ].Vertex2 = 1 ;
 373                  Triangles[ 0 ].Vertex3 = 2 ;
 374                  Triangles[ 1 ].Vertex1 = 1 ;
 375                  Triangles[ 1 ].Vertex2 = 2 ;
 376                  Triangles[ 1 ].Vertex3 = 3 ;
 377 
 378                  VInt Width = BoundRect.right - BoundRect.left;
 379                  VInt Height = BoundRect.bottom - BoundRect.top;
 380                   if (Cos > 0 )
 381                  {
 382                      VDouble Ratio = Height * Cos / (Width * Sin + Height * Cos);
 383                      SetColor(Vertices[ 0 ],Brush.MainColor);
 384                      SetColor(Vertices[ 1 ],MixColor(Brush.MainColor,Brush.GradientColor, 1 - Ratio));
 385                      SetColor(Vertices[ 2 ],MixColor(Brush.MainColor,Brush.GradientColor,Ratio));
 386                      SetColor(Vertices[ 3 ],Brush.GradientColor);
 387                  }
 388                   else
 389                  {
 390                      VDouble Ratio = Width * Sin / (Width * Sin - Height * Cos);
 391                      SetColor(Vertices[ 0 ],MixColor(Brush.MainColor,Brush.GradientColor, 1 - Ratio));
 392                      SetColor(Vertices[ 1 ],Brush.GradientColor);
 393                      SetColor(Vertices[ 2 ],Brush.MainColor);
 394                      SetColor(Vertices[ 3 ],MixColor(Brush.MainColor,Brush.GradientColor,Ratio));
 395                  }
 396 
 397                   if (Brush.MainColor.A == 255   &&  Brush.GradientColor.A == 255 )
 398                  {
 399                      FCanvas -> GetDC() -> GradientTriangle(Vertices, 4 ,Triangles, 2 );
 400                  }
 401                   else
 402                  {
 403                      FCanvas -> GetAlphaBuffer() -> GetWinDC() -> GradientTriangle(Vertices, 4 ,Triangles, 2 );
 404                      VInt X1 = BoundRect.left;
 405                      VInt X2 = BoundRect.right;
 406                      VInt Y1 = BoundRect.top;
 407                      VInt Y2 = BoundRect.bottom;
 408                       if (X1 < 0 )X1 = 0 ;
 409                       if (Y1 < 0 )Y1 = 0 ;
 410                       if (X2 > FCanvas -> GetSize().X)X2 = FCanvas -> GetSize().X;
 411                       if (Y2 > FCanvas -> GetSize().Y)Y2 = FCanvas -> GetSize().Y;
 412                       for (VInt y = Y1;y < Y2;y ++ )
 413                      {
 414                          BYTE *  Colors = FCanvas -> GetAlphaBuffer() -> GetScanLines()[y] + X1 * 4 ;
 415                           for (VInt x = X1;x < X2;x ++ )
 416                          {
 417                              BYTE Alpha = Colors[ 3 ];
 418                              Colors[ 0 ] = Colors[ 0 ] * Alpha / 255 ;
 419                              Colors[ 1 ] = Colors[ 1 ] * Alpha / 255 ;
 420                              Colors[ 2 ] = Colors[ 2 ] * Alpha / 255 ;
 421                              Colors += 4 ;
 422                          }
 423                      }
 424                      FCanvas -> GetDC() -> Draw(X1,Y1,X2 - X1,Y2 - Y1,FCanvas -> GetAlphaBuffer(),X1,Y1,X2 - X1,Y2 - Y1);
 425                  }
 426                  LeaveClip(CurrentClip);
 427              }
 428 
 429               void  VL_GDIElement::FillAlphaBitmap(VL_WinRegion::Ptr CurrentClip , VL_WinRegion::Ptr Region ,  const  VL_IrBrushRec &  Brush)
 430              {
 431                  RECT BoundRect = EnterClip(CurrentClip,Region) -> GetBoundRect();
 432                  VInt W = Brush.Bitmap -> GetWidth();
 433                  VInt H = Brush.Bitmap -> GetHeight();
 434                  VInt StartCol = BoundRect.left / W;
 435                  VInt StartRow = BoundRect.top / H;
 436                  VInt EndCol = BoundRect.right / W;
 437                  VInt EndRow = BoundRect.bottom / H;
 438                   if (EndCol * W != BoundRect.right)
 439                  {
 440                      EndCol ++ ;
 441                  }
 442                   if (EndRow * H != BoundRect.bottom)
 443                  {
 444                      EndRow ++ ;
 445                  }
 446                   for (VInt i = StartCol;i <= EndCol;i ++ )
 447                  {
 448                       for (VInt j = StartRow;j < EndRow;j ++ )
 449                      {
 450                          FCanvas -> GetDC() -> Draw(i * W,j * H,Brush.Bitmap);
 451                      }
 452                  }
 453                  LeaveClip(CurrentClip);
 454              }
 455 
 456               void  VL_GDIElement::DrawBorder(VL_WinRegion::Ptr CurrentClip)
 457              {
 458                   if (FPen)
 459                  {
 460                      FCanvas -> GetDC() -> SetPen(FPen ? FPen -> GetGDIPen():FCanvas -> GetEmptyPen());
 461                       switch (GetIndirectFillReason(FPen -> GetInternalBrush()))
 462                      {
 463                       case  ifrDirectFill:
 464                           if (FElementKind != ekCurve)
 465                          {
 466                              FCanvas -> GetDC() -> SetBrush(FCanvas -> GetEmptyBrush());
 467                          }
 468                          DrawShape( true );
 469                           break ;
 470                       case  ifrLinearGradient: case  ifrAlphaLinearGradient:
 471                          EnsureRegion();
 472                          FillLinearGradient(CurrentClip,FBorderRegion,FPen -> GetInternalBrush());
 473                           break ;
 474                       case  ifrAlphaBitmap:
 475                          EnsureRegion();
 476                          FillAlphaBitmap(CurrentClip,FBorderRegion,FPen -> GetInternalBrush());
 477                           break ;
 478                       default :
 479                           throw  L " 内部错误 " ;
 480                      }
 481                  }
 482              }
 483 
 484               void  VL_GDIElement::DrawFilling(VL_WinRegion::Ptr CurrentClip)
 485              {
 486                   if (FBrush)
 487                  {
 488                       switch (GetIndirectFillReason(FBrush -> GetInternalData()))
 489                      {
 490                       case  ifrDirectFill:
 491                          FCanvas -> GetDC() -> SetBrush(FBrush -> GetGDIBrush());
 492                          FCanvas -> GetDC() -> SetPen(FCanvas -> GetEmptyPen());
 493                           if (FPen  &&  IsBrushAlpha(FPen -> GetInternalBrush()))
 494                          {
 495                              EnsureRegion();
 496                              FCanvas -> GetDC() -> FillRegion(FContentRegion);
 497                          }
 498                           else
 499                          {
 500                              DrawShape( false );
 501                          }
 502                           break ;
 503                       case  ifrLinearGradient: case  ifrAlphaLinearGradient:
 504                          EnsureRegion();
 505                          FillLinearGradient(CurrentClip,FContentRegion,FBrush -> GetInternalData());
 506                           break ;
 507                       case  ifrAlphaBitmap:
 508                          EnsureRegion();
 509                          FillAlphaBitmap(CurrentClip,FContentRegion,FBrush -> GetInternalData());
 510                           break ;
 511                       default :
 512                           throw  L " 内部错误 " ;
 513                      }
 514                  }
 515              }
 516 
 517               void  VL_GDIElement::Draw(VL_WinRegion::Ptr CurrentClip)
 518              {
 519                   if (FVisible)
 520                  {
 521                       switch (FElementKind)
 522                      {
 523                       case  ekCurve:
 524                          DrawBorder(CurrentClip);
 525                           break ;
 526                       case  ekShape:
 527                          DrawFilling(CurrentClip);
 528                          DrawBorder(CurrentClip);
 529                           break ;
 530                       case  ekContainerShape:
 531                          DrawFilling(CurrentClip);
 532                           if (FChildren.GetCount())
 533                          {
 534                              EnsureRegion();
 535                              VL_WinRegion::Ptr Clip = EnterClip(CurrentClip,FContentRegion);
 536                               for (VInt i = FChildren.GetCount() - 1 ;i >= 0 ;i -- )
 537                              {
 538                                  FChildren[i] -> Draw(Clip);
 539                              }
 540                              LeaveClip(CurrentClip);
 541                          }
 542                          DrawBorder(CurrentClip);
 543                           break ;
 544                      }
 545                  }
 546              }
 547 
 548               void  VL_GDIElement::DrawShape(VBool Border)
 549              {
 550                  DrawForPath();
 551              }
 552 
 553              VL_GDIElement::VL_GDIElement(VL_GDIFactory *  Factory , ElementKind aElementKind)
 554              {
 555                  FFactory = Factory;
 556                  FCanvas = 0 ;
 557                  FParent = 0 ;
 558                  FEnvironmentModified = false ;
 559                  FVisible = true ;
 560                  FElementKind = aElementKind;
 561              }
 562 
 563              VL_GDIElement:: ~ VL_GDIElement()
 564              {
 565              }
 566 
 567              VInt VL_GDIElement::ChildrenCount()
 568              {
 569                   return  FChildren.GetCount();
 570              }
 571 
 572              IVL_IrElement::Ptr VL_GDIElement::GetChild(VInt Index)
 573              {
 574                   return  FChildren[Index];
 575              }
 576 
 577               void  VL_GDIElement::AddChild(IVL_IrElement::Ptr Element)
 578              {
 579                  VL_GDIElement::Ptr e = Element;
 580                   if ( ! e) throw  L " 内部错误 " ;
 581                  FChildren.Add(e);
 582                  e -> FParent = this ;
 583                  e -> EnvironmentModified(FCanvas);
 584              }
 585 
 586               void  VL_GDIElement::InsertChild(VInt Index , IVL_IrElement::Ptr Element)
 587              {
 588                  VL_GDIElement::Ptr e = Element;
 589                   if ( ! e) throw  L " 内部错误 " ;
 590                  FChildren.Insert(Index,e);
 591                  e -> FParent = this ;
 592                  e -> EnvironmentModified(FCanvas);
 593              }
 594 
 595              IVL_IrElement::Ptr VL_GDIElement::DeleteChild(IVL_IrElement::Ptr Element)
 596              {
 597                  VInt Index = FChildren.IndexOf(dynamic_cast < VL_GDIElement *> (Element.Object()));
 598                   if (Index ==- 1 ) throw  L " 内部错误 " ;
 599                   return  DeleteChildAt(Index);
 600              }
 601 
 602              IVL_IrElement::Ptr VL_GDIElement::DeleteChildAt(VInt Index)
 603              {
 604                  VL_GDIElement::Ptr e = FChildren.Fetch(Index);
 605                  e -> FParent = 0 ;
 606                  e -> EnvironmentModified(FCanvas);
 607                   return  e;
 608              }
 609 
 610              VBool VL_GDIElement::HasChild(IVL_IrElement::Ptr Element)
 611              {
 612                   return  FChildren.Exists(dynamic_cast < VL_GDIElement *> (Element.Object()));
 613              }
 614 
 615              VInt VL_GDIElement::IndexOfChild(IVL_IrElement::Ptr Element)
 616              {
 617                   return  FChildren.IndexOf(dynamic_cast < VL_GDIElement *> (Element.Object()));
 618              }
 619 
 620               void  VL_GDIElement::MoveChild(VInt FromIndex , VInt ToIndex)
 621              {
 622                  FChildren.Insert(ToIndex,FChildren.Fetch(FromIndex));
 623              }
 624 
 625              IVL_IrPen::Ptr VL_GDIElement::GetPen()
 626              {
 627                   return  FPen;
 628              }
 629 
 630               void  VL_GDIElement::SetPen(IVL_IrPen::Ptr Pen)
 631              {
 632                  FPen = Pen;
 633                  EnvironmentModified(FCanvas);
 634              }
 635 
 636              IVL_IrBrush::Ptr VL_GDIElement::GetBrush()
 637              {
 638                   return  FBrush;
 639              }
 640 
 641               void  VL_GDIElement::SetBrush(IVL_IrBrush::Ptr Brush)
 642              {
 643                  FBrush = Brush;
 644              }
 645 
 646              IVL_IrFont::Ptr VL_GDIElement::GetFont()
 647              {
 648                   return  FFont;
 649              }
 650 
 651               void  VL_GDIElement::SetFont(IVL_IrFont::Ptr Font)
 652              {
 653                  FFont = Font;
 654                  EnvironmentModified(FCanvas);
 655              }
 656 
 657              VBool VL_GDIElement::GetVisible()
 658              {
 659                   return  FVisible;
 660              }
 661 
 662               void  VL_GDIElement::SetVisible(VBool Value)
 663              {
 664                  FVisible = Value;
 665              }
 666 
 667              IVL_IrCanvas *  VL_GDIElement::GetCanvas()
 668              {
 669                   return  FCanvas;
 670              }
 671 
 672              IVL_IrElement *  VL_GDIElement::GetParent()
 673              {
 674                   return  dynamic_cast < IVL_IrElement *> (FParent);
 675              }
 676 
 677              IVL_IrFactory *  VL_GDIElement::GetFactory()
 678              {
 679                   return  FFactory;
 680              }
 681 
 682              IVL_IrElement::HitTestResult VL_GDIElement::ContainedPoint(VL_IrPoint Point)
 683              {
 684                  EnsureRegion();
 685                  POINT P = {Point.X,Point.Y};
 686                   if (FBorderRegion)
 687                  {
 688                       if (FBorderRegion -> ContainPoint(P))
 689                      {
 690                           return  IVL_IrElement::htrBorder;
 691                      }
 692                  }
 693                   if (FContentRegion)
 694                  {
 695                       if (FContentRegion -> ContainPoint(P))
 696                      {
 697                           return  IVL_IrElement::htrInternal;
 698                      }
 699                  }
 700                   return  IVL_IrElement::htrNone;
 701              }
 702 
 703              VL_IrRect VL_GDIElement::GetElementRectangle()
 704              {
 705                  EnsureRegion();
 706                   return  FElementRectangle;
 707              }
 708 
 709              VL_IrRect VL_GDIElement::GetClientRectangle()
 710              {
 711                  EnsureRegion();
 712                   return  FClientRectangle;
 713              }
 714 
 715  /* ********************************************************************************************************
 716  VL_GDILine
 717  ******************************************************************************************************** */
 718 
 719               void  VL_GDILine::DrawForPath()
 720              {
 721                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
 722                  FCanvas -> GetDC() -> MoveTo(Offset.X + FStartPoint.X,Offset.Y + FStartPoint.Y);
 723                  FCanvas -> GetDC() -> LineTo(Offset.X + FEndPoint.X,Offset.Y + FEndPoint.Y);
 724              }
 725 
 726              VL_GDILine::VL_GDILine(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekCurve)
 727              {
 728              }
 729 
 730              VL_GDILine:: ~ VL_GDILine()
 731              {
 732              }
 733 
 734              IVL_IrElementProperties *  VL_GDILine::Properties()
 735              {
 736                   return   this ;
 737              }
 738 
 739              IVL_IrElementContainer *  VL_GDILine::Container()
 740              {
 741                   return   0 ;
 742              }
 743 
 744              VL_IrPoint VL_GDILine::GetStartPoint()
 745              {
 746                   return  FStartPoint;
 747              }
 748 
 749              VL_IrPoint VL_GDILine::GetEndPoint()
 750              {
 751                   return  FEndPoint;
 752              }
 753 
 754               void  VL_GDILine::Update( const  VL_IrPoint &  Start ,  const  VL_IrPoint &  End)
 755              {
 756                  FStartPoint = Start;
 757                  FEndPoint = End;
 758                  EnvironmentModified(FCanvas);
 759              }
 760 
 761  /* ********************************************************************************************************
 762  VL_GDIRectangle
 763  ******************************************************************************************************** */
 764              
 765               void  VL_GDIRectangle::DrawForPath()
 766              {
 767                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
 768                  FCanvas -> GetDC() -> Rectangle(
 769                      Offset.X + FPosition.X,
 770                      Offset.Y + FPosition.Y,
 771                      Offset.X + FPosition.X + FSize.X,
 772                      Offset.Y + FPosition.Y + FSize.Y
 773                      );
 774              }
 775 
 776              VL_GDIRectangle::VL_GDIRectangle(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekContainerShape)
 777              {
 778              }
 779 
 780              VL_GDIRectangle:: ~ VL_GDIRectangle()
 781              {
 782              }
 783 
 784              IVL_IrElementProperties *  VL_GDIRectangle::Properties()
 785              {
 786                   return   this ;
 787              }
 788 
 789              IVL_IrElementContainer *  VL_GDIRectangle::Container()
 790              {
 791                   return   this ;
 792              }
 793 
 794              VL_IrPoint VL_GDIRectangle::GetPosition()
 795              {
 796                   return  FPosition;
 797              }
 798 
 799              VL_IrPoint VL_GDIRectangle::GetSize()
 800              {
 801                   return  FSize;
 802              }
 803 
 804               void  VL_GDIRectangle::Update( const  VL_IrPoint &  Position ,  const  VL_IrPoint &  Size)
 805              {
 806                  FPosition = Position;
 807                  FSize = Size;
 808                  EnvironmentModified(FCanvas);
 809              }
 810 
 811               void  VL_GDIRectangle::Update( const  VL_IrRect &  Rectangle)
 812              {
 813                  Update(Rectangle.Position,Rectangle.Size);
 814              }
 815 
 816  /* ********************************************************************************************************
 817  VL_GDIRoundRectangle
 818  ******************************************************************************************************** */
 819              
 820               void  VL_GDIRoundRectangle::DrawForPath()
 821              {
 822                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
 823                  FCanvas -> GetDC() -> RoundRect(
 824                      Offset.X + FPosition.X,
 825                      Offset.Y + FPosition.Y,
 826                      Offset.X + FPosition.X + FSize.X,
 827                      Offset.Y + FPosition.Y + FSize.Y,
 828                      FEllipse.X,
 829                      FEllipse.Y
 830                      );
 831              }
 832 
 833              VL_GDIRoundRectangle::VL_GDIRoundRectangle(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekContainerShape)
 834              {
 835              }
 836 
 837              VL_GDIRoundRectangle:: ~ VL_GDIRoundRectangle()
 838              {
 839              }
 840 
 841              IVL_IrElementProperties *  VL_GDIRoundRectangle::Properties()
 842              {
 843                   return   this ;
 844              }
 845 
 846              IVL_IrElementContainer *  VL_GDIRoundRectangle::Container()
 847              {
 848                   return   this ;
 849              }
 850 
 851              VL_IrPoint VL_GDIRoundRectangle::GetPosition()
 852              {
 853                   return  FPosition;
 854              }
 855 
 856              VL_IrPoint VL_GDIRoundRectangle::GetSize()
 857              {
 858                   return  FSize;
 859              }
 860 
 861              VL_IrPoint VL_GDIRoundRectangle::GetEllipse()
 862              {
 863                   return  FEllipse;
 864              }
 865 
 866               void  VL_GDIRoundRectangle::Update( const  VL_IrPoint &  Position ,  const  VL_IrPoint &  Size ,  const  VL_IrPoint &  Ellipse)
 867              {
 868                  FPosition = Position;
 869                  FSize = Size;
 870                  FEllipse = Ellipse;
 871                  EnvironmentModified(FCanvas);
 872              }
 873 
 874               void  VL_GDIRoundRectangle::Update( const  VL_IrRect &  Rectangle ,  const  VL_IrPoint &  Ellipse)
 875              {
 876                  Update(Rectangle.Position,Rectangle.Size,Ellipse);
 877              }
 878 
 879  /* ********************************************************************************************************
 880  VL_GDIEllipse
 881  ******************************************************************************************************** */
 882              
 883               void  VL_GDIEllipse::DrawForPath()
 884              {
 885                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
 886                  FCanvas -> GetDC() -> Ellipse(
 887                      Offset.X + FPosition.X,
 888                      Offset.Y + FPosition.Y,
 889                      Offset.X + FPosition.X + FSize.X,
 890                      Offset.Y + FPosition.Y + FSize.Y
 891                      );
 892              }
 893 
 894              VL_GDIEllipse::VL_GDIEllipse(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekContainerShape)
 895              {
 896              }
 897 
 898              VL_GDIEllipse:: ~ VL_GDIEllipse()
 899              {
 900              }
 901 
 902              IVL_IrElementProperties *  VL_GDIEllipse::Properties()
 903              {
 904                   return   this ;
 905              }
 906 
 907              IVL_IrElementContainer *  VL_GDIEllipse::Container()
 908              {
 909                   return   this ;
 910              }
 911 
 912              VL_IrPoint VL_GDIEllipse::GetPosition()
 913              {
 914                   return  FPosition;
 915              }
 916 
 917              VL_IrPoint VL_GDIEllipse::GetSize()
 918              {
 919                   return  FSize;
 920              }
 921 
 922               void  VL_GDIEllipse::Update( const  VL_IrPoint &  Position ,  const  VL_IrPoint &  Size)
 923              {
 924                  FPosition = Position;
 925                  FSize = Size;
 926                  EnvironmentModified(FCanvas);
 927              }
 928 
 929               void  VL_GDIEllipse::Update( const  VL_IrRect &  Rectangle)
 930              {
 931                  Update(Rectangle.Position,Rectangle.Size);
 932              }
 933 
 934  /* ********************************************************************************************************
 935  VL_GDIChord
 936  ******************************************************************************************************** */
 937 
 938               void  VL_GDIChord::DrawForPath()
 939              {
 940                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
 941                  VInt StartX = Round(cos(FStartAngle) * 1000 );
 942                  VInt StartY = Round( - sin(FStartAngle) * 1000 );
 943                  VInt EndX = Round(cos(FEndAngle) * 1000 );
 944                  VInt EndY = Round( - sin(FEndAngle) * 1000 );
 945                  FCanvas -> GetDC() -> Chord(
 946                      Offset.X + FPosition.X,
 947                      Offset.Y + FPosition.Y,
 948                      Offset.X + FPosition.X + FSize.X,
 949                      Offset.Y + FPosition.Y + FSize.Y,
 950                      Offset.X + FPosition.X + FSize.X / 2 + StartX,
 951                      Offset.Y + FPosition.Y + FSize.Y / 2 + StartY,
 952                      Offset.X + FPosition.X + FSize.X / 2 + EndX,
 953                      Offset.Y + FPosition.Y + FSize.Y / 2 + EndY
 954                      );
 955              }
 956 
 957              VL_GDIChord::VL_GDIChord(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekContainerShape)
 958              {
 959              }
 960 
 961              VL_GDIChord:: ~ VL_GDIChord()
 962              {
 963              }
 964 
 965              IVL_IrElementProperties *  VL_GDIChord::Properties()
 966              {
 967                   return   this ;
 968              }
 969 
 970              IVL_IrElementContainer *  VL_GDIChord::Container()
 971              {
 972                   return   this ;
 973              }
 974 
 975              VL_IrPoint VL_GDIChord::GetPosition()
 976              {
 977                   return  FPosition;
 978              }
 979 
 980              VL_IrPoint VL_GDIChord::GetSize()
 981              {
 982                   return  FSize;
 983              }
 984 
 985              VDouble VL_GDIChord::GetStartAngle()
 986              {
 987                   return  FStartAngle;
 988              }
 989 
 990              VDouble VL_GDIChord::GetEndAngle()
 991              {
 992                   return  FEndAngle;
 993              }
 994 
 995               void  VL_GDIChord::Update( const  VL_IrPoint &  Position ,  const  VL_IrPoint &  Size , VDouble Start , VDouble End)
 996              {
 997                  FPosition = Position;
 998                  FSize = Size;
 999                  FStartAngle = Start;
1000                  FEndAngle = End;
1001                  EnvironmentModified(FCanvas);
1002              }
1003 
1004               void  VL_GDIChord::Update( const  VL_IrRect &  Rectangle , VDouble Start , VDouble End)
1005              {
1006                  Update(Rectangle.Position,Rectangle.Size,Start,End);
1007              }
1008 
1009  /* ********************************************************************************************************
1010  VL_GDIPie
1011  ******************************************************************************************************** */
1012 
1013               void  VL_GDIPie::DrawForPath()
1014              {
1015                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1016                  VInt StartX = Round(cos(FStartAngle) * 1000 );
1017                  VInt StartY = Round( - sin(FStartAngle) * 1000 );
1018                  VInt EndX = Round(cos(FEndAngle) * 1000 );
1019                  VInt EndY = Round( - sin(FEndAngle) * 1000 );
1020                  FCanvas -> GetDC() -> Pie(
1021                      Offset.X + FPosition.X,
1022                      Offset.Y + FPosition.Y,
1023                      Offset.X + FPosition.X + FSize.X,
1024                      Offset.Y + FPosition.Y + FSize.Y,
1025                      Offset.X + FPosition.X + FSize.X / 2 + StartX,
1026                      Offset.Y + FPosition.Y + FSize.Y / 2 + StartY,
1027                      Offset.X + FPosition.X + FSize.X / 2 + EndX,
1028                      Offset.Y + FPosition.Y + FSize.Y / 2 + EndY
1029                      );
1030              }
1031 
1032              VL_GDIPie::VL_GDIPie(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekContainerShape)
1033              {
1034              }
1035 
1036              VL_GDIPie:: ~ VL_GDIPie()
1037              {
1038              }
1039 
1040              IVL_IrElementProperties *  VL_GDIPie::Properties()
1041              {
1042                   return   this ;
1043              }
1044 
1045              IVL_IrElementContainer *  VL_GDIPie::Container()
1046              {
1047                   return   this ;
1048              }
1049 
1050              VL_IrPoint VL_GDIPie::GetPosition()
1051              {
1052                   return  FPosition;
1053              }
1054 
1055              VL_IrPoint VL_GDIPie::GetSize()
1056              {
1057                   return  FSize;
1058              }
1059 
1060              VDouble VL_GDIPie::GetStartAngle()
1061              {
1062                   return  FStartAngle;
1063              }
1064 
1065              VDouble VL_GDIPie::GetEndAngle()
1066              {
1067                   return  FEndAngle;
1068              }
1069 
1070               void  VL_GDIPie::Update( const  VL_IrPoint &  Position ,  const  VL_IrPoint &  Size , VDouble Start , VDouble End)
1071              {
1072                  FPosition = Position;
1073                  FSize = Size;
1074                  FStartAngle = Start;
1075                  FEndAngle = End;
1076                  EnvironmentModified(FCanvas);
1077              }
1078 
1079               void  VL_GDIPie::Update( const  VL_IrRect &  Rectangle , VDouble Start , VDouble End)
1080              {
1081                  Update(Rectangle.Position,Rectangle.Size,Start,End);
1082              }
1083 
1084  /* ********************************************************************************************************
1085  VL_GDIArc
1086  ******************************************************************************************************** */
1087 
1088               void  VL_GDIArc::DrawForPath()
1089              {
1090                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1091                  VInt StartX = Round(cos(FStartAngle) * 1000 );
1092                  VInt StartY = Round( - sin(FStartAngle) * 1000 );
1093                  VInt EndX = Round(cos(FEndAngle) * 1000 );
1094                  VInt EndY = Round( - sin(FEndAngle) * 1000 );
1095                  FCanvas -> GetDC() -> Arc(
1096                      Offset.X + FPosition.X,
1097                      Offset.Y + FPosition.Y,
1098                      Offset.X + FPosition.X + FSize.X,
1099                      Offset.Y + FPosition.Y + FSize.Y,
1100                      Offset.X + FPosition.X + FSize.X / 2 + StartX,
1101                      Offset.Y + FPosition.Y + FSize.Y / 2 + StartY,
1102                      Offset.X + FPosition.X + FSize.X / 2 + EndX,
1103                      Offset.Y + FPosition.Y + FSize.Y / 2 + EndY
1104                      );
1105              }
1106 
1107              VL_GDIArc::VL_GDIArc(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekCurve)
1108              {
1109              }
1110 
1111              VL_GDIArc:: ~ VL_GDIArc()
1112              {
1113              }
1114 
1115              IVL_IrElementProperties *  VL_GDIArc::Properties()
1116              {
1117                   return   this ;
1118              }
1119 
1120              IVL_IrElementContainer *  VL_GDIArc::Container()
1121              {
1122                   return   0 ;
1123              }
1124 
1125              VL_IrPoint VL_GDIArc::GetPosition()
1126              {
1127                   return  FPosition;
1128              }
1129 
1130              VL_IrPoint VL_GDIArc::GetSize()
1131              {
1132                   return  FSize;
1133              }
1134 
1135              VDouble VL_GDIArc::GetStartAngle()
1136              {
1137                   return  FStartAngle;
1138              }
1139 
1140              VDouble VL_GDIArc::GetEndAngle()
1141              {
1142                   return  FEndAngle;
1143              }
1144 
1145               void  VL_GDIArc::Update( const  VL_IrPoint &  Position ,  const  VL_IrPoint &  Size , VDouble Start , VDouble End)
1146              {
1147                  FPosition = Position;
1148                  FSize = Size;
1149                  FStartAngle = Start;
1150                  FEndAngle = End;
1151                  EnvironmentModified(FCanvas);
1152              }
1153 
1154               void  VL_GDIArc::Update( const  VL_IrRect &  Rectangle , VDouble Start , VDouble End)
1155              {
1156                  Update(Rectangle.Position,Rectangle.Size,Start,End);
1157              }
1158 
1159  /* ********************************************************************************************************
1160  VL_GDIPolyline
1161  ******************************************************************************************************** */
1162              
1163               void  VL_GDIPolyline::DrawForPath()
1164              {
1165                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1166                   for (VInt i = 0 ;i < FCount;i ++ )
1167                  {
1168                      FBuffer[i].x = Offset.X + FPoints[i].X;
1169                      FBuffer[i].y = Offset.Y + FPoints[i].Y;
1170                  }
1171                  FCanvas -> GetDC() -> PolyLine(FBuffer,FCount);
1172              }
1173 
1174              VL_GDIPolyline::VL_GDIPolyline(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekCurve)
1175              {
1176                  FCount = 0 ;
1177                  FPoints = 0 ;
1178                  FBuffer = 0 ;
1179              }
1180 
1181              VL_GDIPolyline:: ~ VL_GDIPolyline()
1182              {
1183                   if (FPoints)delete[] FPoints;
1184                   if (FBuffer)delete[] FBuffer;
1185              }
1186 
1187              IVL_IrElementProperties *  VL_GDIPolyline::Properties()
1188              {
1189                   return   this ;
1190              }
1191 
1192              IVL_IrElementContainer *  VL_GDIPolyline::Container()
1193              {
1194                   return   0 ;
1195              }
1196 
1197              VInt VL_GDIPolyline::GetHandlerCount()
1198              {
1199                   return  FCount;
1200              }
1201 
1202              VL_IrPoint VL_GDIPolyline::GetHandler(VInt Index)
1203              {
1204                   if (Index >= 0   &&  Index < FCount)
1205                  {
1206                       return  FPoints[Index];
1207                  }
1208                   else
1209                  {
1210                       throw  L " 内部错误 " ;
1211                  }
1212              }
1213 
1214               void  VL_GDIPolyline::Update(VL_IrPoint *  Handlers , VInt Count)
1215              {
1216                  FCount = Count;
1217                   if (FPoints)delete[] FPoints;
1218                  FPoints = new  VL_IrPoint[FCount];
1219                   if (FBuffer)delete[] FBuffer;
1220                  FBuffer = new  POINT[FCount];
1221                   for (VInt i = 0 ;i < FCount;i ++ )
1222                  {
1223                      FPoints[i] = Handlers[i];
1224                  }
1225                  EnvironmentModified(FCanvas);
1226              }
1227 
1228  /* ********************************************************************************************************
1229  VL_GDIPolygon
1230  ******************************************************************************************************** */
1231              
1232               void  VL_GDIPolygon::DrawForPath()
1233              {
1234                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1235                   for (VInt i = 0 ;i < FCount;i ++ )
1236                  {
1237                      FBuffer[i].x = Offset.X + FPoints[i].X;
1238                      FBuffer[i].y = Offset.Y + FPoints[i].Y;
1239                  }
1240                  FCanvas -> GetDC() -> PolyGon(FBuffer,FCount);
1241              }
1242 
1243              VL_GDIPolygon::VL_GDIPolygon(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekContainerShape)
1244              {
1245                  FCount = 0 ;
1246                  FPoints = 0 ;
1247                  FBuffer = 0 ;
1248              }
1249 
1250              VL_GDIPolygon:: ~ VL_GDIPolygon()
1251              {
1252                   if (FPoints)delete[] FPoints;
1253                   if (FBuffer)delete[] FBuffer;
1254              }
1255 
1256              IVL_IrElementProperties *  VL_GDIPolygon::Properties()
1257              {
1258                   return   this ;
1259              }
1260 
1261              IVL_IrElementContainer *  VL_GDIPolygon::Container()
1262              {
1263                   return   this ;
1264              }
1265 
1266              VInt VL_GDIPolygon::GetHandlerCount()
1267              {
1268                   return  FCount;
1269              }
1270 
1271              VL_IrPoint VL_GDIPolygon::GetHandler(VInt Index)
1272              {
1273                   if (Index >= 0   &&  Index < FCount)
1274                  {
1275                       return  FPoints[Index];
1276                  }
1277                   else
1278                  {
1279                       throw  L " 内部错误 " ;
1280                  }
1281              }
1282 
1283               void  VL_GDIPolygon::Update(VL_IrPoint *  Handlers , VInt Count)
1284              {
1285                  FCount = Count;
1286                   if (FPoints)delete[] FPoints;
1287                  FPoints = new  VL_IrPoint[FCount];
1288                   if (FBuffer)delete[] FBuffer;
1289                  FBuffer = new  POINT[FCount];
1290                   for (VInt i = 0 ;i < FCount;i ++ )
1291                  {
1292                      FPoints[i] = Handlers[i];
1293                  }
1294                  EnvironmentModified(FCanvas);
1295              }
1296 
1297  /* ********************************************************************************************************
1298  VL_GDIBezier
1299  ******************************************************************************************************** */
1300              
1301               void  VL_GDIBezier::DrawForPath()
1302              {
1303                  VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1304                   for (VInt i = 0 ;i < FCount;i ++ )
1305                  {
1306                      FBuffer[i].x = Offset.X + FPoints[i].X;
1307                      FBuffer[i].y = Offset.Y + FPoints[i].Y;
1308                  }
1309                  FCanvas -> GetDC() -> PolyBezier(FBuffer,FCount);
1310              }
1311 
1312              VL_GDIBezier::VL_GDIBezier(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekCurve)
1313              {
1314                  FCount = 0 ;
1315                  FPoints = 0 ;
1316                  FBuffer = 0 ;
1317              }
1318 
1319              VL_GDIBezier:: ~ VL_GDIBezier()
1320              {
1321                   if (FPoints)delete[] FPoints;
1322                   if (FBuffer)delete[] FBuffer;
1323              }
1324 
1325              IVL_IrElementProperties *  VL_GDIBezier::Properties()
1326              {
1327                   return   this ;
1328              }
1329 
1330              IVL_IrElementContainer *  VL_GDIBezier::Container()
1331              {
1332                   return   0 ;
1333              }
1334 
1335              VInt VL_GDIBezier::GetHandlerCount()
1336              {
1337                   return  FCount;
1338              }
1339 
1340              VL_IrPoint VL_GDIBezier::GetHandler(VInt Index)
1341              {
1342                   if (Index >= 0   &&  Index < FCount)
1343                  {
1344                       return  FPoints[Index];
1345                  }
1346                   else
1347                  {
1348                       throw  L " 内部错误 " ;
1349                  }
1350              }
1351 
1352               void  VL_GDIBezier::Update(VL_IrPoint *  Handlers , VInt Count)
1353              {
1354                  FCount = Count;
1355                   if (FPoints)delete[] FPoints;
1356                  FPoints = new  VL_IrPoint[FCount];
1357                   if (FBuffer)delete[] FBuffer;
1358                  FBuffer = new  POINT[FCount];
1359                   for (VInt i = 0 ;i < FCount;i ++ )
1360                  {
1361                      FPoints[i] = Handlers[i];
1362                  }
1363                  EnvironmentModified(FCanvas);
1364              }
1365 
1366  /* ********************************************************************************************************
1367  VL_GDIText
1368  ******************************************************************************************************** */
1369 
1370               void  VL_GDIText::EnvironmentModified(VL_GDICanvas *  Canvas)
1371              {
1372                  VL_GDIElement::EnvironmentModified(Canvas);
1373                   if (FCanvas  &&  FFont)
1374                  {
1375                      FCanvas -> GetDC() -> SetFont(FFont -> GetGDIFont());
1376                      SIZE Size = FCanvas -> GetDC() -> MeasureString(FText);
1377                      FSize = VL_IrPoint(Size.cx,Size.cy);
1378                  }
1379                   else
1380                  {
1381                      FSize = VL_IrPoint();
1382                  }
1383              }
1384 
1385               void  VL_GDIText::Draw(VL_WinRegion::Ptr CurrentClip)
1386              {
1387                  VBool Painted = false ;
1388                   if ( ! FFont)
1389                  {
1390                      Painted = true ;
1391                  }
1392                   else   if ( ! FPen)
1393                  {
1394                       if (FBrush)
1395                      {
1396                           const  VL_IrBrushRec &  BrushRec = FBrush -> GetInternalData();
1397                           if (BrushRec.BrushKind == VL_IrBrushRec::bkSolid  &&  BrushRec.MainColor.A == 255 )
1398                          {
1399                              VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1400                              FCanvas -> GetDC() -> SetFont(FFont -> GetGDIFont());
1401                              FCanvas -> GetDC() -> SetTextColor(RGB(BrushRec.MainColor.R,BrushRec.MainColor.G,BrushRec.MainColor.B));
1402                              FCanvas -> GetDC() -> DrawString(Offset.X + FPosition.X,Offset.Y + FPosition.Y,FText);
1403                              Painted = true ;
1404                          }
1405                      }
1406                       else
1407                      {
1408                          Painted = true ;
1409                      }
1410                  }
1411                   if ( ! Painted)
1412                  {
1413                      VL_GDIElement::Draw(CurrentClip);
1414                  }
1415              }
1416 
1417               void  VL_GDIText::DrawShape(VBool Border)
1418              {
1419                  EnsureRegion();
1420                   if (Border)
1421                  {
1422                      FCanvas -> GetDC() -> SetBrush(FPenBrush -> GetGDIBrush());
1423                      FCanvas -> GetDC() -> FillRegion(FBorderRegion);
1424                  }
1425                   else
1426                  {
1427                      FCanvas -> GetDC() -> FillRegion(FContentRegion);
1428                  }
1429              }
1430              
1431               void  VL_GDIText::DrawForPath()
1432              {
1433                   if (FFont)
1434                  {
1435                      VL_IrPoint Offset = FParent ? FParent -> GetClientRectangle().Position:VL_IrPoint( 0 , 0 );
1436                      FCanvas -> GetDC() -> SetFont(FFont -> GetGDIFont());
1437                      FCanvas -> GetDC() -> DrawString(Offset.X + FPosition.X,Offset.Y + FPosition.Y,FText);
1438                  }
1439              }
1440 
1441              VL_GDIText::VL_GDIText(VL_GDIFactory *  Factory):VL_GDIElement(Factory,ekShape)
1442              {
1443              }
1444 
1445              VL_GDIText:: ~ VL_GDIText()
1446              {
1447              }
1448 
1449              IVL_IrElementProperties *  VL_GDIText::Properties()
1450              {
1451                   return   this ;
1452              }
1453 
1454              IVL_IrElementContainer *  VL_GDIText::Container()
1455              {
1456                   return   0 ;
1457              }
1458 
1459               void  VL_GDIText::SetPen(IVL_IrPen::Ptr Pen)
1460              {
1461                  VL_GDIElement::SetPen(Pen);
1462                   if (FPen)
1463                  {
1464                      FPenBrush = FFactory -> CreateBrush(FPen -> GetInternalBrush());
1465                  }
1466                   else
1467                  {
1468                      FPenBrush = 0 ;
1469                  }
1470              }
1471 
1472              VL_IrRect VL_GDIText::GetElementRectangle()
1473              {
1474                   return  VL_IrRect(FPosition,FSize);
1475              }
1476 
1477              VL_IrRect VL_GDIText::GetClientRectangle()
1478              {
1479                   return  VL_IrRect(FPosition,FSize);
1480              }
1481 
1482              VL_IrPoint VL_GDIText::GetPosition()
1483              {
1484                   return  FPosition;
1485              }
1486 
1487              VUnicodeString VL_GDIText::GetText()
1488              {
1489                   return  FText;
1490              }
1491 
1492               void  VL_GDIText::Update(VL_IrPoint Position , VUnicodeString Text)
1493              {
1494                  FPosition = Position;
1495                  FText = Text;
1496                  EnvironmentModified(FCanvas);
1497              }
1498 
1499  /* ********************************************************************************************************
1500  VL_GDICanvas
1501  ******************************************************************************************************** */
1502 
1503               void  VL_GDICanvas::UpdateBuffer()
1504              {
1505                  FBuffer = new  VL_WinBitmap(FHost -> GetClientWidth(),FHost -> GetClientHeight(),VL_WinBitmap::vbb32Bits, true );
1506                  SetPolyFillMode(FBuffer -> GetWinDC() -> GetHandle(),WINDING);
1507                  FBuffer -> GetWinDC() -> SetBackTransparent( true );
1508                  FAlphaBuffer = new  VL_WinBitmap(FHost -> GetClientWidth(),FHost -> GetClientHeight(),VL_WinBitmap::vbb32Bits, true );
1509                  FAlphaBuffer -> BuildAlphaChannel();
1510                   if (FRootElement)
1511                  {
1512                      FRootElement -> EnvironmentModified( this );
1513                  }
1514                  Render();
1515              }
1516 
1517               void  VL_GDICanvas::HostPaint(VL_Base *  Sender)
1518              {
1519                  FHostDC -> Draw( 0 , 0 ,FBuffer);
1520              }
1521 
1522               void  VL_GDICanvas::HostSized(VL_Base *  Sender)
1523              {
1524                  UpdateBuffer();
1525              }
1526 
1527              VL_GDICanvas::VL_GDICanvas(VL_GDIFactory *  Factory , VL_WinControl *  Control)
1528              {
1529                  FFactory = Factory;
1530                  FHost = Control;
1531                  FHostDC = new  VL_WinControlDC(FHost -> GetHandle());
1532                  FEmptyPen = new  VL_WinPen(PS_NULL, 1 , 0 );
1533                  FEmptyBrush = new  VL_WinBrush;
1534                  FBackgroundBrush = new  VL_WinBrush(RGB( 255 , 255 , 255 ));
1535                  UpdateBuffer();
1536 
1537                  FHost -> OnPaint.Bind( this , & VL_GDICanvas::HostPaint);
1538                  FHost -> OnSized.Bind( this , & VL_GDICanvas::HostSized);
1539              }
1540 
1541              VL_GDICanvas:: ~ VL_GDICanvas()
1542              {
1543                  FHost -> OnPaint.Unbind( this , & VL_GDICanvas::HostPaint);
1544                  FHost -> OnSized.Unbind( this , & VL_GDICanvas::HostSized);
1545                  delete FHostDC;
1546              }
1547 
1548              IVL_IrFactory *  VL_GDICanvas::GetFactory()
1549              {
1550                   return  FFactory;
1551              }
1552 
1553              VL_IrPoint VL_GDICanvas::GetSize()
1554              {
1555                   return  VL_IrPoint(FBuffer -> GetWidth(),FBuffer -> GetHeight());
1556              }
1557 
1558              IVL_IrElement::Ptr VL_GDICanvas::GetRootElement()
1559              {
1560                   return  FRootElement;
1561              }
1562 
1563               void  VL_GDICanvas::SetRootElement(IVL_IrElement::Ptr Element)
1564              {
1565                  FRootElement = Element;
1566                   if (Element)
1567                  {
1568                       if (FRootElement)
1569                      {
1570                          FRootElement -> EnvironmentModified( this );
1571                      }
1572                       else
1573                      {
1574                           throw  L " 内部错误 " ;
1575                      }
1576                  }
1577              }
1578 
1579               void  VL_GDICanvas::Render()
1580              {
1581                  FBuffer -> GetWinDC() -> SetBrush(FBackgroundBrush);
1582                  FBuffer -> GetWinDC() -> FillRect( 0 , 0 ,FBuffer -> GetWidth(),FBuffer -> GetHeight());
1583                   if (FRootElement)
1584                  {
1585                      FRootElement -> Draw( 0 );
1586                  }
1587                  UpdateWindow(FHost -> GetHandle());
1588              }
1589 
1590              VL_WinDC *  VL_GDICanvas::GetDC()
1591              {
1592                   return  FBuffer -> GetWinDC();
1593              }
1594 
1595              VL_WinBitmap::Ptr VL_GDICanvas::GetAlphaBuffer()
1596              {
1597                   return  FAlphaBuffer;
1598              }
1599 
1600              VL_WinPen::Ptr VL_GDICanvas::GetEmptyPen()
1601              {
1602                   return  FEmptyPen;
1603              }
1604 
1605              VL_WinBrush::Ptr VL_GDICanvas::GetEmptyBrush()
1606              {
1607                   return  FEmptyBrush;
1608              }
1609 
1610  /* ********************************************************************************************************
1611  VL_GDIFactory
1612  ******************************************************************************************************** */
1613 
1614               class  GDIFactoryRegister
1615              {
1616               public :
1617                   static  IVL_IrFactory::Ptr Constructor()
1618                  {
1619                       return   new  VL_GDIFactory;
1620                  }
1621 
1622                  GDIFactoryRegister()
1623                  {
1624                      RegisterInteractionFactory(L " GDI " ,Constructor);
1625                  }
1626              } _GDIFactoryRegister;
1627 
1628              IVL_IrBrush::Ptr VL_GDIFactory::CreateBrush( const  VL_IrBrushRec &  Brush)
1629              {
1630                   return   new  VL_GDIBrush( this ,Brush);
1631              }
1632 
1633              IVL_IrPen::Ptr VL_GDIFactory::CreatePen( const  VL_IrBrushRec &  Brush ,  const  VL_IrPenRec &  Pen)
1634              {
1635                   return   new  VL_GDIPen( this ,Brush,Pen);
1636              }
1637 
1638              IVL_IrFont::Ptr VL_GDIFactory::CreateFont( const  VL_IrFontRec &  Font)
1639              {
1640                   return   new  VL_GDIFont( this ,Font);
1641              }
1642 
1643              IVL_IrLine::Ptr VL_GDIFactory::CreateLine()
1644              {
1645                   return   new  VL_GDILine( this );
1646              }
1647 
1648              IVL_IrRectangle::Ptr VL_GDIFactory::CreateRectangle()
1649              {
1650                   return   new  VL_GDIRectangle( this );
1651              }
1652 
1653              IVL_IrRoundRectangle::Ptr VL_GDIFactory::CreateRoundRectangle()
1654              {
1655                   return   new  VL_GDIRoundRectangle( this );
1656              }
1657 
1658              IVL_IrEllipse::Ptr VL_GDIFactory::CreateEllipse()
1659              {
1660                   return   new  VL_GDIEllipse( this );
1661              }
1662 
1663              IVL_IrChord::Ptr VL_GDIFactory::CreateChord()
1664              {
1665                   return   new  VL_GDIChord( this );
1666              }
1667 
1668              IVL_IrPie::Ptr VL_GDIFactory::CreatePie()
1669              {
1670                   return   new  VL_GDIPie( this );
1671              }
1672 
1673              IVL_IrArc::Ptr VL_GDIFactory::CreateArc()
1674              {
1675                   return   new  VL_GDIArc( this );
1676              }
1677 
1678              IVL_IrPolyline::Ptr VL_GDIFactory::CreatePolyline()
1679              {
1680                   return   new  VL_GDIPolyline( this );
1681              }
1682 
1683              IVL_IrPolygon::Ptr VL_GDIFactory::CreatePolygon()
1684              {
1685                   return   new  VL_GDIPolygon( this );
1686              }
1687 
1688              IVL_IrBezier::Ptr VL_GDIFactory::CreateBezier()
1689              {
1690                   return   new  VL_GDIBezier( this );
1691              }
1692 
1693              IVL_IrText::Ptr VL_GDIFactory::CreateText()
1694              {
1695                   return   new  VL_GDIText( this );
1696              }
1697 
1698              IVL_IrCanvas::Ptr VL_GDIFactory::CreateCanvas(VL_WinControl *  Control)
1699              {
1700                   return   new  VL_GDICanvas( this ,Control);
1701              }
1702          }
1703      }
1704  }

你可能感兴趣的:(C++界面库:在GDI上添加完全的alpha混合支持)