scintilla4evr

Motion Graphics UDF

22 posts in this topic

#1 ·  Posted (edited)

Hello! I've been working on this UDF for some time, but when I read Seeking "kinetic typography" capability in au3 topic, I decided to share it. This UDF brings some functions for creating animations in GDI+ without worrying about rendering or calculating.

screen.png

Features:

  • Adding basic shapes (rectangle, ellipse) and text
  • Animating object properties (like position or size)
  • Animatable transformations (translate, rotate, scale)
  • Double-buffering
  • Rendering to a window or GUI control

Enjoy!

Motion Graphics UDF

Edited by scintilla4evr
3 people like this

Share this post


Link to post
Share on other sites



Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Very nice.

About the problem with Au3Check in your script.

Try to not use this kind of notation:

Local $hBrush = ($oOutline.brush)($iTime)

but instead use this:

Local $hBrush = $oOutline.brush($iTime)

 

try my "Example 1 - Basic Animation.au3"  modyfcation Motion Graphics UDF 0.0.2_mod.zip

You will see what I mean.

EDIT: Need some more learning ;)

 

Edited by mLipok

Signature beginning:   Wondering who uses AutoIT and what it can be used for ?
* GHAPI UDF - modest begining - comunication with GitHub REST API *
ADO.au3 UDF     POP3.au3 UDF     XML.au3 UDF    How to use IE.au3  UDF with  AutoIt v3.3.14.x  for other useful stuff click the following button

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST API *

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 - BETA * ADO.au3 UDF SMTP Mailer UDF *

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Best coding practices * 

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * 

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2017-06-04

Share this post


Link to post
Share on other sites

New version:

  • Added LayeredWindowRenderer
  • Fixed issues with brushes and text

screen4.jpg

Motion Graphics UDF

Share this post


Link to post
Share on other sites

Version 0.0.4:

  • Added time transformations
  • Added arcs
  • Added time events (call a function at a specific time)

Motion Graphics UDF

Share this post


Link to post
Share on other sites

Pretty neat demos and UDF; thanks for sharing  When I run most of them (at least on this PC) they start out very fast, then slow down-not gradually, instantly.  When I move the mouse the speed picks up again and when the mouse is at rest for a few moments, the speed drops again.  

Does this happen to you?

Share this post


Link to post
Share on other sites
15 hours ago, spudw2k said:

Pretty neat demos and UDF; thanks for sharing  When I run most of them (at least on this PC) they start out very fast, then slow down-not gradually, instantly.  When I move the mouse the speed picks up again and when the mouse is at rest for a few moments, the speed drops again.  

Does this happen to you?

Yes, I think it's something with AutoIt's GUI, because it happens in every script that renders something with GDI+ like this.

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

0.0.5:

  • Clipping the view with a rectangle
  • Added images

Motion Graphics UDF

PS. Image in the 14th example is taken from Intel's ad "Jim Parsons and a Special Guest Want You To Wake Up"

Edited by scintilla4evr

Share this post


Link to post
Share on other sites

Thanks, again, for this UDF.  You've added impressive capabilities in these updates.

But could you provide one more example?: show simple typing of a couple of text strings ... with some timing control parameter to adjust the rate of display.

I see how to control text sliding into view.  But I'm unsure of how to produce a typing effect.

 

 

 

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

0.0.7:

  • Added hatch brushes
  • Added GUIControlRenderer
  • Added keyframed animations

screen7.png

Motion Graphics UDF

Share this post


Link to post
Share on other sites
16 hours ago, qwert said:

with some timing control parameter to adjust the rate of display

I'm sorry to keep bringing this up.  With all your great additions, I still can't manage to control the pace of the text display.  The following, for example, has no affect other than delaying the display of the end result.

:
$oScene = _MoGraph_SceneCreate()

$oText = _MoGraph_TextCreate(_MoGraph_AnimatedStringCreate("Lorem ipsum dolor", 0, 50, $MOGRAPH_TXTANIM_LEFTTORIGHT), 10, 10, 380, 0, "Impact", 36, 0)
_MoGraph_SceneAddObject($oScene, $oText)
Sleep(1000)
$oText2 = _MoGraph_TextCreate(_MoGraph_AnimatedStringCreate("Lorem ipsum dolor", 0, 50, $MOGRAPH_TXTANIM_RIGHTTOLEFT), 10, 60, 380, 0, "Impact", 36, 0)
_MoGraph_SceneAddObject($oScene, $oText2)
Sleep(1000)
:
:

With so much capability, I hope there's a way to orchestrate use of the features with timing.  Am I just missing it?

 

 

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

4 hours ago, qwert said:

I'm sorry to keep bringing this up.  With all your great additions, I still can't manage to control the pace of the text display.  The following, for example, has no affect other than delaying the display of the end result.

:
$oScene = _MoGraph_SceneCreate()

$oText = _MoGraph_TextCreate(_MoGraph_AnimatedStringCreate("Lorem ipsum dolor", 0, 50, $MOGRAPH_TXTANIM_LEFTTORIGHT), 10, 10, 380, 0, "Impact", 36, 0)
_MoGraph_SceneAddObject($oScene, $oText)
Sleep(1000)
$oText2 = _MoGraph_TextCreate(_MoGraph_AnimatedStringCreate("Lorem ipsum dolor", 0, 50, $MOGRAPH_TXTANIM_RIGHTTOLEFT), 10, 60, 380, 0, "Impact", 36, 0)
_MoGraph_SceneAddObject($oScene, $oText2)
Sleep(1000)
:
:

With so much capability, I hope there's a way to orchestrate use of the features with timing.  Am I just missing it?

 

 

To delay the text animation, you have to change the 2nd and 3rd parameters in the _MoGraph_AnimatedStringCreate calls. Adding Sleep() doesn't affect the rendering, because timing is calculated when calling _MoGraph_RendererRenderFrame() or _MoGraph_RendererRenderNextFrame().

Here is the basic idea of how to add delay:

; mumbo jumbo code before

$iStart = 100
$iLength = 50

$oText = _MoGraph_TextCreate(_MoGraph_AnimatedStringCreate("Lorem ipsum dolor", $iStart, $iStart+$iLength, $MOGRAPH_TXTANIM_LEFTTORIGHT), 10, 10, 380, 0, "Impact", 36, 0)
_MoGraph_SceneAddObject($oScene, $oText)

; blah blah after

 

Edited by scintilla4evr

Share this post


Link to post
Share on other sites

Thanks for your response. 

I did a simple substitution to confirm what I think you're saying, but I got an unexpected result:

a "slot-machine" effect on the last two lines, followed by the first two lines flowing into view from the left.

:
$oText = _MoGraph_TextCreate(_MoGraph_AnimatedStringCreate("Lorem ipsum dolor", 100, 150, $MOGRAPH_TXTANIM_LEFTTORIGHT), 10, 10, 380, 0, "Impact", 36, 0)
_MoGraph_SceneAddObject($oScene, $oText)

$oText2 = _MoGraph_TextCreate(_MoGraph_AnimatedStringCreate("Lorem ipsum dolor", 100, 150, $MOGRAPH_TXTANIM_RIGHTTOLEFT), 10, 60, 380, 0, "Impact", 36, 0)
_MoGraph_SceneAddObject($oScene, $oText2)
:

Is there another parameter involved?

Share this post


Link to post
Share on other sites
7 hours ago, qwert said:

Thanks for your response. 

I did a simple substitution to confirm what I think you're saying, but I got an unexpected result:

a "slot-machine" effect on the last two lines, followed by the first two lines flowing into view from the left.

:
$oText = _MoGraph_TextCreate(_MoGraph_AnimatedStringCreate("Lorem ipsum dolor", 100, 150, $MOGRAPH_TXTANIM_LEFTTORIGHT), 10, 10, 380, 0, "Impact", 36, 0)
_MoGraph_SceneAddObject($oScene, $oText)

$oText2 = _MoGraph_TextCreate(_MoGraph_AnimatedStringCreate("Lorem ipsum dolor", 100, 150, $MOGRAPH_TXTANIM_RIGHTTOLEFT), 10, 60, 380, 0, "Impact", 36, 0)
_MoGraph_SceneAddObject($oScene, $oText2)
:

Is there another parameter involved?

