├── .gitignore ├── README.md ├── WindowsToast.dpk ├── WindowsToast.dproj ├── boss-lock.json ├── boss.json └── src └── FMX.Toast.Windows.pas /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Delphi compiler-generated binaries (safe to delete) 30 | *.exe 31 | *.dll 32 | *.bpl 33 | *.bpi 34 | *.dcp 35 | *.so 36 | *.apk 37 | *.drc 38 | *.map 39 | *.dres 40 | *.rsm 41 | *.tds 42 | *.dcu 43 | *.lib 44 | *.a 45 | *.o 46 | *.ocx 47 | 48 | # Delphi autogenerated files (duplicated info) 49 | *.cfg 50 | *.hpp 51 | *Resource.rc 52 | 53 | # Delphi local files (user-specific info) 54 | *.local 55 | *.identcache 56 | *.projdata 57 | *.tvsconfig 58 | *.dsk 59 | 60 | # Delphi history and backups 61 | __history/ 62 | __recovery/ 63 | *.~* 64 | 65 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 66 | *.stat 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Delphi Windows Toast (Only Firemonkey) 2 | Windows Toast like Android Toast 3 | 4 | 5 | # Usage 6 | 7 | Place TWindowsToastDialog on form; 8 | 9 | On your form, anywhere in your source, call the MakeText procedure; 10 | 11 | example: 12 | 13 | ```pascal 14 | WindowsToastDialog1.MakeText("Testing Windows Toast"); 15 | ``` 16 | # ---- 17 | 18 | You can change the duration, text color and background color; 19 | 20 | MakeText(Text; Duration; BackgroundColor; TextColor); 21 | 22 | example: 23 | 24 | ```pascal 25 | WindowsToastDialog1.MakeText('Toast on Windows Application', ToastDurationLengthShort, $FF009688, $FFFFFFFF); 26 | ``` 27 | -------------------------------------------------------------------------------- /WindowsToast.dpk: -------------------------------------------------------------------------------- 1 | package WindowsToast; 2 | 3 | {$R *.res} 4 | {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} 5 | {$ALIGN 8} 6 | {$ASSERTIONS ON} 7 | {$BOOLEVAL OFF} 8 | {$DEBUGINFO OFF} 9 | {$EXTENDEDSYNTAX ON} 10 | {$IMPORTEDDATA ON} 11 | {$IOCHECKS ON} 12 | {$LOCALSYMBOLS ON} 13 | {$LONGSTRINGS ON} 14 | {$OPENSTRINGS ON} 15 | {$OPTIMIZATION OFF} 16 | {$OVERFLOWCHECKS OFF} 17 | {$RANGECHECKS OFF} 18 | {$REFERENCEINFO ON} 19 | {$SAFEDIVIDE OFF} 20 | {$STACKFRAMES ON} 21 | {$TYPEDADDRESS OFF} 22 | {$VARSTRINGCHECKS ON} 23 | {$WRITEABLECONST OFF} 24 | {$MINENUMSIZE 1} 25 | {$IMAGEBASE $400000} 26 | {$DEFINE DEBUG} 27 | {$ENDIF IMPLICITBUILDING} 28 | {$IMPLICITBUILD ON} 29 | 30 | requires 31 | rtl, 32 | fmx; 33 | 34 | contains 35 | FMX.Toast.Windows in 'src\FMX.Toast.Windows.pas'; 36 | 37 | end. 38 | -------------------------------------------------------------------------------- /WindowsToast.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {200B8DD7-A1A3-4961-8C34-216013A56F9B} 4 | WindowsToast.dpk 5 | 18.4 6 | FMX 7 | True 8 | Debug 9 | Win32 10 | 1119 11 | Package 12 | 13 | 14 | true 15 | 16 | 17 | true 18 | Base 19 | true 20 | 21 | 22 | true 23 | Base 24 | true 25 | 26 | 27 | true 28 | Base 29 | true 30 | 31 | 32 | true 33 | Base 34 | true 35 | 36 | 37 | true 38 | Base 39 | true 40 | 41 | 42 | true 43 | Base 44 | true 45 | 46 | 47 | true 48 | Base 49 | true 50 | 51 | 52 | true 53 | Base 54 | true 55 | 56 | 57 | true 58 | Base 59 | true 60 | 61 | 62 | true 63 | Cfg_1 64 | true 65 | true 66 | 67 | 68 | true 69 | Base 70 | true 71 | 72 | 73 | .\$(Platform)\$(Config) 74 | .\$(Platform)\$(Config) 75 | false 76 | false 77 | false 78 | false 79 | false 80 | true 81 | true 82 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 83 | All 84 | WindowsToast 85 | 86 | 87 | None 88 | android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar 89 | rtl;fmx;$(DCC_UsePackage) 90 | package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= 91 | Debug 92 | 93 | 94 | None 95 | rtl;fmx;$(DCC_UsePackage) 96 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera 97 | iPhoneAndiPad 98 | true 99 | Debug 100 | $(MSBuildProjectName) 101 | 102 | 103 | None 104 | rtl;fmx;$(DCC_UsePackage) 105 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera 106 | iPhoneAndiPad 107 | true 108 | Debug 109 | $(MSBuildProjectName) 110 | 111 | 112 | None 113 | rtl;fmx;$(DCC_UsePackage) 114 | CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone & iPad;CFBundleResourceSpecification=ResourceRules.plist;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;FMLocalNotificationPermission=false;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSCameraUsageDescription=The reason for accessing the camera 115 | iPhoneAndiPad 116 | true 117 | 118 | 119 | rtl;$(DCC_UsePackage) 120 | 121 | 122 | rtl;fmx;$(DCC_UsePackage) 123 | CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts 124 | Debug 125 | 126 | 127 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 128 | Debug 129 | true 130 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 131 | 1033 132 | rtl;fmx;$(DCC_UsePackage) 133 | 134 | 135 | rtl;fmx;$(DCC_UsePackage) 136 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 137 | Debug 138 | true 139 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 140 | 1033 141 | 142 | 143 | DEBUG;$(DCC_Define) 144 | true 145 | false 146 | true 147 | true 148 | true 149 | 150 | 151 | false 152 | 153 | 154 | false 155 | RELEASE;$(DCC_Define) 156 | 0 157 | 0 158 | 159 | 160 | 161 | MainSource 162 | 163 | 164 | 165 | 166 | 167 | Cfg_2 168 | Base 169 | 170 | 171 | Base 172 | 173 | 174 | Cfg_1 175 | Base 176 | 177 | 178 | 179 | Delphi.Personality.12 180 | Package 181 | 182 | 183 | 184 | WindowsToast.dpk 185 | 186 | 187 | 188 | 189 | 190 | WindowsToast.bpl 191 | true 192 | 193 | 194 | 195 | 196 | true 197 | 198 | 199 | 200 | 201 | true 202 | 203 | 204 | 205 | 206 | true 207 | 208 | 209 | 210 | 211 | true 212 | 213 | 214 | 215 | 216 | 1 217 | 218 | 219 | Contents\MacOS 220 | 0 221 | 222 | 223 | 224 | 225 | classes 226 | 1 227 | 228 | 229 | 230 | 231 | library\lib\armeabi-v7a 232 | 1 233 | 234 | 235 | 236 | 237 | library\lib\armeabi 238 | 1 239 | 240 | 241 | 242 | 243 | library\lib\mips 244 | 1 245 | 246 | 247 | 248 | 249 | library\lib\armeabi-v7a 250 | 1 251 | 252 | 253 | 254 | 255 | res\drawable 256 | 1 257 | 258 | 259 | 260 | 261 | res\values 262 | 1 263 | 264 | 265 | 266 | 267 | res\drawable 268 | 1 269 | 270 | 271 | 272 | 273 | res\drawable-xxhdpi 274 | 1 275 | 276 | 277 | 278 | 279 | res\drawable-ldpi 280 | 1 281 | 282 | 283 | 284 | 285 | res\drawable-mdpi 286 | 1 287 | 288 | 289 | 290 | 291 | res\drawable-hdpi 292 | 1 293 | 294 | 295 | 296 | 297 | res\drawable-xhdpi 298 | 1 299 | 300 | 301 | 302 | 303 | res\drawable-small 304 | 1 305 | 306 | 307 | 308 | 309 | res\drawable-normal 310 | 1 311 | 312 | 313 | 314 | 315 | res\drawable-large 316 | 1 317 | 318 | 319 | 320 | 321 | res\drawable-xlarge 322 | 1 323 | 324 | 325 | 326 | 327 | 1 328 | 329 | 330 | 1 331 | 332 | 333 | 0 334 | 335 | 336 | 337 | 338 | 1 339 | .framework 340 | 341 | 342 | 0 343 | 344 | 345 | 346 | 347 | 1 348 | .dylib 349 | 350 | 351 | 0 352 | .dll;.bpl 353 | 354 | 355 | 356 | 357 | 1 358 | .dylib 359 | 360 | 361 | 1 362 | .dylib 363 | 364 | 365 | 1 366 | .dylib 367 | 368 | 369 | 1 370 | .dylib 371 | 372 | 373 | 0 374 | .bpl 375 | 376 | 377 | 378 | 379 | 0 380 | 381 | 382 | 0 383 | 384 | 385 | 0 386 | 387 | 388 | 0 389 | 390 | 391 | 0 392 | 393 | 394 | 0 395 | 396 | 397 | 398 | 399 | 1 400 | 401 | 402 | 1 403 | 404 | 405 | 1 406 | 407 | 408 | 409 | 410 | 1 411 | 412 | 413 | 1 414 | 415 | 416 | 1 417 | 418 | 419 | 420 | 421 | 1 422 | 423 | 424 | 1 425 | 426 | 427 | 1 428 | 429 | 430 | 431 | 432 | 1 433 | 434 | 435 | 1 436 | 437 | 438 | 1 439 | 440 | 441 | 442 | 443 | 1 444 | 445 | 446 | 1 447 | 448 | 449 | 1 450 | 451 | 452 | 453 | 454 | 1 455 | 456 | 457 | 1 458 | 459 | 460 | 1 461 | 462 | 463 | 464 | 465 | 1 466 | 467 | 468 | 1 469 | 470 | 471 | 1 472 | 473 | 474 | 475 | 476 | 1 477 | 478 | 479 | 480 | 481 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 482 | 1 483 | 484 | 485 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 486 | 1 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 1 495 | 496 | 497 | 1 498 | 499 | 500 | 1 501 | 502 | 503 | 504 | 505 | 506 | 507 | Contents\Resources 508 | 1 509 | 510 | 511 | 512 | 513 | library\lib\armeabi-v7a 514 | 1 515 | 516 | 517 | 1 518 | 519 | 520 | 1 521 | 522 | 523 | 1 524 | 525 | 526 | 1 527 | 528 | 529 | 1 530 | 531 | 532 | 0 533 | 534 | 535 | 536 | 537 | 1 538 | 539 | 540 | 1 541 | 542 | 543 | 544 | 545 | Assets 546 | 1 547 | 548 | 549 | Assets 550 | 1 551 | 552 | 553 | 554 | 555 | Assets 556 | 1 557 | 558 | 559 | Assets 560 | 1 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | True 574 | True 575 | True 576 | True 577 | False 578 | True 579 | True 580 | True 581 | 582 | 583 | 12 584 | 585 | 586 | 587 | 588 | 589 | -------------------------------------------------------------------------------- /boss-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "hash": "d41d8cd98f00b204e9800998ecf8427e", 3 | "updated": "2019-08-13T11:02:12.0394813-03:00", 4 | "installedModules": {} 5 | } -------------------------------------------------------------------------------- /boss.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DelphiWindowsToast", 3 | "description": "", 4 | "version": "1.0.0", 5 | "homepage": "", 6 | "mainsrc": "src/", 7 | "projects": [ 8 | "WindowsToast.dproj" 9 | ], 10 | "dependencies": {} 11 | } -------------------------------------------------------------------------------- /src/FMX.Toast.Windows.pas: -------------------------------------------------------------------------------- 1 | unit FMX.Toast.Windows; 2 | 3 | interface 4 | 5 | uses 6 | System.SysUtils, System.Classes, System.Types, System.UITypes, FMX.Types, FMX.TextLayout, 7 | FMX.Controls, FMX.Graphics, FMX.Ani, FMX.Forms, FMX.Layouts, 8 | System.Generics.Collections, DateUtils; 9 | 10 | type 11 | TWindowsToastDuration = (ToastDurationLengthShort, ToastDurationLengthLong); 12 | 13 | TWindowsToast = class(TControl) 14 | private 15 | FBackgroundSize: TSize; 16 | FFloatAnimationOpacity: TFloatAnimation; 17 | FText: string; 18 | FFont: TFont; 19 | FFillText: TBrush; 20 | FFillBackground: TBrush; 21 | FOnFinishToast: TNotifyEvent; 22 | FIsStarted: Boolean; 23 | FDuration: TWindowsToastDuration; 24 | FThreadDuration: TThread; 25 | procedure SetText(const Value: String); 26 | procedure SetFillText(const Value: TBrush); 27 | procedure SetFillBackground(const Value: TBrush); 28 | procedure SetOnFinishToast(const Value: TNotifyEvent); 29 | procedure SetIsStarted(const Value: Boolean); 30 | procedure SetDuration(const Value: TWindowsToastDuration); 31 | { Private declarations } 32 | protected 33 | { Protected declarations } 34 | procedure DoFinishToast(Sender: TObject); 35 | property FillText: TBrush read FFillText write SetFillText; 36 | property FillBackground: TBrush read FFillBackground write SetFillBackground; 37 | property Duration: TWindowsToastDuration read FDuration write SetDuration; 38 | procedure Paint; override; 39 | procedure DoTextChanged(Sender: TObject); 40 | procedure RecalcToastHeight; 41 | public 42 | { Public declarations } 43 | constructor Create(AOwner: TComponent); override; 44 | destructor Destroy; override; 45 | procedure Start; 46 | published 47 | { Published declarations } 48 | property Align; 49 | property Anchors; 50 | property Width; 51 | property Height; 52 | property Size; 53 | property Enabled; 54 | property Padding; 55 | property Margins; 56 | property Opacity; 57 | property ClipChildren; 58 | property ClipParent; 59 | property HitTest; 60 | property Visible; 61 | property Locked; 62 | property Position; 63 | property Text: String read FText write SetText; 64 | property OnClick; 65 | property OnDblClick; 66 | property OnPainting; 67 | property OnPaint; 68 | property OnResize; 69 | property OnResized; 70 | property OnFinishToast: TNotifyEvent read FOnFinishToast write SetOnFinishToast; 71 | property IsStarted: Boolean read FIsStarted write SetIsStarted; 72 | end; 73 | 74 | TWindowsToastDialog = class(TCustomScrollBox) 75 | private 76 | FToastList: TObjectList; 77 | { private declarations } 78 | protected 79 | { protected declarations } 80 | procedure DoFinishToast(Sender: TObject); 81 | function GetDefaultStyleLookupName: string; override; 82 | function DoCalcContentBounds: TRectF; override; 83 | procedure Paint; override; 84 | procedure DoUpdateAniCalculations(const AAniCalculations: TScrollCalculations); override; 85 | public 86 | { public declarations } 87 | constructor Create(AOwner: TComponent); override; 88 | destructor Destroy; override; 89 | property Content; 90 | procedure MakeText(AText: string; const ADuration: TWindowsToastDuration = TWindowsToastDuration.ToastDurationLengthShort; 91 | ABackgroundColor: TAlphaColor = $FF525252; ATextColor: TAlphaColor = $FFFFFFFF); 92 | published 93 | { published declarations } 94 | property Align; 95 | property Anchors; 96 | property ClipParent; 97 | property Cursor; 98 | property DisableMouseWheel; 99 | property Height; 100 | property Locked; 101 | property Margins; 102 | property Opacity; 103 | property Padding; 104 | property Position; 105 | property RotationAngle; 106 | property RotationCenter; 107 | property Scale; 108 | property Size; 109 | property TouchTargetExpansion; 110 | property Visible; 111 | property Width; 112 | end; 113 | 114 | procedure Register; 115 | 116 | implementation 117 | 118 | procedure Register; 119 | begin 120 | RegisterComponents('Material Design', [TWindowsToastDialog]); 121 | end; 122 | 123 | { TWindowsToast } 124 | 125 | constructor TWindowsToast.Create(AOwner: TComponent); 126 | begin 127 | inherited; 128 | FIsStarted := False; 129 | FFont := TFont.Create; 130 | FFont.Size := 14; 131 | FFont.Family := 'Roboto'; 132 | 133 | FFillText := TBrush.Create(TBrushKind.Solid, $FFFFFFFF); 134 | FFillBackground := TBrush.Create(TBrushKind.Solid, $FF525252); 135 | FFloatAnimationOpacity := TFloatAnimation.Create(Self); 136 | AddObject(FFloatAnimationOpacity); 137 | Width := 300; 138 | Height := 30; 139 | 140 | FBackgroundSize := TSize.Create(270, 30); 141 | 142 | HitTest := False; 143 | end; 144 | 145 | destructor TWindowsToast.Destroy; 146 | begin 147 | FFont.Free; 148 | FFillText.Free; 149 | FFillBackground.Free; 150 | FFloatAnimationOpacity.Free; 151 | if IsStarted then 152 | begin 153 | FThreadDuration.Terminate; 154 | FreeAndNil(FThreadDuration); 155 | end; 156 | inherited; 157 | end; 158 | 159 | procedure TWindowsToast.DoFinishToast(Sender: TObject); 160 | begin 161 | if Assigned(FOnFinishToast) then 162 | FOnFinishToast(Self); 163 | end; 164 | 165 | procedure TWindowsToast.DoTextChanged(Sender: TObject); 166 | begin 167 | RecalcToastHeight; 168 | Repaint; 169 | end; 170 | 171 | procedure TWindowsToast.Paint; 172 | var 173 | FillTextRect: TRectF; 174 | begin 175 | inherited; 176 | FillTextRect := TRectF.Create(Width / 2 - FBackgroundSize.Width / 2, 15, Width / 2 + FBackgroundSize.Width / 2, FBackgroundSize.Height - 15); 177 | // Desenha primeiro o fundo... 178 | Canvas.Fill.Assign(FFillBackground); 179 | Canvas.FillRect(TRectF.Create((Width / 2 - FBackgroundSize.Width / 2) - 15, 0, (Width / 2 + FBackgroundSize.Width / 2) + 15, 180 | FBackgroundSize.Height), FBackgroundSize.Height / 2, FBackgroundSize.Height / 2, [TCorner.TopLeft, TCorner.TopRight, TCorner.BottomLeft, 181 | TCorner.BottomRight], Opacity, TCornerType.Round); 182 | // Depois desenha o texto... 183 | Canvas.Fill.Assign(FFillText); 184 | Canvas.FillText(FillTextRect, FText, True, Opacity * 0.87 / 1, [], TTextAlign.Center, TTextAlign.Leading); 185 | end; 186 | 187 | procedure TWindowsToast.RecalcToastHeight; 188 | var 189 | MeasureTextRect: TRectF; 190 | begin 191 | // Calcula o tamanho do texto 192 | MeasureTextRect := TRectF.Create(0, 0, FBackgroundSize.Width, Screen.Height); 193 | Canvas.Fill.Assign(FFillText); 194 | Canvas.Font.Assign(FFont); 195 | Canvas.MeasureText(MeasureTextRect, FText, True, [], TTextAlign.Center, TTextAlign.Leading); 196 | FBackgroundSize.Height := Round(MeasureTextRect.Height) + 30; 197 | Height := FBackgroundSize.Height; 198 | if MeasureTextRect.Width < 250 then 199 | FBackgroundSize.Width := Round(MeasureTextRect.Width) + 30; 200 | end; 201 | 202 | procedure TWindowsToast.SetDuration(const Value: TWindowsToastDuration); 203 | begin 204 | FDuration := Value; 205 | end; 206 | 207 | procedure TWindowsToast.SetFillBackground(const Value: TBrush); 208 | begin 209 | FFillBackground := Value; 210 | end; 211 | 212 | procedure TWindowsToast.SetFillText(const Value: TBrush); 213 | begin 214 | FFillText := Value; 215 | end; 216 | 217 | procedure TWindowsToast.SetIsStarted(const Value: Boolean); 218 | begin 219 | FIsStarted := Value; 220 | end; 221 | 222 | procedure TWindowsToast.SetOnFinishToast(const Value: TNotifyEvent); 223 | begin 224 | FOnFinishToast := Value; 225 | end; 226 | 227 | procedure TWindowsToast.SetText(const Value: String); 228 | var 229 | OldText: string; 230 | begin 231 | OldText := FText; 232 | FText := Value; 233 | if OldText <> FText then 234 | DoTextChanged(Self); 235 | end; 236 | 237 | procedure TWindowsToast.Start; 238 | begin 239 | FIsStarted := True; 240 | FFloatAnimationOpacity.PropertyName := 'Opacity'; 241 | FFloatAnimationOpacity.Duration := 0.5; 242 | FFloatAnimationOpacity.StartValue := 0; 243 | FFloatAnimationOpacity.StopValue := 1; 244 | 245 | FThreadDuration := TThread.CreateAnonymousThread( 246 | procedure 247 | var 248 | LDateTime: TDateTime; 249 | LNow: TDateTime; 250 | begin 251 | 252 | TThread.Synchronize(nil, 253 | procedure 254 | begin 255 | FFloatAnimationOpacity.Enabled := True; 256 | end); 257 | LDateTime := Now(); 258 | LNow := Now(); 259 | 260 | case FDuration of 261 | ToastDurationLengthShort: 262 | while (SecondsBetween(LNow, LDateTime) <= 3) and (not FThreadDuration.CheckTerminated) do 263 | begin 264 | LNow := Now(); 265 | Sleep(100); 266 | end; 267 | ToastDurationLengthLong: 268 | while (SecondsBetween(LNow, LDateTime) <= 6) and (not FThreadDuration.CheckTerminated) do 269 | begin 270 | LNow := Now(); 271 | Sleep(100); 272 | end; 273 | end; 274 | 275 | TThread.Synchronize(nil, 276 | procedure 277 | begin 278 | FFloatAnimationOpacity.Enabled := False; 279 | FFloatAnimationOpacity.StartValue := 1; 280 | FFloatAnimationOpacity.StopValue := 0; 281 | FFloatAnimationOpacity.OnFinish := DoFinishToast; 282 | FFloatAnimationOpacity.Enabled := True; 283 | end); 284 | 285 | end); 286 | FThreadDuration.FreeOnTerminate := False; 287 | FThreadDuration.Start; 288 | end; 289 | 290 | { TWindowsToastDialog } 291 | 292 | constructor TWindowsToastDialog.Create(AOwner: TComponent); 293 | begin 294 | inherited; 295 | ShowScrollBars := False; 296 | FToastList := TObjectList.Create; 297 | HitTest := False; 298 | Content.Locked := True; 299 | Content.Enabled := False; 300 | Enabled := False; 301 | end; 302 | 303 | procedure TWindowsToastDialog.Paint; 304 | begin 305 | inherited; 306 | if (csDesigning in ComponentState) and not Locked then 307 | DrawDesignBorder(DesignBorderColor or TAlphaColorRec.Alpha, DesignBorderColor); 308 | end; 309 | 310 | destructor TWindowsToastDialog.Destroy; 311 | begin 312 | FToastList.Clear; 313 | FreeAndNil(FToastList); 314 | inherited; 315 | end; 316 | 317 | function TWindowsToastDialog.DoCalcContentBounds: TRectF; 318 | begin 319 | if (Content <> nil) and (ContentLayout <> nil) then 320 | Content.Width := ContentLayout.Width; 321 | Result := inherited DoCalcContentBounds; 322 | if ContentLayout <> nil then 323 | Result.Width := ContentLayout.Width; 324 | end; 325 | 326 | procedure TWindowsToastDialog.DoFinishToast(Sender: TObject); 327 | var 328 | LWindowsToast: TWindowsToast; 329 | begin 330 | LWindowsToast := Sender as TWindowsToast; 331 | LWindowsToast.Parent := nil; 332 | FToastList.Remove(LWindowsToast); 333 | // Self.Content.Repaint; 334 | end; 335 | 336 | procedure TWindowsToastDialog.DoUpdateAniCalculations(const AAniCalculations: TScrollCalculations); 337 | begin 338 | inherited DoUpdateAniCalculations(AAniCalculations); 339 | AAniCalculations.TouchTracking := AAniCalculations.TouchTracking - [ttHorizontal]; 340 | end; 341 | 342 | function TWindowsToastDialog.GetDefaultStyleLookupName: string; 343 | begin 344 | Result := 'scrollboxstyle'; 345 | end; 346 | 347 | procedure TWindowsToastDialog.MakeText(AText: string; const ADuration: TWindowsToastDuration; ABackgroundColor, ATextColor: TAlphaColor); 348 | var 349 | LWindowsToast: TWindowsToast; 350 | begin 351 | LWindowsToast := TWindowsToast.Create(nil); 352 | FToastList.Add(LWindowsToast); 353 | Content.AddObject(LWindowsToast); 354 | 355 | LWindowsToast.Opacity := 0; 356 | LWindowsToast.FillBackground.Color := ABackgroundColor; 357 | LWindowsToast.FillText.Color := ATextColor; 358 | LWindowsToast.Text := AText; 359 | LWindowsToast.Duration := ADuration; 360 | LWindowsToast.OnFinishToast := DoFinishToast; 361 | LWindowsToast.Margins.Bottom := 5; 362 | 363 | // LWindowsToast.Position.Y := Self.Content.Height - LWindowsToast.Height - (30); 364 | LWindowsToast.Position.X := Self.Content.Width / 2 - LWindowsToast.Width / 2; 365 | LWindowsToast.Position.Y := Content.Width; 366 | LWindowsToast.Align := TAlignLayout.Bottom; 367 | LWindowsToast.Start; 368 | 369 | end; 370 | 371 | end. 372 | --------------------------------------------------------------------------------