随笔-341  评论-2670  文章-0  trackbacks-0
    做完了小型WCF之后,就是小型的WPF了。之前那个完全避免用户大部分的错误使用导致的死锁的方案还有一点点的问题,所以先休息一下,做做别的。为了在C++上重现一套类似WPF的工具,首先要解决绘图部分。

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



    之所以不用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 }

posted on 2009-08-02 02:41 陈梓瀚(vczh) 阅读(6140) 评论(3)  编辑 收藏 引用 所属分类: 2D

评论:
# re: C++界面库:在GDI上添加完全的alpha混合支持 2009-08-02 18:30 | ABC
很厉害!  回复  更多评论
  
# re: C++界面库:在GDI上添加完全的alpha混合支持 2009-08-03 01:47 | CY
扫了一遍,没有发现你很强大的汇编代码....  回复  更多评论
  
# re: C++界面库:在GDI上添加完全的alpha混合支持 2009-08-04 23:15 | 陈梓瀚(vczh)
@CY
因为这样子就很难clip了……  回复  更多评论
  

只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理