No, because _MoGraph_AnimatedStringCreate does not affect the starting position of the text. It only changes the contents. If you want the 2nd string to flow into view from the right you can do one of two things:

  • add an EaseValue to control the position of the text
  • set $iHorzAlign argument (10th) of _MoGraph_TextCreate to 2, so the text will be aligned to right

Share this post


Link to post
Share on other sites

What you're describing seem to be tweaks to specific internal functions rather than a general capability to choreograph entire sequences ... sequences that can produce a dynamic text result like the example on this site: here

Can you describe how a general capability should be implemented?

 

 

Share this post


Link to post
Share on other sites

To choreograph sequences like this, you need to break down all animations to small parts that can be represented with "keyframes".

In the "I LOVE blah blah", you can find 4 animations (in order of appearance):

  1. Letter 'I' rolling from the bottom
  2. Word 'LOVE' rolling from the left
  3. Word 'KINETIC' rolling from the right
  4. Word 'TYPOGRAPHY' rolling from top

No, you have to translate these animations into code (I Love Kinetic Typography.au3):

; Move 'I' at the start from 340;230 to 340;140:
$oI_YValue = _MoGraph_EaseValueCreate(230, 140, 0, 50)
$oText_I = _MoGraph_TextCreate("I", 340, $oI_YValue, 0, 0, "Rockwell", 48, 1, _MoGraph_SolidBrushCreate(0, 0, 0, 220))
_MoGraph_SceneAddObject($oScene, $oText_I)

; Move 'LOVE' after 'I' from -160;100 to 20;100:
; 3rd argument is 50 to match the end of 'I' animation
; 4th argument is the end of animation (start+length)
$oLove_XValue = _MoGraph_EaseValueCreate(-160, 20, 50, 100)
$oText_Love = _MoGraph_TextCreate("LOVE", $oLove_XValue, 100, 0, 0, "Rockwell", 48, 1, _MoGraph_SolidBrushCreate(0, 0, 0, 160))
_MoGraph_SceneAddObject($oScene, $oText_Love)

; Move 'KINETIC' after 'LOVE' from 520;100 to 190;100
$oKinetic_XValue = _MoGraph_EaseValueCreate(520, 190, 100, 150)
$oText_Kinetic = _MoGraph_TextCreate("KINETIC", $oKinetic_XValue, 100, 0, 0, "Rockwell", 48, 1, _MoGraph_SolidBrushCreate(0, 0, 0, 220))
_MoGraph_SceneAddObject($oScene, $oText_Kinetic)

; Move 'TYPOGRAPHY' after 'KINETIC' from 110;-60 to 110;60
$oTypography_YValue = _MoGraph_EaseValueCreate(-60, 60, 150, 200)
$oText_Typography = _MoGraph_TextCreate("TYPOGRAPHY", 110, $oTypography_YValue, 0, 0, "Rockwell", 48, 1, _MoGraph_SolidBrushCreate(0, 0, 0, 220))
_MoGraph_SceneAddObject($oScene, $oText_Typography)

The most important types of all these sequences are objects created using _MoGraph_EaseValueCreate or _MoGraph_KeyframedValueCreate. Here is the basic syntax for both of these functions:

  • _MoGraph_EaseValueCreate($iValueStart, $iValueEnd, $iStart = 0, $iEnd = 100, $oEasing = _MoGraph_LinearEasingCreate())
    • $iValueStart - value the object will represent before the animation will start
    • $iValueEnd - value the object will represent after the animation ends
    • $iStart - time when the animation should start
    • $iEnd - time when the animation ends (start time + animation length)
    • $oEasing - object representing how the value will change

If the current time is between $iStart and $iEnd, the output value will also be between $iValueStart and $iValueEnd

  • _MoGraph_KeyframedValueCreate($aKeyframes)
    • $aKeyframes - 2D array of time-value pairs

_MoGraph_KeyframedValueCreate is basically a wrapper function for multiple _MoGraph_EaseValueCreate's

Share this post


Link to post
Share on other sites

Almost there.  I generally follow what you're saying, but the example script produced an empty screen, for me.  I confirmed that each of the 4 steps is executing, but the resulting GUI is blank.

Any idea what's missing?  (New example is on the same directory as MoGraphics.au3, and the other examples still display properly.)

Invisible.PNG

Share this post


Link to post
Share on other sites
1 hour ago, qwert said:

Almost there.  I generally follow what you're saying, but the example script produced an empty screen, for me.  I confirmed that each of the 4 steps is executing, but the resulting GUI is blank.

Any idea what's missing?  (New example is on the same directory as MoGraphics.au3, and the other examples still display properly.)

Invisible.PNG

I think you don't have Rockwell font installed. Change it to something else, like Times New Roman or Courier New.

Share this post


Link to post
Share on other sites

An excellent analysis!  I completely overlooked that.

Clarendon gives me the kind of result I was hoping for.  With only a couple adjustments, I was able to get what I've posted below.

Thanks for sticking with me on this.  And thanks for a great UDF!

 

Visible.PNG

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • c.haslam
      By c.haslam
      UEZ has kindly provided me with code that rotates an image per a line: see here
      Because I want to trim a photograph after rotation, I need to crop the photo. I wrote code which calls _GDIPlus_GraphicsSetClipRect() to do this, but it places spurious stuff in the corners: see 2.jpg attached.
      I want only the trimmed photo to show.
      The original jpeg is also attached.
      The arguments to _GDIPlus_GraphicsSetClipRect() come from solving 2 simultaneous equations: if a and b are the width and height of the original photo, find x and y, the width and height of the rotated and cropped rectangle;
      a = x cos(ang) + y sin(ang)
      b = x sin(ang) + y cos(ang)
      My solution is:
      x = (b * sin(ang) - a*cos(ang)) / (sin(ang)^2 - (cos(ang)^2)
      y = (b * cos(ang) - a * sin(ang)) / (cos(ang)^2 - sin(ang)^2)
      To try to get a handle on the problem, I have temporarily added in several lines in Case $btn. In 2.jpg, you can see that the rectangle bounding the area to be retained is in the wrong place.
      The code is:
      #include <ButtonConstants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> Opt('MustDeclareVars',1) Global Const $MK_SHIFT = 0x4 Global Const $MK_CONTROL = 0x8 Global Const $fPi = ACos(-1), $fPi2 = $fPi / 2, $fRad = 180 / $fPi GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL") GUIRegisterMsg($WM_PAINT,'WM_PAINT') Global $gX0=10,$gX1=580,$gY0,$gY1,$gForm1,$glblPic,$iLW,$iLH,$iW,$iH Global $ghCanvas,$ghImage,$ghPen,$gGraphicPic,$ghBitmap,$ghMatrix,$ghImageClone,$ghGfxClone Global Const $kDegToRads = 3.14159/180 main() Func main() $gForm1 = GUICreate("Form1", 623, 601, 192, 114) $iLW = 589 $iLH = 500 $glblPic = GUICtrlCreateLabel("", 8, 8, $iLW, $iLH) Local $btn = GUICtrlCreateButton("Rotate", 472, 560, 65, 25) GUISetState(@SW_SHOW) Local $oldY0,$oldY1,$fAngle _GDIPlus_Startup() $ghPen = _GDIPlus_PenCreate(0xFF999999,2) $ghImage = _GDIPlus_ImageLoadFromFile('H:\b\pergola.jpg') Local $h = GUICtrlGetHandle($glblPic) $gGraphicPic = _GDIPlus_GraphicsCreateFromHWND($h) $gY0 = 400 $gY1 = 400 $iW = _GDIPlus_ImageGetWidth($ghImage) $iH = _GDIPlus_ImageGetHeight($ghImage) $ghBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH) $ghCanvas = _GDIPlus_ImageGetGraphicsContext($ghBitmap) $ghMatrix = _GDIPlus_MatrixCreate() ; Loop until the user exits. While True If $gY0<>$oldY0 Or $gY1<>$oldY1 Then Paint() $oldY0 = $gY0 $oldY1 = $gY1 Else Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $btn $ghImageClone=_GDIPlus_BitmapCreateFromScan0($iW, $iH) $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImageClone) _GDIPlus_MatrixTranslate($ghMatrix, $iW/2, $iH/2) $gY1 = 300 ; temp Local $ang = -Angle($gY1-$gY0, $gX1-$gX0) _GDIPlus_MatrixRotate($ghMatrix, $ang) ;~ _GDIPlus_MatrixRotate($ghMatrix, -Angle($gY1-$gY0, $gX1-$gX0)) _GDIPlus_MatrixTranslate($ghMatrix, -$iW/2, -$iH/2) _GDIPlus_GraphicsSetTransform($ghGfxClone, $ghMatrix) _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImage,0,0,$iW,$iH) Local $angRads = $ang*$kDegToRads Local $sinAng = Sin($angRads) Local $cosAng = Cos($angRads) Local $wid = ($iLH*$sinAng-$iLW*$cosAng)/($sinAng^2-$cosAng^2) Local $left = ($iLW-$wid)/2 Local $ht = ($iLH*$cosAng-$iLW*$sinAng)/($cosAng^2-$sinAng^2) Local $top = ($iLH-$ht)/2 _GDIPlus_GraphicsDrawRect($ghGfxClone,$left,$top,$wid,$ht,$ghPen) ; temp _GDIPlus_GraphicsSetClipRect($ghGfxClone,$left,$top,$wid,$ht,0) _GDIPlus_GraphicsDispose($ghGfxClone) $ghGfxClone=_GDIPlus_ImageGetGraphicsContext($ghImage) _GDIPlus_GraphicsClear($ghImage) _GDIPlus_GraphicsDrawImageRect($ghGfxClone,$ghImageClone,0,0,$iW,$iH) _GDIPlus_GraphicsDispose($ghGfxClone) _GDIPlus_ImageDispose($ghImageClone) $gy0 = 400 $gy1 = 400 Paint() _GDIPlus_ImageSaveToFile($ghImage,'H:\b\2.jpg') ; added - is rotated, with same size as original file EndSwitch EndIf WEnd ; Clean up resources _GDIPlus_MatrixDispose($ghMatrix) _GDIPlus_ImageDispose($ghCanvas) _GDIPlus_ImageDispose($ghImage) _GDIPlus_ImageDispose($ghBitmap) _GDIPlus_PenDispose($ghPen) _GDIPlus_GraphicsDispose($gGraphicPic) _GDIPlus_Shutdown() EndFunc Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam Local Const $kYmax=$iLH-1,$kDelta=2 Local $vec = GUIGetCursorInfo($gForm1) If $vec[4] = $vec[4]=$glblPic Then Local $iDelta = BitShift($wParam, 16) ; positive = up Local $iKeys = _WinAPI_LoWord($wParam) If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then ; do nothing Else If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta EndIf Else If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta If $iDelta < 0 And $gY1<$kYmax Then $gY1 += $kDelta Else If $iDelta > 0 And $gY0>3 Then $gY0 -= $kDelta If $iDelta < 0 And $gY0<$kYmax Then $gY0 += $kDelta If $iDelta > 0 And $gY1>3 Then $gY1 -= $kDelta If $iDelta < 0 And $gY1<$kYmax Then $gY1 += $kDelta EndIf EndIf EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_MOUSEWHEEL Func Paint() _GDIPlus_GraphicsClear($ghCanvas,0) _GDIPlus_GraphicsDrawImageRect($ghCanvas, $ghImage, 0,0, $iLW, $iLH) _GDIPlus_GraphicsDrawLine($ghCanvas, $gX0, $gY0, $gX1, $gY1, $ghPen) _GDIPlus_GraphicsDrawImageRect($gGraphicPic, $ghBitmap, 0, 0, $iW, $iH) EndFunc Func WM_PAINT() _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_UPDATENOW) Paint() _WinAPI_RedrawWindow($gForm1, 0, 0, $RDW_VALIDATE) EndFunc Func Angle($y, $x) ;return value is in degree Local Const $fPi = ACos(-1), $fPi2 = ACos(-1) / 2, $fRad = 180 / $fPi Switch True Case ($x > 0) Return ATan($y / $x) * $fRad Case ($x < 0 And $y >= 0) Return ATan($y / $x + $fPi) * $fRad Case ($x < 0 And $y < 0) Return ATan($y / $x - $fPi) * $fRad Case ($x = 0 And $y > 0) Return $fPi2 * $fRad Case ($x = 0 And $y < 0) Return -$fPi2 * $fRad Case ($x = 0 And $y = 0) Return 0 EndSwitch EndFunc I also don't understand how the rotated picture gets displayed. There are graphics objects, graphics contexts and PDI+ bitmaps. How are they related?
      Help would be much appreciated.


    • UEZ
      By UEZ
      Here a small tool I wrote to update my Sysinternal tools collection without the need to download always the whole package or visiting the site to check for updates. I know that there are several tools available (also some tools written in AutoIt) but here another one for the collection. It was good exercise for me to code it.
       
       
        
       
       
      Some files from cannot be downloaded although they are visible on the web site!
       
      Here the download link of the source code only: AutoIt Sysinternal Tools Synchronizer v0.99.1 build 2017-10-23 beta.7z  (1353 downloads previously)
      -=> Requires AutoIt version 3.3.13.20 or higher / tested on Win8.1 real machine and some VMs: Win7 / Vista / Win10
       
      Compiled exe only: @MediaFire
       
      Just select the Sysinternal Tools folder or create one and press the synchronize button to download the selected items. Click on AutoIt label (near to left upper corner) to open menu.
       
      Special thanks to LarsJ, Melba23 and mesale0077 for their help. 
       
      I've still some ideas to implement which are more gimmick related, so it is not finished yet...
      If you want to add your language please check out #Region Language. Thanks. 
       
      Please report any bug or if you have any suggestions.
       
      The language of the tool tip from each of the executable in the left list view were automatically created using Google translator and weren't checked for correctness.
       
      Br,
      UEZ
    • c.haslam
      By c.haslam
      In my code, the mouse wheel causes the line to move up and down. It does move down to where the picture is, but is not seen there. This can be observed by scrolling down to the picture, and then up again: the line reappears as expected.
      How can I get the line to show on the picture? This seems to be a matter of transparency, but I have not found a way of getting the background of $graphLine to be transparent.
      The code is now:
      #include <ButtonConstants.au3> #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> Opt('MustDeclareVars',1) Global Const $MK_SHIFT = 0x4 Global Const $MK_CONTROL = 0x8 GUIRegisterMsg($WM_MOUSEWHEEL, "WM_MOUSEWHEEL") Global $gY0,$gY1,$gForm1,$glblLine,$glblPic main() Func main() $gForm1 = GUICreate("Form1", 623, 601, 192, 114) $glblLine = GUICtrlCreateLabel("", 8, 8, 604, 137) $glblPic = GUICtrlCreateLabel("", 8, 8, 589, 500) Local $btn = GUICtrlCreateButton("Rotate", 472, 560, 65, 25) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### Local $oldY0,$oldY1 _GDIPlus_Startup() Local $h = GUICtrlGetHandle($glblLine) ; limit graphics to area of $label Local $GraphicLine = _GDIPlus_GraphicsCreateFromHWND($h) Local $hPen = _GDIPlus_PenCreate(0xFF000000,2) Local $image = _GDIPlus_ImageLoadFromFile('H:\a\P5130021.jpg') Local $h = GUICtrlGetHandle($glblPic) Local $GraphicPic = _GDIPlus_GraphicsCreateFromHWND($h) _GDIPlus_GraphicsDrawImage($GraphicPic,$image,0,0) $gY0 = 67 $gY1 = 67 _GDIPlus_GraphicsClear($GraphicLine,0) _GDIPlus_GraphicsDrawLine($GraphicLine, 10, $gY0, 350, $gY1, $hPen) ; Loop until the user exits. While True If $gY0<>$oldY0 Or $gY1<>$oldY1 Then _GDIPlus_GraphicsClear($GraphicLine,0xFFD4D0C8) _GDIPlus_GraphicsDrawLine($GraphicLine, 10, $gY0, 590, $gY1, $hPen) $oldY0 = $gY0 $oldY1 = $gY1 Else Switch GUIGetMsg() Case $GUI_EVENT_CLOSE,$btn Exit EndSwitch EndIf WEnd ; Clean up resources _GDIPlus_PenDispose($hPen) _GDIPlus_GraphicsDispose($GraphicLine) _GDIPlus_Shutdown() EndFunc Func WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam, $lParam Local Const $ymax=500 Local $vec = GUIGetCursorInfo($gForm1) If $vec[4] = $glblLine Or $vec[4]=$glblPic Then Local $iDelta = BitShift($wParam, 16) ; positive = up Local $iKeys = _WinAPI_LoWord($wParam) If BitAND($iKeys,$MK_CONTROL)=$MK_CONTROL Then If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then ; do nothing Else If $iDelta > 0 And $gY0>3 Then $gY0 -= 1 If $iDelta < 0 And $gY0<$ymax Then $gY0 += 1 EndIf Else If BitAND($iKeys,$MK_SHIFT)=$MK_SHIFT Then If $iDelta > 0 And $gY1>3 Then $gY1 -= 1 If $iDelta < 0 And $gY1<$ymax Then $gY1 += 1 Else If $iDelta > 0 And $gY0>3 Then $gY0 -= 1 If $iDelta < 0 And $gY0<$ymax Then $gY0 += 1 If $iDelta > 0 And $gY1>3 Then $gY1 -= 1 If $iDelta < 0 And $gY1<$ymax Then $gY1 += 1 EndIf EndIf EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_MOUSEWHEEL Some other questions:
      Do I really need GDI+, or is there a simpler way? My code creates Graphics (canvases?) from labels. Is this legitimate? I have found MSDN to be un-helpful in learning GDI+. Is there a better learning tool?
    • spudw2k
      By spudw2k
      Here's a fun tool I put together.  It's a Plasma sandbox.  More features to come.

      This page was a useful resource for learning about this kind of Plasma implementation.
      Warning! Not Epileptic Friendly (probably)! Use at own Risk!
      I tried to curve the "default/initial" Plasma patterns so they aren't too erratic.  That doesn't mean you can't alter the Plasmas to be more erratic.  If you are sensitive to flashing colors and lights, use due caution.  
      #Region - Includes and Globals #include <ButtonConstants.au3> #include <GUIConstantsEx.au3> #include <ComboConstants.au3> #include <GuiComboBox.au3> #include <SliderConstants.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <GDIPlus.au3> #include <Misc.au3> ;#include <Array.au3> Opt("GUIOnEventMode", 1) Local $hDLL = DllOpen("user32.dll") Global Const $iWinMinWidth = @DesktopWidth * .25 Global Const $iWinMinHeight = @DesktopHeight * .25 Global $bIsPlaying = True, $bIsDrawing = False Global $hTimerFPS Global $iRows = 16, $iCols = 16 Global $iDisplayPlasma = 0, $iSelectPlasma = 0 Global $aPlasmaShapes[4] = ["($iX)", "($iY)", "($iX + $iY)", "Sqrt(($iX * $iX) + ($iY * $iY))"] ;~ Global $aPlasmas[4][7] = [[0, Random(6, 14, 1), 0, 0, 1, 0, 0], [1, Random(6, 14, 1), 0, 0, 0, 0, 0], [2, Random(8, 16,1 ), 0, 0, 1, 0, 0], [3, Random(8, 16, 1), 0, 0, Random(0,1,1), 0, 0]] ;Sine Wave | Spread | Position | Rotation | Spread Motion | Position Motion | Rotation Motion Global $aPlasmas[4][7] = [[0, Random(6, 14, 1), 0, 0, 0, 0, 0], [1, Random(6, 14, 1), 0, 0, 0, 0, 0], [2, Random(8, 16,1 ), 0, 0, 0, 0, 0], [3, Random(8, 16, 1), 0, 0, 0, 0, 0]] ;Sine Wave | Spread | Position | Rotation | Spread Motion | Position Motion | Rotation Motion Global $aPallete[256] Global $aPalleteSettings[3][3] = [[0, 128, 128], [-1.75, 128, 128], [1.75, 128, 128]] ;Position | Spread | Value Global $aPalleteDefaults = $aPalleteSettings Global $iPalleteShift = 0, $bPalleteShift = True, $iPalletShiftDirection = -5 #EndRegion - Includes and Globals #Region - Main GUI Global $aGUI[1] = ["id|hWnd"] Global Enum $hGUI = 1, $idMnuFile, $idMnuFileExit, $idMnuFilePlay, $idMnuOptions, $idMnuOptionsPallete, $idMnuOptionsPalleteShift, $idMnuOptionsEditor, $idMnuOptionsZoom, $idMnuOptionsZoomIn, $idMnuOptionsZoomOut, $iGUILast ReDim $aGUI[$iGUILast] Global Const $sVersion = "0.1" Global Const $sTitle = "Plasma_kIt - Version " & $sVersion $aGUI[$hGUI] = GUICreate($sTitle, $iWinMinWidth, $iWinMinHeight, -1, -1, BitOR($WS_SIZEBOX, $WS_MAXIMIZEBOX, $WS_MINIMIZEBOX)) GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit") $aGUI[$idMnuFile] = GUICtrlCreateMenu("&File") $aGUI[$idMnuFilePlay] = GUICtrlCreateMenuItem("&Pause", $aGUI[$idMnuFile]) GUICtrlSetOnEvent(-1, "_PlayToggle") $aGUI[$idMnuFileExit] = GUICtrlCreateMenuItem("E&xit", $aGUI[$idMnuFile]) GUICtrlSetOnEvent(-1, "_Exit") $aGUI[$idMnuOptions] = GUICtrlCreateMenu("&Options") $aGUI[$idMnuOptionsPallete] = GUICtrlCreateMenuItem("Pallete Mixer", $aGUI[$idMnuOptions]) GUICtrlSetOnEvent(-1, "_GUIPallete_Show") $aGUI[$idMnuOptionsPalleteShift] = GUICtrlCreateMenuItem("Pallete Shift", $aGUI[$idMnuOptions]) GUICtrlSetState(-1, $GUI_CHECKED) GUICtrlSetOnEvent(-1, "_GUIPallete_ShiftToggle") $aGUI[$idMnuOptionsEditor] = GUICtrlCreateMenuItem("Plasma Editor", $aGUI[$idMnuOptions]) GUICtrlSetOnEvent(-1, "_GUIPlasmaEditor_Show") $aGUI[$idMnuOptionsZoom] = GUICtrlCreateMenu("Zoom", $aGUI[$idMnuOptions]) $aGUI[$idMnuOptionsZoomIn] = GUICtrlCreateMenuItem("Zoom In" & @TAB & "+", $aGUI[$idMnuOptionsZoom]) GUICtrlSetOnEvent(-1, "_Zoom") $aGUI[$idMnuOptionsZoomOut] = GUICtrlCreateMenuItem("Zoom Out" & @TAB & "-", $aGUI[$idMnuOptionsZoom]) GUICtrlSetOnEvent(-1, "_Zoom") _GDIPlus_Startup() ;Start GDI+ UDF Global Const $hDC = _WinAPI_GetDC($aGUI[$hGUI]) Global Const $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC, @DesktopWidth, @DesktopHeight) Global Const $hDC_backbuffer = _WinAPI_CreateCompatibleDC($hDC) Global Const $DC_obj = _WinAPI_SelectObject($hDC_backbuffer, $hHBitmap) $hBackbuffer = _GDIPlus_GraphicsCreateFromHDC($hDC_backbuffer) ;_GDIPlus_GraphicsSetSmoothingMode($hBackbuffer, $GDIP_SMOOTHINGMODE_HIGHQUALITY) ;Sets the graphics object rendering quality (antialiasing) $hBrush = _GDIPlus_BrushCreateSolid(0x00000000) ;Brush for Coloring/Painting LED Pixels Local $aAccelKeys[5][2] = [["{+}", $aGUI[$idMnuOptionsZoomIn]], ["{NUMPADADD}", $aGUI[$idMnuOptionsZoomIn]], ["{-}", $aGUI[$idMnuOptionsZoomOut]], ["{NUMPADSUB}", $aGUI[$idMnuOptionsZoomOut]], ["{pause}", $aGUI[$idMnuFilePlay]]] GUISetAccelerators($aAccelKeys) #EndRegion - Main GUI #Region - Pallete Mixer GUI Global $aGUIPallete[1] = ["id|hWnd"] Global Enum $hGUIPallete = 1, $idSliderRPosition, $idSliderRValue, $idSliderRSpread, $idSliderGPosition, $idSliderGValue, _ $idSliderGSpread, $idSliderBPosition, $idSliderBValue, $idSliderBSpread, $idBtnResetPallete, $iGUIPalleteLast ReDim $aGUIPallete[$iGUIPalleteLast] $aGUIPallete[$hGUIPallete] = GUICreate("Pallete Mixer", 338, 260, -1, -1) GUISetOnEvent($GUI_EVENT_CLOSE, "_GUIPallete_Hide") $aGUIPallete[$idSliderRPosition] = GUICtrlCreateSlider(8, 132, 97, 33, $TBS_ENABLESELRANGE) GUICtrlSetLimit(-1, 20, -20) ;~ GUICtrlSetOnEvent(-1, "_GUIPallete_SettingsChange") $aGUIPallete[$idSliderRValue] = GUICtrlCreateSlider(48, 56, 33, 73, BitOR($TBS_VERT, $TBS_ENABLESELRANGE)) GUICtrlSetLimit(-1, 128, 0) ;~ GUICtrlSetOnEvent(-1, "_GUIPallete_SettingsChange") $aGUIPallete[$idSliderRSpread] = GUICtrlCreateSlider(8, 168, 97, 33, $TBS_ENABLESELRANGE) GUICtrlSetLimit(-1, 24, 2) ;~ GUICtrlSetOnEvent(-1, "_GUIPallete_SettingsChange") $aGUIPallete[$idSliderGPosition] = GUICtrlCreateSlider(120, 132, 97, 33, $TBS_ENABLESELRANGE) GUICtrlSetLimit(-1, 20, -20) ;~ GUICtrlSetOnEvent(-1, "_GUIPallete_SettingsChange") $aGUIPallete[$idSliderGValue] = GUICtrlCreateSlider(160, 56, 33, 73, BitOR($TBS_VERT, $TBS_ENABLESELRANGE)) GUICtrlSetLimit(-1, 128, 0) ;~ GUICtrlSetOnEvent(-1, "_GUIPallete_SettingsChange") $aGUIPallete[$idSliderGSpread] = GUICtrlCreateSlider(120, 168, 97, 33, $TBS_ENABLESELRANGE) GUICtrlSetLimit(-1, 24, 2) ;~ GUICtrlSetOnEvent(-1, "_GUIPallete_SettingsChange") $aGUIPallete[$idSliderBPosition] = GUICtrlCreateSlider(232, 132, 97, 33, $TBS_ENABLESELRANGE) GUICtrlSetLimit(-1, 20, -20) ;~ GUICtrlSetOnEvent(-1, "_GUIPallete_SettingsChange") GUICtrlSetData(-1, 9) $aGUIPallete[$idSliderBValue] = GUICtrlCreateSlider(272, 56, 33, 73, BitOR($TBS_VERT, $TBS_ENABLESELRANGE)) GUICtrlSetLimit(-1, 128, 0) ;~ GUICtrlSetOnEvent(-1, "_GUIPallete_SettingsChange") $aGUIPallete[$idSliderBSpread] = GUICtrlCreateSlider(232, 168, 97, 33, $TBS_ENABLESELRANGE) GUICtrlSetLimit(-1, 24, 2) GUICtrlSetData(-1, 11) ;~ GUICtrlSetOnEvent(-1, "_GUIPallete_SettingsChange") GUICtrlCreateLabel("RED", 46, 200, 30, 20) GUICtrlCreateLabel("GREEN", 150, 200, 38, 20) GUICtrlCreateLabel("BLUE", 268, 200, 30, 20) $aGUIPallete[$idBtnResetPallete] = GUICtrlCreateButton("Reset", 136, 236, 67, 17) GUICtrlSetOnEvent(-1, "_GUIPallete_Reset") GUISetAccelerators($aAccelKeys) Global Const $hDCPallete = _WinAPI_GetDC($aGUIPallete[$hGUIPallete]) Global Const $hHBitmapPallete = _WinAPI_CreateCompatibleBitmap($hDCPallete, 320, 40) Global Const $hDC_backbufferPallete = _WinAPI_CreateCompatibleDC($hDCPallete) Global Const $DC_objPallete = _WinAPI_SelectObject($hDC_backbufferPallete, $hHBitmapPallete) Global Const $hBackbufferPallete = _GDIPlus_GraphicsCreateFromHDC($hDC_backbufferPallete) Global $hBrushPallete = _GDIPlus_BrushCreateSolid(0xFF000000) ;~ _GDIPlus_GraphicsSetSmoothingMode($hBackbuffer, $GDIP_SMOOTHINGMODE_HIGHQUALITY) ;Sets the graphics object rendering quality (antialiasing) _GUIPallete_Update() _GUIPallete_Reset() #EndRegion - Pallete Mixer GUI #Region - Plasma Editor GUI Global $aGUIPlasmaEditor[1] = ["id|hWnd"] Global Enum $hGUIPlasmaEditor = 1, $idCmbPlasmaSelector, $idCmbPlasmaDisplay, $idBtnPlasmaAdd, $idBtnPlasmaDel, $idCmbPlasmaShape, $idSliderPlasmaSpread, $idCmbPlasmaSpread, $idSliderPlasmaRotation, $idCmbPlasmaRotation, $idSliderPlasmaPosition, $idCmbPlasmaPosition, $iGUIPlasmaEditorLast ReDim $aGUIPlasmaEditor[$iGUIPlasmaEditorLast] $aGUIPlasmaEditor[$hGUIPlasmaEditor] = GUICreate("Plasma Editor", 419, 323, -1, -1) GUISetOnEvent($GUI_EVENT_CLOSE, "_GUIPlasmaEditor_Hide") GUICtrlCreateLabel("Display", 16, 8, 95, 17) GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif") $aGUIPlasmaEditor[$idCmbPlasmaDisplay] = GUICtrlCreateCombo("", 16, 24, 121, 25, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "All Combined|Selected Plasma", "All Combined") GUICtrlSetOnEvent(-1, "_GUIPlasmaEditor_PlasmaDisplay") GUICtrlCreateLabel("Selected Plasma", 24, 96, 120, 17) GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif") $aGUIPlasmaEditor[$idBtnPlasmaAdd] = GUICtrlCreateButton("Add Plasma", 160, 16, 113, 33) GUICtrlSetOnEvent(-1, "_GUIPlasmaEditor_PlasmaAddRem") GUICtrlSetState(-1, $GUI_DISABLE) $aGUIPlasmaEditor[$idBtnPlasmaDel] = GUICtrlCreateButton("Remove Plasma", 296, 16, 113, 33) GUICtrlSetOnEvent(-1, "_GUIPlasmaEditor_PlasmaAddRem") GUICtrlSetState(-1, $GUI_DISABLE) GUICtrlCreateGroup("Plasma Controls", 8, 64, 401, 249) GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif") $aGUIPlasmaEditor[$idCmbPlasmaSelector] = GUICtrlCreateCombo("", 24, 112, 121, 25, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "Plasma #1|Plasma #2|Plasma #3|Plasma #4", "Plasma #1") GUICtrlSetOnEvent(-1, "_GUIPlasmaEditor_PlasmaSelect") GUICtrlCreateLabel("Shape", 174, 96, 35, 17) $aGUIPlasmaEditor[$idCmbPlasmaShape] = GUICtrlCreateCombo("", 174, 112, 113, 25, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "Horizontal|Vertical|Diagonal|Circular", "Horizontal") GUICtrlSetOnEvent(-1, "_GUIPlasmaEditor_PlasmaSetShape") GUICtrlCreateLabel("Spread", 24, 145, 38, 17) $aGUIPlasmaEditor[$idSliderPlasmaSpread] = GUICtrlCreateSlider(16, 160, 257, 25, $TBS_FIXEDLENGTH) GUICtrlSetLimit(-1, 255, 5) $aGUIPlasmaEditor[$idCmbPlasmaSpread] = GUICtrlCreateCombo("", 280, 160, 113, 25, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "Static|Oscillate", "Static") GUICtrlSetOnEvent(-1, "_GUIPlasmaEditor_PlasmaSetSpread") GUICtrlCreateLabel("Rotation", 24, 201, 44, 17) GUICtrlSetState(-1, $GUI_DISABLE) $aGUIPlasmaEditor[$idSliderPlasmaRotation] = GUICtrlCreateSlider(16, 216, 257, 25, $TBS_FIXEDLENGTH) GUICtrlSetState(-1, $GUI_DISABLE) $aGUIPlasmaEditor[$idCmbPlasmaRotation] = GUICtrlCreateCombo("", 280, 216, 113, 25, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "Static|Oscillate", "Static") GUICtrlSetOnEvent(-1, "_GUIPlasmaEditor_PlasmaSetRotation") GUICtrlSetState(-1, $GUI_DISABLE) GUICtrlCreateLabel("Position", 24, 257, 41, 17) GUICtrlSetState(-1, $GUI_DISABLE) $aGUIPlasmaEditor[$idSliderPlasmaPosition] = GUICtrlCreateSlider(16, 272, 257, 25, $TBS_FIXEDLENGTH) GUICtrlSetLimit(-1, 127, -127) GUICtrlSetState(-1, $GUI_DISABLE) $aGUIPlasmaEditor[$idCmbPlasmaPosition] = GUICtrlCreateCombo("", 280, 272, 113, 25, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL)) GUICtrlSetData(-1, "Static|Oscillate", "Static") GUICtrlSetOnEvent(-1, "_GUIPlasmaEditor_PlasmaSetPosition") GUICtrlSetState(-1, $GUI_DISABLE) GUICtrlCreateGroup("", -99, -99, 1, 1) _GUIPlasmaEditor_PlasmaSettingsLoad($iSelectPlasma) ;_GUIPlasmaEditor_PlasmaControlsLock() GUISetAccelerators($aAccelKeys) #EndRegion - Plasma Editor GUI #Region - Initialization and Main Loop GUIRegisterMsg($WM_GETMINMAXINFO, "_WM_GETMINMAXINFO") GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY") GUISetState(@SW_SHOW, $aGUI[$hGUI]) While 1 If $bIsPlaying And Not $bIsDrawing Then _DrawScreen(_RenderPlasma()) Sleep(10) WEnd #EndRegion - Initialization and Main Loop #Region - Main GUI Functions Func _DrawScreen($aPixels) ;If Function called while Drawing Return 0 If $bIsDrawing Then Return 0 ;Set Drawing Status Indictaor $bIsDrawing = True ;Create Timer for Drawing Performance/Duration Local $hTimer = TimerInit() ;Erase Bitmap Graphic _GDIPlus_GraphicsClear($hBackbuffer, 0xFFFFFFFF) ;Capture Client Window Size $aWinClientSize = WinGetClientSize($aGUI[$hGUI]) ;Setup Variables Local $iPixelIndex = 0 Local $iCol = $iCols Local $iRow = $iRows Local $iWidth = $aWinClientSize[0] / $iCol Local $iHeight = $aWinClientSize[1] / $iRow ;Draw Pixel Grid (Top-Left to Bottom Right) For $iY = 0 To $iRow - 1 For $iX = 0 To $iCol - 1 Local $dARGB = $aPixels[$iPixelIndex] ;Set Brush Color _GDIPlus_BrushSetSolidColor($hBrush, $dARGB) ;Draw "Pixel" _GDIPlus_GraphicsFillRect($hBackbuffer, $iX * $iWidth, $iY * $iHeight, $iWidth, $iHeight, $hBrush) ;Increment Pixel Counter $iPixelIndex += 1 If $iPixelIndex = UBound($aPixels) Then $iPixelIndex = 0 Next Next ;Draw Bitmap to Screen _WinAPI_BitBlt($hDC, 0, 0, $aWinClientSize[0], $aWinClientSize[1], $hDC_backbuffer, 0, 0, $SRCCOPY) ;blit drawn bitmap to GUI ;FPS Counter $hTimer = TimerDiff($hTimer) ;~ ConsoleWrite("Whole Process time: " & Round($hTimer / 1000, 3) & @CRLF) If $bIsPlaying Then If TimerDiff($hTimerFPS) >= 998 Then Local $iFPS = Round(1000 / $hTimer, 2) WinSetTitle($aGUI[$hGUI], "", $sTitle & " (" & $iFPS & " FPS) " & $iCols & " x " & $iRows) $hTimerFPS = TimerInit() EndIf Else ;Show FPS in Window Title WinSetTitle($aGUI[$hGUI], "", $sTitle) EndIf $bIsDrawing = False EndFunc ;==>_DrawScreen Func _Exit() ; Clean up resources _GUIPallete_Exit() GUIDelete($aGUIPallete[$hGUIPallete]) GUIDelete($aGUIPlasmaEditor[$hGUIPlasmaEditor]) GUIDelete($aGUI[$hGUI]) _GDIPlus_BrushDispose($hBrush) _GDIPlus_GraphicsDispose($hBackbuffer) _WinAPI_SelectObject($hDC, $DC_obj) _WinAPI_DeleteObject($hHBitmap) _WinAPI_ReleaseDC($hGUI, $hDC) _GDIPlus_Shutdown() DllClose($hDLL) Exit EndFunc ;==>_Exit Func _PlayToggle() ;Toggle Play State If Not $bIsPlaying Then ;Start Playing $bIsPlaying = True $hTimerFPS = TimerInit() GUICtrlSetData($aGUI[$idMnuFilePlay], "&Pause") Else ;Stop Playing $bIsPlaying = False GUICtrlSetData($aGUI[$idMnuFilePlay], "&Play") EndIf EndFunc ;==>_PlayToggle Func _RenderPlasma() ;Setup Variables Local $aWorkPallete = $aPallete Local $iRow = $iRows Local $iCol = $iCols Local $iGridSize = $iRow * $iCol Local $aPixels[$iGridSize] Local $iIndex = 0 Local $iPlasma = 0 Local $iPlasmas Local $iDisplayPlasmaNumber = $iDisplayPlasma Local $iSine, $iSpread, $iPosition ;Loop Through Pixel Grid and Calculate Plasma(s) For $iY = 0 To $iRow - 1 For $iX = 0 To $iCol - 1 $iPlasmas = 0 If Not $iDisplayPlasmaNumber Then For $iZ = 0 To UBound($aPlasmas) - 1 $iSine = $aPlasmas[$iZ][0] ;Spread Motions If $aPlasmas[$iZ][4] Then $aPlasmas[$iZ][4] += ($aPlasmas[$iZ][1] * 0.00001125) $iSpread = -7*Sin($aPlasmas[$iZ][4])+9 Else $iSpread = $aPlasmas[$iZ][1] EndIf $iPosition = $aPlasmas[$iZ][2] $iPlasma = Execute("128.0 + (128.0 * Sin(" & $aPlasmaShapes[$iSine] & " / " & $iSpread & "))") $iPlasmas += $iPlasma Next Else $iSine = $aPlasmas[$iDisplayPlasmaNumber - 1][0] ;Spread Motions If $aPlasmas[$iDisplayPlasmaNumber - 1][4] Then $aPlasmas[$iDisplayPlasmaNumber - 1][4] += ($aPlasmas[$iDisplayPlasmaNumber - 1][1] * 0.005) $iSpread = Sin($aPlasmas[$iDisplayPlasmaNumber - 1][4])/2 Else $iSpread = $aPlasmas[$iDisplayPlasmaNumber - 1][1] EndIf $iPosition = $aPlasmas[$iDisplayPlasmaNumber - 1][2] ;$iPlasmas = Execute("128.0 + (128.0 * Sin(" & $aPlasmaShapes[$aPlasmas[$iDisplayPlasmaNumber - 1][0]] & " / " & $aPlasmas[$iDisplayPlasmaNumber - 1][1] & ") - " & $aPlasmas[$iDisplayPlasmaNumber - 1][2] & ")") $iPlasmas = Execute("128.0 + (128.0 * Sin(" & $aPlasmaShapes[$iSine] & " / " & $iSpread & "))") EndIf $iPlasma = Int($iPlasmas) ;Account for Pallete Shift $iPlasma += $iPalleteShift ;Wrap Pixel Pallete Color If $iPlasma >= 256 Then Do $iPlasma -= 256 Until $iPlasma < 256 EndIf If $iPlasma <= -1 Then Do $iPlasma += 256 Until $iPlasma > -1 EndIf ;Set Pixel Color value from Pallete $aPixels[$iIndex] = $aWorkPallete[$iPlasma] ;Increment Pixel Index Counter $iIndex += 1 If $iIndex = $iGridSize Then $iIndex = 0 Next Next ;Pallete Shift Logic If $bPalleteShift Then $iPalleteShift += $iPalletShiftDirection If $iPalleteShift >= 256 Then $iPalleteShift = 0 If $iPalleteShift <= -1 Then $iPalleteShift = 255 EndIf Return $aPixels EndFunc ;==>_RenderPlasma Func _WM_GETMINMAXINFO($hwnd, $Msg, $wParam, $lParam) ;Only Control Size of Main GUI If $hwnd <> $aGUI[$hGUI] Then Return Default $tagMaxinfo = DllStructCreate("int;int;int;int;int;int;int;int;int;int", $lParam) DllStructSetData($tagMaxinfo, 7, $iWinMinWidth) ; min X DllStructSetData($tagMaxinfo, 8, $iWinMinHeight) ; min Y Return 0 EndFunc ;==>_WM_GETMINMAXINFO Func _WM_NOTIFY($hwnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR $tNMHDR = DllStructCreate($tagNMHDR, $lParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") ;Local $tInfo If Not _IsPressed("01", $hDLL) Then Return Default Switch $iIDFrom Case $aGUIPallete[$idSliderRPosition] Switch $iCode Case $NM_CUSTOMDRAW _GUIPallete_ColorSet(0, -1, GUICtrlRead($iIDFrom)) EndSwitch Return 0 Case $aGUIPallete[$idSliderRValue] Switch $iCode Case $NM_CUSTOMDRAW _GUIPallete_ColorSet(0, GUICtrlRead($iIDFrom)) EndSwitch Return 0 Case $aGUIPallete[$idSliderRSpread] Switch $iCode Case $NM_CUSTOMDRAW _GUIPallete_ColorSet(0, -1, "", GUICtrlRead($iIDFrom)) EndSwitch Return 0 Case $aGUIPallete[$idSliderGPosition] Switch $iCode Case $NM_CUSTOMDRAW _GUIPallete_ColorSet(1, -1, GUICtrlRead($iIDFrom)) EndSwitch Return 0 Case $aGUIPallete[$idSliderGValue] Switch $iCode Case $NM_CUSTOMDRAW _GUIPallete_ColorSet(1, GUICtrlRead($iIDFrom)) EndSwitch Return 0 Case $aGUIPallete[$idSliderGSpread] Switch $iCode Case $NM_CUSTOMDRAW _GUIPallete_ColorSet(1, -1, "", GUICtrlRead($iIDFrom)) EndSwitch Return 0 Case $aGUIPallete[$idSliderBPosition] Switch $iCode Case $NM_CUSTOMDRAW _GUIPallete_ColorSet(2, -1, GUICtrlRead($iIDFrom)) EndSwitch Return 0 Case $aGUIPallete[$idSliderBValue] Switch $iCode Case $NM_CUSTOMDRAW _GUIPallete_ColorSet(2, GUICtrlRead($iIDFrom)) EndSwitch Return 0 Case $aGUIPallete[$idSliderBSpread] Switch $iCode Case $NM_CUSTOMDRAW _GUIPallete_ColorSet(2, -1, "", GUICtrlRead($iIDFrom)) EndSwitch Return 0 Case $aGUIPlasmaEditor[$idSliderPlasmaSpread] Switch $iCode Case $NM_CUSTOMDRAW $aPlasmas[$iSelectPlasma][1] = 0.2 * GUICtrlRead($iIDFrom) EndSwitch Return 0 Case $aGUIPlasmaEditor[$idSliderPlasmaRotation] Switch $iCode Case $NM_CUSTOMDRAW EndSwitch Return 0 Case $aGUIPlasmaEditor[$idSliderPlasmaPosition] Switch $iCode Case $NM_CUSTOMDRAW $aPlasmas[$iSelectPlasma - 1][2] = GUICtrlRead($iIDFrom) EndSwitch Return 0 EndSwitch Return 0 EndFunc ;==>_WM_NOTIFY Func _Zoom() Local $bPlaying = $bIsPlaying If $bPlaying Then $bIsPlaying = False Local $iCtrlID = @GUI_CtrlId Switch $iCtrlID Case $aGUI[$idMnuOptionsZoomOut] $iCols += 2 $iRows += 2 If $iCols >= 4 * 8 Then $iCols = 4 * 8 If $iRows >= 4 * 8 Then $iRows = 4 * 8 Case $aGUI[$idMnuOptionsZoomIn] $iCols -= 2 $iRows -= 2 If $iCols <= 4 Then $iCols = 4 If $iRows <= 4 Then $iRows = 4 EndSwitch If $bPlaying Then $bIsPlaying = $bPlaying EndFunc ;==>_Zoom #EndRegion - Main GUI Functions #Region - Pallete Mixer GUI Functions Func _GUIPallete_ColorSet($iColor, $iValue = -1, $iPosition = "", $iSpread = "") If $iValue >= 0 Then $aPalleteSettings[$iColor][2] = (128.0 - $iValue) If $iPosition Then $aPalleteSettings[$iColor][0] = (0.25 * $iPosition) If $iSpread Then $aPalleteSettings[$iColor][1] = ($iSpread ^ 2) Return _GUIPallete_Update() EndFunc ;==>_GUIPallete_ColorSet Func _GUIPallete_Draw() ;Draw Color Pallete in Palette Mixer GUI _GDIPlus_GraphicsClear($hBackbufferPallete, 0xFF000000) Local $iX = 0 For $iColor = 1 To 256 Local $dARGB = $aPallete[$iColor - 1] ;Set Brush Color _GDIPlus_BrushSetSolidColor($hBrushPallete, $dARGB) ;Draw Color Bar to Bitmap _GDIPlus_GraphicsFillRect($hBackbufferPallete, $iX, 0, 320 / 256, 40, $hBrushPallete) $iX += (320 / 256) Next ;Write Bitmap to Screen Return _WinAPI_BitBlt($hDCPallete, 8, 8, 320, 40, $hDC_backbufferPallete, 0, 0, $SRCCOPY) ;blit drawn bitmap to GUI EndFunc ;==>_GUIPallete_Draw Func _GUIPallete_Exit() ; Clean up resources GUIDelete() _GDIPlus_BrushDispose($hBrushPallete) _GDIPlus_GraphicsDispose($hBackbufferPallete) _WinAPI_SelectObject($hDCPallete, $DC_objPallete) _WinAPI_DeleteObject($hHBitmapPallete) _WinAPI_ReleaseDC($aGUIPallete[$hGUIPallete], $hDCPallete) Return 1 EndFunc ;==>_GUIPallete_Exit Func _GUIPallete_Hide() Return GUISetState(@SW_HIDE, $aGUIPallete[$hGUIPallete]) EndFunc ;==>_GUIPallete_Hide Func _GUIPallete_Reset() $aPalleteSettings = $aPalleteDefaults GUICtrlSetData($aGUIPallete[$idSliderRPosition], $aPalleteSettings[0][0] / 0.25) GUICtrlSetData($aGUIPallete[$idSliderRValue], 128 - $aPalleteSettings[0][2]) GUICtrlSetData($aGUIPallete[$idSliderRSpread], Sqrt($aPalleteSettings[0][1])) GUICtrlSetData($aGUIPallete[$idSliderGPosition], $aPalleteSettings[1][0] / 0.25) GUICtrlSetData($aGUIPallete[$idSliderGValue], 128 - $aPalleteSettings[1][2]) GUICtrlSetData($aGUIPallete[$idSliderGSpread], Sqrt($aPalleteSettings[1][1])) GUICtrlSetData($aGUIPallete[$idSliderBPosition], $aPalleteSettings[2][0] / 0.25) GUICtrlSetData($aGUIPallete[$idSliderBValue], 128 - $aPalleteSettings[2][2]) GUICtrlSetData($aGUIPallete[$idSliderBSpread], Sqrt($aPalleteSettings[2][1])) Return _GUIPallete_Update() EndFunc ;==>_GUIPallete_Reset Func _GUIPallete_ShiftToggle() ;Toggle Pallete Shift Local $iCtrlState = GUICtrlRead(@GUI_CtrlId) If BitAND($iCtrlState, $GUI_CHECKED) Then ;Disable PalleteShift $bPalleteShift = False GUICtrlSetState(@GUI_CtrlId, $GUI_UNCHECKED) Else ;Enable PalleteShift $bPalleteShift = True GUICtrlSetState(@GUI_CtrlId, $GUI_CHECKED) EndIf EndFunc ;==>_GUIPallete_ShiftToggle Func _GUIPallete_Show() GUISetState(@SW_SHOW, $aGUIPallete[$hGUIPallete]) _GUIPallete_Draw() EndFunc ;==>_GUIPallete_Show Func _GUIPallete_Update() ;Re-Calculate Work Color Pallete For $iStep = 0 To 255 Local $iR = Int($aPalleteSettings[0][2] + ($aPalleteSettings[0][2] * Sin((3.1415 * $iStep / $aPalleteSettings[0][1]) - $aPalleteSettings[0][0]))) Local $iG = Int($aPalleteSettings[1][2] + ($aPalleteSettings[1][2] * Sin((3.1415 * $iStep / $aPalleteSettings[1][1]) - $aPalleteSettings[1][0]))) Local $iB = Int($aPalleteSettings[2][2] + ($aPalleteSettings[2][2] * Sin((3.1415 * $iStep / $aPalleteSettings[2][1]) - $aPalleteSettings[2][0]))) $aPallete[$iStep] = "0xFF" & Hex($iR, 2) & Hex($iG, 2) & Hex($iB, 2) Next Return _GUIPallete_Draw() EndFunc ;==>_GUIPallete_Update #EndRegion - Pallete Mixer GUI Functions #Region - Plasma Editor GUI Functions Func _GUIPlasmaEditor_Hide() GUISetState(@SW_HIDE, $aGUIPlasmaEditor[$hGUIPlasmaEditor]) EndFunc ;==>_GUIPlasmaEditor_Hide Func _GUIPlasmaEditor_PlasmaAddRem() EndFunc ;==>_GUIPlasmaEditor_PlasmaAddRem Func _GUIPlasmaEditor_PlasmaDisplay() Local $sSelection = GUICtrlRead($aGUIPlasmaEditor[$idCmbPlasmaDisplay]) If $sSelection = "All Combined" Then $iDisplayPlasma = 0 Else $iDisplayPlasma = _GUICtrlComboBox_GetCurSel($aGUIPlasmaEditor[$idCmbPlasmaSelector])+1 EndIf Return $iDisplayPlasma EndFunc ;==>_GUIPlasmaEditor_PlasmaDisplay Func _GUIPlasmaEditor_PlasmaSelect() Local $sSelection = GUICtrlRead($aGUIPlasmaEditor[$idCmbPlasmaSelector]) $iSelectPlasma = _GUICtrlComboBox_GetCurSel($aGUIPlasmaEditor[$idCmbPlasmaSelector]) _GUIPlasmaEditor_PlasmaDisplay() Return _GUIPlasmaEditor_PlasmaSettingsLoad($iSelectPlasma) EndFunc ;==>_GUIPlasmaEditor_PlasmaSelect Func _GUIPlasmaEditor_PlasmaSetPosition() EndFunc ;==>_GUIPlasmaEditor_PlasmaSetPosition Func _GUIPlasmaEditor_PlasmaSetRotation() EndFunc ;==>_GUIPlasmaEditor_PlasmaSetRotation Func _GUIPlasmaEditor_PlasmaSetShape() $aPlasmas[$iSelectPlasma][0] = _GUICtrlComboBox_GetCurSel($aGUIPlasmaEditor[$idCmbPlasmaShape]) EndFunc ;==>_GUIPlasmaEditor_PlasmaSetShape Func _GUIPlasmaEditor_PlasmaSetSpread() $aPlasmas[$iSelectPlasma][4] = _GUICtrlComboBox_GetCurSel($aGUIPlasmaEditor[$idCmbPlasmaSpread]) EndFunc ;==>_GUIPlasmaEditor_PlasmaSetSpread Func _GUIPlasmaEditor_PlasmaSettingsLoad(ByRef $iPlasma) GUICtrlSetData($aGUIPlasmaEditor[$idSliderPlasmaSpread],$aPlasmas[$iPlasma][1]/0.2) _GUICtrlComboBox_SetCurSel($aGUIPlasmaEditor[$idCmbPlasmaShape],$aPlasmas[$iPlasma][0]) If $aPlasmas[$iPlasma][4] Then _GUICtrlComboBox_SetCurSel($aGUIPlasmaEditor[$idCmbPlasmaSpread],1) Else _GUICtrlComboBox_SetCurSel($aGUIPlasmaEditor[$idCmbPlasmaSpread],0) EndIf Return 1 EndFunc ;==>_GUIPlasmaEditor_PlasmaSettingsLoad Func _GUIPlasmaEditor_Show() GUISetState(@SW_SHOW, $aGUIPlasmaEditor[$hGUIPlasmaEditor]) EndFunc ;==>_GUIPlasmaEditor_Show #EndRegion - Plasma Editor GUI Functions edit: Minor tweaks
    • timmalos
      By timmalos
      Hey all.
      I'm trying to know when my user clicks on a Rect drawn via GDI+. Everything is almost working except I have a strange behaviour in the "order" clicks are fired.
      I created a simplified code to help :
      #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StaticConstants.au3> #include <WinAPI.au3> #include <Array.au3> Opt("GUIOnEventMode", 1) ;0=disabled, 1=OnEvent mode enabled _GDIPlus_Startup() Global $hGUI, $hGraphics Global $iWidth = 1024, $iHeight = 762 createGUI() draw() While 1 Sleep(10) WEnd Func createGUI() $hGUI = GUICreate("Current CasparCG Output", $iWidth,$iHeight) GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") GUISetBkColor(0x000000) GUISetState(@SW_SHOW) $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI) _GDIPlus_GraphicsSetSmoothingMode($hGraphics, $GDIP_SMOOTHINGMODE_HIGHQUALITY) ;sets the graphics object rendering quality (antialiasing) EndFunc ;==>Example Func draw() ;_WinAPI_draw($hGUI,"","",BitOR($RDW_ERASE,$RDW_INVALIDATE,$RDW_UPDATENOW)) _GDIPlus_GraphicsClear($hGraphics) $hFamily = _GDIPlus_FontFamilyCreate("Arial") $hFont = _GDIPlus_FontCreate($hFamily, 15, 1) $hPen = _GDIPlus_PenCreate(0xFFFEDCFF, 2) ;color format AARRGGBB (hex) $hFormat = _GDIPlus_StringFormatCreate() _GDIPlus_StringFormatSetAlign($hFormat, 1) _GDIPlus_StringFormatSetLineAlign($hFormat, 1) $hBrushString = _GDIPlus_BrushCreateSolid(0xFFFFFFFF) Local $hBrush = _GDIPlus_BrushCreateSolid(0xFFFF00FF) ;color format AARRGGBB (hex) For $i = 1 to 2 Local $x = 0.25 Local $y = 0.25 Local $w = 0.5 Local $h = 0.5 Local $title = "Layer "&$i If $x >= -1 And $x <= 1 Then $x *= $iWidth If $y >= -1 And $y <= 1 Then $y *= $iHeight If $w >= -1 And $w <= 1 Then $w *= $iWidth If $h >= -1 And $h <= 1 Then $h *= $iHeight $hItem = GUICtrlCreateLabel("", $x,$y,$w,$h) GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetOnEvent($hItem,"_gui_layer_clicked") ConsoleWrite("Created label with handle="&$hItem&" $i= " & $i&@CRLF) _GDIPlus_GraphicsFillRect($hGraphics, $x, $y, $w, $h,$hBrush) _GDIPlus_GraphicsDrawRect($hGraphics, $x, $y, $w, $h,$hPen) $tLayout = _GDIPlus_RectFCreate($x, $y, $w, $h) $aInfo = _GDIPlus_GraphicsMeasureString($hGraphics, $title, $hFont, $tLayout, $hFormat) _GDIPlus_GraphicsDrawStringEx($hGraphics, $title, $hFont, $aInfo[0], $hFormat, $hBrushString) Next _GDIPlus_BrushDispose($hBrush) _GDIPlus_PenDispose($hPen) _GDIPlus_FontDispose($hFont) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_BrushDispose($hBrushString) Return 1 EndFunc Func _gui_layer_clicked() ConsoleWrite("Clicked on " & @GUI_CtrlId&@CRLF) EndFunc Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE ; Clean up resources _GDIPlus_GraphicsDispose($hGraphics) _GDIPlus_Shutdown() Exit EndSelect EndFunc ;==>SpecialEvents What happens there :
      We have two rectangles, with the one labelled "2" is front and, the one labelled "1" in background. However when we click, the fired label is the one created first (in the background) and not the second one (in the front).
      Is it normal ?
      If yes, is there any way to change this order ? If I create another label after a first one on the same coords, I would the second one to be fired instead of the first one (This is a simplified code I can't just invert the label order creation easily)
       
      Thanks for your help