Storing images in the script itself and than displaying them in an animated button (picture control)

Put simple Tips and Tricks that are not entire Tutorials in this forum
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Storing images in the script itself and than displaying them in an animated button (picture control)

12 Sep 2018, 18:18

Hello there :angel:

If you are a beginner AutoHotkey programmer and have set yourself to learn how to program GUIs, you may have noticed what may seem like "limitations" of the standard GUI controls and their options. For the picture control, in example, a shallow look takes us to conclude that it relies on an image file path for the picture, which means that any user can change the images in the GUIs of your program at any time by simply altering the image in that path. Another example: the button control seems to lack some form of texture or color adding routine, which is upsetting to those who would like to develop some GUI aesthethics.

Both of these situations are not flaws. The standards of the GUI Controls are exactly what they are: standards. What this means is that it is still possible to do the things you want to do, it just means you will have to go beyond the standard options (and this basically means coding a little bit more). To illustrate this paradigm, it suffices to say that over the years, users have already provided added functionalities that allow not only for images in buttons and pictures without files, but also many other implementations.

:arrow: For this reason, this tip/trick topic is yet another demonstration on how to overcome standard GUI options, and in this example we will basically: stop a user from disrupting (deleting, altering) the picture controls associated image (by restoring the original images the programmer choose right before the scripts uses them with in-script data) and also, how to simulate an animated button with images (by using a picture control that responds to mouse hover and mouse clicks, altering its image accordingly).

:arrow: Working around a standard option may have some implications which the developer has to fully understand in order to judge wether the method presented is really a valid solution to his problem. That is one of the reasons for why these methods have not become standard options themselves. Nevertheless, if the method works for your design, and the implications are not affecting your idea, you are free to use and benefit from these non-standard ways.

First the sample code for testing (explanations below it):

Code: Select all

Message_Monitor() ; This function will set the OnMessage commands to monitor mouse hover and mouse click (setting action if they happen inside the images area)


; The label definition below is for organization purposes only. The code in it sets the hex strings correponding to the image file binaries in variables, and than rewrites the files with these in-script binaries. The hex strings have been obtained by opening the image files using HexEdit (File->Export->Hex Text) and than proceding a simple substitution in a text editor to remove the whitespaces.
RESTORE_IMAGE_FILES_FROM_IN_SCRIPT_BINARY:

; The hex string below corresponds to the image file of an ordinary button.
FILE_DATA_ORDINARY_BUTTON_IMAGE := "89504E470D0A1A0A0000000D49484452000000570000005008060000006CCDE9D40000000467414D410000B18F0BFC6105000000097048597300000EC200000EC20115284A800000001974455874536F667477617265007061696E742E6E657420342E302E3137336E9F630000051249444154785EEDD64D4EDC4010866196AC58B1418AC42677C96972981C85AB708F2C922CA248480E0553EEF2D76FFB67DC9EF1D88EF44472E1EEAEFAC663B86B9AE6B0102C1EEAC0E2A10E2C1EEAC0E2A10E2CAEC1FB3FFBAF97AE591B2C5E920656839E712D585C92067109DAC3A56071093AF035684F4BC3624D3AE05A689F4BC0E25C3AC8543FBF7C1D8DD64FA1BDD784C539B4F93128B439E88C3E3A432D583C8736DC8702590A9D5FA233CD85C5A9B4C9121AFE52A81FA2B3CD81C529B43942C35E0BF5A774C67361710C6D88D0706B41FD2A9D792A2C0ED126140DB356D47FA4B34F81C53E7AB8A201D68EE6883483B1B0D8470F8EA8F15B41F3449AC318582CD1031D357BAB683EA3598C8145A28745D4E42DA3198D6632048B4A0F89A8B95B47733ACDA60F16951EE0A8B1ADA0799DE65382C5483776D4D0D6D0DC46332AC1A2D34D1D35B25534BFD1AC08169D6EE8A8892DA30C342B8245A39B393A7CEB2807A399292C1ADDC8D0C17B417968668A8BB289A343F782F2309A5DC445D9C0D0816BF4E7E57D84DF9FFE7DB7DA73F3F7F5AE79FBF19CDD3B15E5A2D9455C940D0C1DB63ADF1FDA60D567D0F3502E9A5D941764B1A3C3D6E6D78FFBA6797D6C7ED9750CFAE509EF9F8A72319AA1CB0BB2D0D0417B45F968862E2FC8424387441F4F4CF80A260FCD1FB8FFC3B7C7E60DD674DF8D4FCD3FB8A7EBBEF9FB2DEC7B7AC7FACF07DFB5A3FA48281FCDD0E5055968E89028FE12C9E9F043F7BFF3AFF6A870E503D4B0DABD72E3FB48281FCDD0752F6491891B97B44DC666C23BAFF314F4BC0BE337809E9CF69C9E77A8DFF3F6F2700A39FF703FCCE883728A39BAEE852C30BA31C170C353971A0C5FD9C213959EA6FC95321CAE9F6981A6B3F280E6F54139C51C5DF7421698B8690986DB3E19E1C9095F597A224C7A6A7A5E27A570FDCC531FED5E1AE0CC3E28A798A3EB5EC80213372D499FB292C6C250C5BF3BE94339190AD77FDE06D69E57B70FCA29E6E8BA17B2C0C44D4BCAE17ECA875D22DCF84AF05AE1D57093E1CAD72F857E7A6F85A1AABF16DA300A626F33FBA09C628EAE7B210B4CDCB4A4146E1AC21B0C7F5AE9BD1FFA7FD1F4859B3EC8B2F494CEEB83728A39BAEE852C3071D39252B869E0F41B373D11F9531303A2AF6B39DC1456BE2E0419D6CDE983728A39BAEE852C30BA3189CD906EF3E1A928C1776A39DC1454FE679349FDC59F9FDF07E5147374DD0B59606873159F82AEFC7DD5BFA67CBF29855BAAB7C2FB589FC473FAA09C628E2E2FC8224307EC15E5A319BABC200B0D1DB257948F66E8F2822C3474C85E513E9AA1CB0BB2D0D1417B43B918CDD07151161B3A6C6F2817CD2EE2A26C60E8B0BDA15C34BB888BB281A303F782F2309A5D8445A39B183A742F280FCD4C61D1E8468E0EDE3ACAC168660A8B4E3773D4C09651069A15C1A2D30D1D35B05534BFD1AC081623DDD451235B43731BCDA8048B916E1C51435B41F33ACDA8048B4A378FA8B12DA0598D66D3078B440F71D4D8ADA3398D6632048B257A98A3066F15CDE7348F21582CD1C314357B4B6826A7598C81C53E7AA8A2A6D78EE6883483B1B038440F5734C05A51FF91CE3E0516C7D026080DB316D4AFD299A7C2E214DA10A1E1AE85FA233AE739B03895365642C35E0AF54374B639B0780E6DB20F0DBF143ABF44679A0B8B7368C3432890B9E89C3E3A432D589C4B9B9F8A022BA1F55368EF3561B1161D644DB4D72560B1361DEC9AB4B7256171493AEC25680F9782C54BD2206AD033AE058BD7A661F5D1B56B82C5431D583CD481C5431D583CD481C5430DCDDD7FF2957802F31AA04F0000000049454E44AE426082" 


; File writing is done through DllCall().  
VarSetCapacity(FILE_BINARY_ORDINARY_BUTTON_IMAGE, StrLen(FILE_DATA_ORDINARY_BUTTON_IMAGE) / 2, 0) ; Prepares a recipient variable for DllCall()
Loop % StrLen(FILE_DATA_ORDINARY_BUTTON_IMAGE) / 2 ; Loop to insert the binaries of the file byte-by-byte into the recipient variable.
{
	NumPut("0x" . SubStr(FILE_DATA_ORDINARY_BUTTON_IMAGE, A_Index * 2 - 1, 2), FILE_BINARY_ORDINARY_BUTTON_IMAGE, A_Index -1, "UChar") ; Inserts each byte.
}

HandleToFile := DllCall("CreateFile", Str,A_ScriptDir . "/OrdinaryButtonImage.png", Uint, 0xC0000000, Uint, 3, Ptr, 0, Uint, 2, Uint, 0, Ptr, 0, Ptr) ; Creates a file (overwriting previous files with the same path)
Result := DllCall("WriteFile", "Uint", HandleToFile, "Uint", &FILE_BINARY_ORDINARY_BUTTON_IMAGE, "Uint", StrLen(FILE_DATA_ORDINARY_BUTTON_IMAGE) / 2, "Uint", "NULL", "Int", "NULL") ; Writes to the file (overwriitng is set on).
DllCall("CloseHandle", "Uint", HandleToFile) ;  Deletes the file handle (saves memory space and frees the file).


FILE_DATA_MOUSE_HOVERED_BUTTON_IMAGE := "89504E470D0A1A0A0000000D49484452000000570000005008060000006CCDE9D40000000467414D410000B18F0BFC6105000000097048597300000EC100000EC101B8916BED0000001974455874536F667477617265007061696E742E6E657420342E302E3137336E9F630000082249444154785EEDDBCB6B5D551406F0685FA1D1D847ECD3A6E9431DF9404114073AB282E0488482203A12A482A8883A10144110850A4E8A223855848038A81351D181A250ACF84F24695E4DD3A6D99EB59375CF3ADFF9F6B9E7B1CFBDB778859F7057CEDE7BED2FE7EEDC36A723CEB9A196D0E2501CB43814072D0EC5418B4371D0E22048FE93FF15C2318386167B09038B01D7E8175A6C1306D10BD843AFD0621B70C3FD803DB58D1663C20D0E0AECB30DB4D8146EA4AA993B4E96C6C65781BDC7448B4D60F365B0D09A606B14C13DC4428B7560C34558206D61EB87E09E9AA2C5AAB0C910B6F95E61FD30B8B72668B10A6C8E619BED17D61FC23DD6458B6560430CDBDCA060FD22DC7355B4D80D3681D8660615EBDFC2BD57418B45707184CDCF3D32E92EBFBD3B57EF97CBEFEE72F34F1ECED4D83E2CCCA02C5A2C820B5BB66131FFF421B7FED74DCEFD3BE2965FDF9BFB7AAF2DBFB9C7F7223DF522605A0CC105956DD25AF968DC6F462D3EB79F5ED70B4BAF4C647AB972F6567A1DDB9FC02CCAA0450617B35893DEE409B7FAD5CECE86D62F8EE4EE985E587A391BECEAB931DF1BBB56B03D0ACCA41B5A44B888C59ACB3879DC5D9BDED1D9D8F53F6EF6E730BDB6050BA70FF86F6A27D82F7716062BD83E1566538416112EA05863CCEC3D536EEDC7AD69C03F6FF135766D4C18ECD5AF47FD379B5D8BD87E15E613428B164EAC584345E46E95BB56377AEDBBEDA5375A87FF615A3358C5F62D30A3105A5438A9628D9421E76DE62D9A9CC7DDDEA275F875363FA588B5F3DBDCECDDC7E8B5DDB0FD0BCC8AA14585132AD64459F256D54D8B954FC6E97575D1601B1E412C03CC8AA145819329B67855CBAFEECD04BCFCD61E7A5D55FEE8F9754B1A6C72CEC738DB590E023343B4287022C116AE6BE5C3DB7C00EBFF243FE07EBFD92D3C73905E57D6DC8347DDDA0FDBFC7C32AF841CF35309CB033343BC089328B6686DF219F8F3311FECD56F46DDE57776D73E1767A64EB8E5D7F6FA7964BEEBBFC40D56B03C046667F1224C20D8828D253FBD573E1EF7C15E7AFC889BB9ABE6A7873B8FFBF132CFDA9FC91666120BC90FCC33F2F5A36EE54272449C3D9A1F5711CB05B3B3781126106CB12892402F3D96049B043473A4E62707192701BF3FE6DC6CB2852458B41174332C17CCCECA1760B0628B45231FC7EA06AB92F1F39F267F12BC30E1E6E5F599F134DCE966E7B962B908CC50E50B3050B085FEAF583E98A1CA1760A0608B58F36747336FC1D4B85B24D77BA726DC1A19933D1B0FBA55724DD6A85B3965E6DD3C63F5EB5DCFDA527DA4583E98A1CA1760A0608B588BD3C950D2E006DC7CB7EB13FAD62E152E7C0331ACCE5C79E5FB48B17C3043957D0183849D38A4D3A46DC69C7999BBA0E02CB4EF0076E774D6293843F59AB5E9F1CD90F3DF5CAF411F2C279BA3CABE800102276668B8E6AE4B1B346FD9C01D95DE4DF923A57BB8BAA6049AAE950FA8591F2C279BA3CABE8001C24E1A42C3EDDC19E6CE316F59764788F4AE29384E42E1EA9A9B7D74E6C2001BF6C172B239AAEC0B1820ECA421E9771941636653C1CF9DEC9BB2A95BB8FAF54E609DF5E2F6C172B239AAEC0B1820ECA421E17037E437DB46B8F648D05AE068B821C385B75F1AFAE6B9653615FD58E88411607B6BD807CBC9E6A8B22F6080B0938684C24D37A10D9A8F5678AD57FC83A628DCF41B1996DEA5CDFA6039D91C55F6050C1076D29050B8E986D39FB8E91D91BF6B6C40ECED1A0E370D2B3FCE0469C635E983E5647354D9173040E0C48C6D86C9366FEE8A107AA686C34D83CA7F6C12697FF6EBF5FB6039D91C55F6050C106C7264EF82ACFC79151C335F7CBD08851BAA7798F318EF44DE7B711F2C279BA3CA176090600BC4347BEF949B7B20B9BB8FD5FC9B311957776C452C1FCC50E50B3050B04562997B68D25DF9EC16B7F4D2ED6EEEE1C924A40A7F612E7F4D79E2B81FB7F8C23E377B7FFBCF42B07C3043952FC040C11689417E15B3F6D356FF9088FC9A7DE9CC840F8B5D4BC9DFE13E71D82DBFB1C78F976713DA7ED884E58319AA7C01062AB65013F20B45FD4DEDFADF23EEDAF7DB7D8D5D5B64F6BE291FEAF5DFB66CCCF3ED8ED61E3661B908CC50F1220C166CB1BAFCE34DE7B7757E052ECF195C7AF408BDB68CF9A70EB9F50BE9B30AAB5F143F685717CB05B3B3781126106CB13A58B0319E7C5C7C7E7F674E21BFBA67D735C172C1EC2C5E8409145BB092E4ED6A9F788C15ACD2879B55CC07AE591E02B3B36851E024822D5A5A12AC9C8D9D602F8EB885670FF06B1B90C7A36CC0B11EB8667960668816054EA4D8C25D251FAF72C19E8E1FAC270F9B447EE09AE5203033448B0A2753AC8120D9ECB9B1CE66859C8FF4DA58E0F869FAC035CB00B3626851E1848A35409160E5DF26D06B23F33F38233C70CDF62F302B86162D9C54B146109E7FBD0A56F9A71E1B3C70CDF62D30A3105AB470628B35A4563ED8788A515D7E6F17BDAE6DFE79DD1A0F5CB3FD2ACC288416114E6EB1C6E41FD2D9602568765DAFD479E09AED556036456891C145146BCC3EDD1DFBC9F1BAF4816BB98B175FDC47AF516C9F0233E98616437031C51A9480FD3FA46BE18FA175F97F9A9AFC51997D4DB1FD29CCA31B5A0CC1C5106BF646C2F6A4308B3268B1082E8A58D3838EEDC3C20CCAA2C56E7071C43630A858FF16EEBD0A5A2C039B60D8660605EB17E19EABA2C52AB021866DAE5F587F0CEEB30E5AAC0A1B0B619BED15D60F837B6B8216EBC0268BB0CDB785AD1F827B6A8A169BC086BB618134C5D629827B8885169BC2E6AB628185B0F15560EF31D1622CB8914182BDB6811663C38DF513F6D6265A6C136EB617B0875EA1C55EC22062C035FA8516FB0DC32A826307092D0EC5418B4371D0E2501CB43814072D0EC5E046FE03CC0CF56CF1DCBD380000000049454E44AE426082"


VarSetCapacity(FILE_BINARY_HOVERED_BUTTON_IMAGE, StrLen(FILE_DATA_MOUSE_HOVERED_BUTTON_IMAGE) / 2, 0)
Loop % StrLen(FILE_DATA_MOUSE_HOVERED_BUTTON_IMAGE) / 2
{
	NumPut("0x" . SubStr(FILE_DATA_MOUSE_HOVERED_BUTTON_IMAGE, A_Index * 2 - 1, 2), FILE_BINARY_HOVERED_BUTTON_IMAGE, A_Index -1, "UChar")
}

HandleToFile := DllCall("CreateFile", Str,A_ScriptDir . "/HoveredButtonImage.png", Uint, 0xC0000000, Uint, 3, Ptr, 0, Uint, 2, Uint, 0, Ptr, 0, Ptr) 
Result := DllCall("WriteFile", "Uint", HandleToFile, "Uint", &FILE_BINARY_HOVERED_BUTTON_IMAGE, "Uint", StrLen(FILE_DATA_MOUSE_HOVERED_BUTTON_IMAGE) / 2, "Uint", "NULL", "Int", "NULL")
DllCall("CloseHandle", "Uint", HandleToFile) 


FILE_DATA_PRESSED_BUTTON_IMAGE := "89504E470D0A1A0A0000000D49484452000000570000005008060000006CCDE9D40000000467414D410000B18F0BFC6105000000097048597300000EC100000EC101B8916BED0000001974455874536F667477617265007061696E742E6E657420342E302E3137336E9F63000014FF49444154785EED9D097456C515C747129240484848202B0471DFF75D1454D0AA48F5504BF7D6D3A3566B7BBAEFB6B655BBB877B3ADAD756D553697AAB5D65A5BB55A4545AB62B182A2028A065104ADDEDEDFBC7793F93EE6255F42421260CEB9E790EFCDDCB9F7FFDDF9DF3BF3DEF7707DD936DB6C332F83060D72454545AEB8B8D80D1E3CD8959494B8D2D252575656E6860C19E2860E1DEACACBCB7384CFB8461FFA3286B1E840173A4DFF46D54240010470006AD8B061AEB2B2D2555555B9112346B8DADA5A3772E448376AD4282F7575755EEC6FAED187BE8C612C3AD0854E7487406FB0CDA2C80025E2884000011C80AAAFAF778D8D8D6EF4E8D1AEA5A5C58D1D3BD68D1B37CE6DB1C5165EB6DC724B2FF637D7E8435FC630161DE84227BA9983B90C68B3638368386251CAD265391BA0441F808C1933C66DBEF9E61EB86DB6D9C66DBFFDF66EC71D77743BEFBCB3DB65975DDCAEBBEEEA76DB6D37B7FBEEBB7BE1DF7CC635FAD097318C4507BAD0896EE630A0991B1B067C345B8418A844104B9765DCD0D0E09D27F20064871D76F02001DC5E7BEDE5F6D9671FB7FFFEFBBB030F3CD08D1F3FDE1D7CF0C15E264C98E0C5FEE61A7DE8CB18C6A2035DE8443773301773323736608B816C760E9816824AB4E0104BB5A9A9C92FE3ADB6DACA471A91B7E79E7BBA7DF7DDD7830470871E7AA89B3C79326AA43339FAE8A3DD91471EE98E38E2083F86B1E840173AD1CD1CCCC59CCC8D0DD8824D6124F77B803190E546C626A9B01489161C62A912492C61A28B4823F2B445815B170170C09E3871A29F83B99893B9B1015BB009DBB0115BB1B9DF524518AD646C788EA548B2D97AEBADDD4E3BEDE4F6D8630FBA4601E94D99346992A791FDF6DBCFDB802DD8846DD888ADD8DC2FA3D880252B13092C3BB237C905EE236AB4451D5F9F4234431B808C4DD8868DD88ACDD88E0FFD06608C301AA8AEAEF6A510DCB6EDB6DB7ABED31675B4AFE5A0830EF274818DD88ACDD88E0F46137D0A301C45FD48F6656951FA909DB5451D2A54BE33B452BE3B74B87C5FE5CCF2E172767995971FA4627F732D36BE2B72C0010778AA208AB11D1FF0059FF00D1FD77B0B81ADA9A971CDCDCD7E89698B3AD1919C3E240113B000EFC7C3AAE4DC61D572BECA851523E422959FE4099F718D3EF4650C63BB033851BCF7DE7B7B2EC6077CC1A73E013804968C0B67698B1A1E932F950D936F0CA9F0110A183F545000E8021580FB79458D5C5C5923BF52F97565AD5CA2F29BE1B9C2675CA30F7D19C35874A00B9D5D059AF20D9A20D9E113BEAD57808D63BB03EC1715D4AFA7A09EA58E136D441EA0FCC2839900F7BBE123E572952BAB46CA5555A3E46A95DFE7099F718D3EF4650C63D1812E74A29B39982B664F4C4876ECFEF201EE750E366029BE8D0AB4458D0CE573A5E5F2D5B20ABFFC89A61F695411613F53007EA94000CA65299800774DF528B9AEBA4E66AACC52993DA25EE6E4099F718D3EF4650C63D1812E74A29B39988B390B8D64767C06B051043EF71AC028A544B1AA405BD4B0504E2D1D2A5F4829004E8513CF53477F9A82FA5B0580A8230AAF4D8102B41B546E1AD1207FAC69909B556E51B9D54B632AC9675CA30F7D19C35874A00B9DE8660EE6624EE6C6066C89D99B2F50043B3B361C5645F44A9906E7708CC7B6515BD418934F960C91D31458B8F55B1AAD64FD1FAB632421F891A8C271228DA89B95020A5080F62705F0CFB58DF217953B6A9BE4AF2A77E6099F718D3EF4650C63D1812E74A29B39988B39991B1BB0059BB02D667F289C537002C76603DFC1A047F9976F0A52AFA8A8E0CFA8112609B0E5F26505161A80EF4830440E7C0837C29544179176A30A110838B7A760FE6D6493DCA5F28F91CD72B7CA3DC8A866B93715FECD675CA30F7D19C35874A00B9DE8660EE6624EE6C6066CC1266CC3C6981FA1B06D66CBCC59321880458F44AFD1019C03B96B8B1A8084C07E5B9316B52849854C4E76BF5CF9F00FEA244B97E80280DB1408A28F68FC7B0A1800DE376AB4DCAFF22F950790BAD1F260DD182FFC9BCFB8461FFA3286B1E840173AD1CD1CCCC59CCC8D0DD8824DD8868DD81AF32794EDB6DBCE9FAE810158F4083D144207D38B4BE5849232F9B452413EB0646E788F4463D10A47125D1E548D3800211A0109C00070AECA432A0FAB3CA232AFAE2547F88C6BF4A12F63188B0E7479905537733017735A14630B36615B0830B6C7FC43384326C1C1BF3D420F7C3364480E35B44527453E3EB84C4E516029B55866F9C0B224E1BFEBD3688523E14C0FAA0A80108980046080F7687D8B3CA6F26F95C75379A27EAC17FB9B6BF4A12F63188B0E747990553773301773323736600B36E5038CEDF810F3116193C12E0E7A009375AA1EF86638C8D0169D0CF988027BB2D2C1E7D5A86F6A5540B9435666D919B033D419962609074E841F59C2FF5400883600211201C9C07C52419CDF90C853A9FC2715FBDBAED3D7C04607BAD0896EE6602EE6646E6CC0166C3280B1159BB11D1F627E9A400FD4BF6C91C1A65BD1CB37D25912FBC0E052CFB39F559EFD9A1AF53DCDC0E7A891D49664678B589CA17C6289927C8828B892A54CB419A844A58109880B1A3697A755FE6BD2984AFA37D7E8638033161D0632BA9983B99893B9B1015BB0C922185BB119DBF1015F62FE9A503D70C8D3EDE4D659D4BEAFB8C4D301B52C5CC5AE8B429D9D11DBD22B94D78C0A88160396C413462BCBDA400D017D46414416AA2C6A1C1715AE59BF10680319DD611433B7018C4D4611D88ACDD88E0FF8D211FF726783E4D6ADE835AED51655FEDEE2C1F2218DDA933C1D94EB524A78969D10053B3B24764CECA462C09284E6A9E344184B9AA80318A23104F45995E702599C4AF8197D42A0D1812E74A29B39988B3963006323B66233B6E303BEE013BEC5FC47C2E8ED12F7F24D900DB545151FAF51FB098D5A360A6C6B594AD48D70D7A5BAC428DC29E229E84924F01D19DC8065C9C29116AD16A90B53B0DA806C1A27CFA7F242D31639629FD3C700672C3A2C922D8A998B390D606CC1266CC3466CC5666CC7077CC1277CC3C71806C6BDECDC0AAE1CF806A8E1B445954E0DA296AD2D19962D253B1F9616650EC982029E3A939A938402EF59C4B6039B449A45AA811A82F9622712826D205B24A39B390C608B606CC1266CC3466CC5666CC7077CC1277CC3C7180E089503B7EE39D829A8EEA50324AD6D2D65471415CBB48CA8A5A4610714D2013B2676509445F01EE592016B34000816AD06AA01B72495A51962D743A0D1D11EC5ED34D106B0DA802DD8846DD818D2033EE04B21D14BDDCBE13AB7870A4A6C697847954D291AEC2B8413356A3FA77CC4DEDCA2F612FDC6C9BCEC846E4AE9C078961D1589C573AC8FD8B139C086D16AA086202ECB90B08F811C4671083073323736600B3619FF622B36633B3EE08B452F3EE26B0C0FA44B892D8B122669D41EAB51FBD174C340363D43BF59CA1778CAA2960C4CA943E11ED2815505C6B1F9C0E647AA07B03991979AB78C8A5D37A019FBCA4C27AB5F72F2E63227AF7E0A8047CBD27B9CBC7C76B39FDBAA88901EB0159BB1DDA2179FF00D1FF1159F63B81835D89638B311D65955C27B346A29BFD8E67E46EB5A0EBD29BAC9AEDC0DA09C81B7D8665AD452C05367867460C92B06AC456116A02FA712BBC698A5A756CA5BAF3859B35C017E3901F88D254E56BEE0E4A513932417D203B661635BF4AAEDF8802FF8846FF888AFF81CC3056AE0C4ACD3AA21BD105572744009ECC6207B6EA570C2C42E876CCBDEDDB8363F6A298B3C1D28B096BC8C0AF2A3D50033303B13EBFFCAF965F2F643B5B21C9DA754F8085EA500BF7E4D9D9F93B93D3D44A2D7B8171FF0059FF00D1FF1159F63B8201CA873DEC0730F99E066F1ED21838A7D6DFB6105F75325C939AD5102E44F8DC88108BB1EB22F650E7C16462D75670E1D041CBB2EC09AD8B890268C8399CBF8171BB0258C5E6CC5666CC7077CC1277C336AC0677C8FE1C3C325DCADE890773BE2DBE394123EA67CCBC9D757759970D8CC8107CBE7EA138AE4B6394EEEBAD5C9BFEE7432EF5E274F3EE8E4BF8F96CBFCACA83DAC4656E9D27D4B97F0DBBA94FFF7AA93775AF5EF0B5A02D01A64F50A27F25A5CDED56BEFAE289355878700B7C8EB0F273AD1BDEADC317E85588916462FB5EFDCF155F2B8DA8ACDD88E0FF832EB04CE9F93431D7CC5677C8FE103EFF2504926EF12CE59E0528219DF728EC06D1B763156255CFB0D27B7DFE0E4EE3F3B79F02E278FDDE7E4A9879C2C7CCCC9F3F34BE4D90949E96551BBECDA24E9C08D21B08807EC915A6955A0962BB86B22A0E64AA5BCD6F66528B8936BE52DD5834E74AF79B0C6477218BD569A3D75696223B66233B6E303BEDC708D933FFC6888A7067CC5677C8FE1C3ED784ECA32EBDD2CBE1D3FA8488E54BE7D7F717248C3CD46CA93906F677CD3C91D3739B9F78A0AF9BB72173BA0073E3254163DEEE485FF38597266734A091A412757F844B39AA89D599F93C05A2F284BA351C1B9B045C105E07659797D0AE8F50D6B5D33705FD3A8E34B5A33BB5256FBE82D931593DAEB5F6CF0D4F0C961DE366C5C7071ADB7994D05F7E86E3CB558FE789D936B2F73F29BE9C9AD7F5F92A9EF6010C3A9C3A49605EE410A6E98CCD8B170B0CC01C7CFD2126CE6B79CDC79B3937F5E59A185B95509B5F2F4134E5E5CE064E959CD29258C96E5F76B16276A35A2483C4495F1A581F36E1A912BF5EF10C08EC0458C46DE692D9337262B3D6844523D400D9E7B15D8841A9A65B14629B63D775B95AF7BB139E45D7C9A718593CB7E3958CE535FF119DFC120861387E8999B892C702728B86C1E3E986E79394CE6D4284C66B34F77F2B75B9CDC77558566DE04DCB91F2D97E79ED4A85D5022CF4F4CCBAF4347C8CAA50925AC3A6F4C4ED45AE4B55E58962EF7327953B93404AF53704FABF451FF8ED2CAABFAB7AF1E22D4F0CC212364D9426CD3C83DA3D1EFD8C2928CEDF0CC938A65E6954E2EFF55915CB475B5F719DFC120861315C3F0E1C3BB06EE44AD148E5170394F3839A814D81E7237953BAB73BE9D2482FBD364365F13C4338F3A59FC64892C4AF93601B7A60DDCD74FCDAD690D5C00EA2EB8AFE975C07D5B93223A9729FF1A35B42A35E480BB4857D4D36AE72792928CED30772D3850A7DEBD6E4AA9CCBACAC915BF2E929F28B8563180410C270E7132CBB18EC09DAAE05A19C66E85FBFE3170AD52983F578DD644B1787EE2C032A5059FCC0017BEED00DCE5DD0637497E563D7870B57258093568E27C23AD1A7C528B804BBD1B823B43C19D7DB5932B01779B6AEF33BE6795637642D67570831A772D707537D306EED515726FB07978EAB78903CB170D93E74370D93D65D0C28AEED242FAA5584224A959C500B8AB1FA8D1F9D606F7D9339AD60697CDC4C9C509B89714C94F7B15DC422357C1B55B3818FCD8C1D5F28207B754961E42195627AD69E4BE35374D6839E0B6C89BF35200E7D5CA8A103C958EC0E51A8930135C9DB3D59F355031D4C99214DCC5B757CBA36B45EE48B9F16297807BD610BF0DEE35700BE6DC145CF80B70E7E747AE3AB6E49CD2045C1C3E7F4C0EB8BE5250600070CD69B9E0198071708D1254A78E4357420B504FBDBC9E82BBEABA7A6F833F983F4BBF70C0D5A4BBE0F4C61CCEBDF54C27B7CED68D8472EEA5BADAF0B55738B74BD5C25F9D3C728FEDCEB4CCF1D542C2B96D87354DA3A5F501054F1DCED940A411E7C1CD485859E01A95BCBBA27D43D10E6EFB49D9AAA515F2620AEE82866659A4F66223B66233B6E303BEDC32CBC9CCAF54B46D817BA55A28A4CE9D71627152E7DEE1E4E1BB9D3CA1E03DADCBFBB9274A64A1560BE1D6975A939AF3A573CB7C0D9ABB3B4B9251085C2859E0B651C29C8636603DB83A0FE0BE788A6E5C145C4EC8969FD4BE05E6F8F1F1EF94785BB119DBF1E1CE9B8B65CEAEC9D1233EE2EB3AD7B959C78D9DEDD03845E2249FDD0DBB1CBF434B0FC8730F6DDA4FC3C263C6FCA48684E01522E1D8306A9983B9D6DAA1A94DD86607E7E10E0D5FF24FC66C8716C3A7D363473EE8EED9028F6B72932F3C6EE44620CF0D70F26FB775F24FC4C2A3468BB610A418883109C7981E8B5AE6C83F19B3B3056CC3466C0D8F1DF1059FEC8EC43A9F2DD0B2C0EDEC54CC0ECAB9934A422031D87D334E9EB2CE7263D19B0F30120314C9EFD7066C46D4464FC5D4C63099E1437860DE23A762B48EEE9F6D3ACFCD3E2C2FE83C9770A694D0B696828170272204D6E8202B6A7BEA4E04CF2F147427820B03FA1E5A3A3EA403E6602EE664EE3EBB8746CBE25D6420DCFD8D016B74C0DCDDBDFB1BC30329F8EE2F0DCEC87A006FD3730BB9C2AF2EBBF4DC02614D21AC2DAA709A46EFC6F6C44D0C07A4CB4FDCD081F0A666D31655BAE959B1E4573E5D7E568C46786F7ACAB1E3A8EDD6538E34BE01321F19505B54F9C6F07C6ECC6F845F5776FBF95C5A4789CD64437EB23CE6AFC93A3D594EE39B80A43B8A5E6463FB4D043F595DE7DF44D02C7AF986B44527DB987ECDC3ABB57AE4D73C34E35E7E73C5A98FB6E8A41BD2EFD062FE99F4E8EFD0687C336443F6CEDAA2939A0CF45F50C67C32E9F15F50D2F866A8E1D8DE75F6DB5F6420FEF637E64728BCFC0D3AE8F1DFFED25062C9AD237A301948BF5A8FD91F0A6F70EAB55FAD5B0BE98153206D516342E10C94BD3987CDFDED7D0B317BF38557B2F4FAFB1668460FF6A610B887B768688B1A164A7F7A5348CCBE98F02A96F5F6A6101A4AC990708EBDE30692D71635305FA009CA1D0A757642D496384E54B14322D11069EC98883A80EAA977DCC4EC89C961871DE6DF6ABA5EDF7163CD00E6B00272A7E6EB0AC0083B20F86E7DBC9D29367F96F016D33E7B3B9335380752CF079865A42D6A789610C9DC4A21C11061804226871FB91BC0B694EC0E70A1F019D7E8435FC630B62B516AC25B4B7963699FBF57CC5A08B05104B79829B4B5459D2854BAF246BCD8F8AEC8E1871FEEFAD51BF1AC8500B31DB477397242DF57AF732D548E3AEA28FF32E37EF92E476BC6C1564570A011BE85943A515BD4C1BE10DE16CDAB5EFBFD5B48AD6104250A0719DCF288BD3F9744C1BB6BB5459DEE4D39EEB8E39C813AA0DE9F6BCD00E6DE3D871A2C2D0AEFFC373FE3186F61E66DCC24126D5140D645A64F9FEEA64D9BE6A64E9DEAE718D06F7EB686517094D1049140C6A508CF7A6739599A880284638E39C61D7BECB1A88A821613803CFEF8E33D988C45C706F7CEF2B085514CF1CDB691658743705B216FDBE70DFA80C4729E32658A072D143EDBA8DEB61F368C0D4126FBE210D1C252E48489EC4C24C17D9BFE9F886E340C67B98591CC5284E7B82D4DE983F32C55920B8010692C614022F2D8316DFA1F4E3A6816213846FD485626820C68962AA5108090BD49362C63228F532904E010FB9B6BF4A12F63188B0E7419A0CCC15CCC39E023B590867316CD38CD311E49858C0D202C5DC061190314D187709E8AD8DF5CA30F7D19C35874A00B9D0668DF44A973FF072EE9BC87558CB9B50000000049454E44AE426082"



VarSetCapacity(FILE_BINARY_PRESSED_BUTTON_IMAGE, StrLen(FILE_DATA_PRESSED_BUTTON_IMAGE) / 2, 0)
Loop % StrLen(FILE_DATA_PRESSED_BUTTON_IMAGE) / 2
{
	NumPut("0x" . SubStr(FILE_DATA_PRESSED_BUTTON_IMAGE, A_Index * 2 - 1, 2), FILE_BINARY_PRESSED_BUTTON_IMAGE, A_Index -1, "UChar")
}

HandleToFile := DllCall("CreateFile", Str,A_ScriptDir . "/PressedButtonImage.png", Uint, 0xC0000000, Uint, 3, Ptr, 0, Uint, 2, Uint, 0, Ptr, 0, Ptr)
Result := DllCall("WriteFile", "Uint", HandleToFile, "Uint", &FILE_BINARY_PRESSED_BUTTON_IMAGE, "Uint", StrLen(FILE_DATA_PRESSED_BUTTON_IMAGE) / 2, "Uint", "NULL", "Int", "NULL")
DllCall("CloseHandle", "Uint", HandleToFile) 


CREATE_WINDOW:
Gui, add, text, x20 y20 w360 Center, Image below is a button
Gui, add, picture, BackGroundTrans x156 y50 Center, %A_ScriptDir%/OrdinaryButtonImage.png
gui, show, w400 h300, Image button example using Picture control
WinHwnd := WinExist()
HandCursor := DllCall("LoadCursor", "Uint", WinHwnd, "Uint", 32649)
Return

; Message monitor is checking for mouse movement and clicks. It triggers the functions below it accordingly.
Message_Monitor()
{
	OnMessage(0x200, "CheckCursor")
	OnMessage(0x201, "CheckClick")
}
Return

; Function below monitors the mouse cursors position. If the cursor is in the pictures area, it changes the cursor to a hand cursor. 
CheckCursor(WParam, LParam, Msg)
{
	Global
	MouseGetPos, Xcoord, YCoord
	If (A_Gui = 1 AND XCoord >= 156 AND XCoord <= 243 AND YCoord >= 70 AND YCoord <= 150) ; The math to determine if the cursor is hovering the images area.
	{
			DllCall("SetCursor", "Uint", HandCursor)
			If (Botao_Aceso = 1)
			{
				Return
			}
			GuiControl,, Static2, %A_ScriptDir%/HoveredButtonImage.png
			Botao_Aceso := 1
	}
	else
	{
		If (Botao_Aceso)
		{
			GuiControl,, Static2, %A_ScriptDir%/OrdinaryButtonImage.png
			Botao_Aceso := 0
		}
	}
}
Return

; Function below monitors the clicks in the GUI. If a click is performed inside the picture controls area, it triggers an action (msgbox).
CheckClick(WParam, LParam, Msg)
{
	Global
	Gui +OwnDialogs
	MouseGetPos, Xcoord, YCoord
	If (A_Gui = 1 AND XCoord >= 156 AND XCoord <= 243 AND YCoord >= 70 AND YCoord <= 150) ; The math to determine if the click happened inside the images area.
	{
		GuiControl,, Static2, %A_ScriptDir%/PressedButtonImage.png
		Msgbox % "You have clicked the button! `n(Assign corresponding action in place of this msgbox command)"
		GuiControl,, Static2, %A_ScriptDir%/OrdinaryButtonImage.png
	}
}
Return
:arrow: The first trick here is simple. We are storing hex strings which correspond to the image file binaries inside the script. Using these strings, we than rewrite the image files right before assigning them to a GUI. This solves 2 possible problems: First, the script can now be distributed alone and the GUI will still display the images. Second, if the user has deleted or changed the image files, they will still be restored (overwritten) before usage, which means disrupting the scripts GUI from using the intended image is now a little harder.

As a second trick, the script is using OnMessage() to monitor mouse movement and clicks ir order to correctly animate the image. This transforms the picture control into some form of rudimentary button control. Mouse cursor is set to a hand if the movement takes the mouse to an area inside the image and the pictures image is changed if the mouse clicks inside the same area.

Final Thoughts:

The routine sample is just a proof of concept and can be improved in many ways. It is possible, in example, to add some form of integrity checks to the overwritten image files before assigning the images to the GUI. It must be noted also, that even though the image binaries are stored inside the script, the script still makes use of image files. There are many ways to overcome this situation too if needed. The math that determines whether the mouse position or click is inside the image is a simplified and a bit flawed: It is currently considering a retangular area, which goes beyong the image borders a little bit. Finally, It is a known-limitation of this method that some functionalities of real button controls are not present in this simple picture control version of a button.

Regards,
Gio

:arrow: EDIT: An example script on how to obtain the hex strings of an image file using only AutoHotkey:

Code: Select all

#Persistent
#SingleInstance, Force
FileSelectFile, IMAGE_TO_HEX,,, Select the image file you whant to retrieve a Hex String for, Image files (*.png;*.bmp;*.jpg)
If (ErrorLevel)
{
	msgbox, 0x10, Error, Error reading the file. Close any applications that are using the file and try again.
	ExitApp
}
RESULT_STRING := FILE_TO_HEX_STRING(IMAGE_TO_HEX)
Clipboard := RESULT_STRING
msgbox % "The Hex String has been copied to the clipboard."
Return


FILE_TO_HEX_STRING(FilePath)
{
	STRING_OUT := ""
	ObjFile := FileOpen(FilePath, "rw")
	FILE_LENGTH := ObjFile.RawRead(FILE_CONTENTS, 999999)
	SetFormat, IntegerFast, H
	Loop % FILE_LENGTH
	{
		If (StrLen(NumGet(FILE_CONTENTS, A_Index - 1, "UChar")) = 4)
		{
			STRING_OUT := STRING_OUT . SubStr(NumGet(FILE_CONTENTS, A_Index - 1, "UChar"), 3, 2)
		}
		Else If (StrLen(NumGet(FILE_CONTENTS, A_Index - 1, "UChar")) = 3)
		{
			STRING_OUT := STRING_OUT . "0" . SubStr(NumGet(FILE_CONTENTS, A_Index - 1, "UChar"), 3, 1)
		}
	}
	SetFormat, IntegerFast, D
	Return STRING_OUT
}
KEYWORDS: Picture Control Image Button Texture GUI Color Colour coloring File Change Changing Alter Altering Hover Mouse pointer cursor.
User avatar
Alguimist
Posts: 428
Joined: 05 Oct 2015, 16:41
Contact:

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

13 Sep 2018, 04:53

A modified version:

Code: Select all

#SingleInstance Force
#NoEnv
SetWorkingDir %A_ScriptDir%
SetBatchLines -1

Global hPic, hCursorHand := DllCall("LoadCursor", "Ptr", 0, "Ptr", 32649, "Ptr")

CreateImages()

Gui Add, Text, x20 y20 w360 Center, Image below is a button
Gui Add, Picture, hWndhPic gImageClicked x156 y50 Center +0x100, %A_ScriptDir%\OrdinaryButtonImage.png
Gui Show, w400 h300, Image button example using Picture control

OnMessage(0x200, "OnWM_MOUSEMOVE")
OnMessage(0x20,  "OnWM_SETCURSOR")
OnMessage(0x202, "OnWM_LBUTTONUP")
Return

GuiEscape:
GuiClose:
    ExitApp

CreateImages() {

; The hex string below corresponds to the image file of an ordinary button.
FILE_DATA_ORDINARY_BUTTON_IMAGE := "89504E470D0A1A0A0000000D49484452000000570000005008060000006CCDE9D40000000467414D410000B18F0BFC6105000000097048597300000EC200000EC20115284A800000001974455874536F667477617265007061696E742E6E657420342E302E3137336E9F630000051249444154785EEDD64D4EDC4010866196AC58B1418AC42677C96972981C85AB708F2C922CA248480E0553EEF2D76FFB67DC9EF1D88EF44472E1EEAEFAC663B86B9AE6B0102C1EEAC0E2A10E2C1EEAC0E2A10E2CAEC1FB3FFBAF97AE591B2C5E920656839E712D585C92067109DAC3A56071093AF035684F4BC3624D3AE05A689F4BC0E25C3AC8543FBF7C1D8DD64FA1BDD784C539B4F93128B439E88C3E3A432D583C8736DC8702590A9D5FA233CD85C5A9B4C9121AFE52A81FA2B3CD81C529B43942C35E0BF5A774C67361710C6D88D0706B41FD2A9D792A2C0ED126140DB356D47FA4B34F81C53E7AB8A201D68EE6883483B1B0D8470F8EA8F15B41F3449AC318582CD1031D357BAB683EA3598C8145A28745D4E42DA3198D6632048B4A0F89A8B95B47733ACDA60F16951EE0A8B1ADA0799DE65382C5483776D4D0D6D0DC46332AC1A2D34D1D35B25534BFD1AC08169D6EE8A8892DA30C342B8245A39B393A7CEB2807A399292C1ADDC8D0C17B417968668A8BB289A343F782F2309A5DC445D9C0D0816BF4E7E57D84DF9FFE7DB7DA73F3F7F5AE79FBF19CDD3B15E5A2D9455C940D0C1DB63ADF1FDA60D567D0F3502E9A5D941764B1A3C3D6E6D78FFBA6797D6C7ED9750CFAE509EF9F8A72319AA1CB0BB2D0D0417B45F968862E2FC8424387441F4F4CF80A260FCD1FB8FFC3B7C7E60DD674DF8D4FCD3FB8A7EBBEF9FB2DEC7B7AC7FACF07DFB5A3FA48281FCDD0E5055968E89028FE12C9E9F043F7BFF3AFF6A870E503D4B0DABD72E3FB48281FCDD0752F6491891B97B44DC666C23BAFF314F4BC0BE337809E9CF69C9E77A8DFF3F6F2700A39FF703FCCE883728A39BAEE852C30BA31C170C353971A0C5FD9C213959EA6FC95321CAE9F6981A6B3F280E6F54139C51C5DF7421698B8690986DB3E19E1C9095F597A224C7A6A7A5E27A570FDCC531FED5E1AE0CC3E28A798A3EB5EC80213372D499FB292C6C250C5BF3BE94339190AD77FDE06D69E57B70FCA29E6E8BA17B2C0C44D4BCAE17ECA875D22DCF84AF05AE1D57093E1CAD72F857E7A6F85A1AABF16DA300A626F33FBA09C628EAE7B210B4CDCB4A4146E1AC21B0C7F5AE9BD1FFA7FD1F4859B3EC8B2F494CEEB83728A39BAEE852C3071D39252B869E0F41B373D11F9531303A2AF6B39DC1456BE2E0419D6CDE983728A39BAEE852C30BA3189CD906EF3E1A928C1776A39DC1454FE679349FDC59F9FDF07E5147374DD0B59606873159F82AEFC7DD5BFA67CBF29855BAAB7C2FB589FC473FAA09C628E2E2FC8224307EC15E5A319BABC200B0D1DB257948F66E8F2822C3474C85E513E9AA1CB0BB2D0D1417B43B918CDD07151161B3A6C6F2817CD2EE2A26C60E8B0BDA15C34BB888BB281A303F782F2309A5D8445A39B183A742F280FCD4C61D1E8468E0EDE3ACAC168660A8B4E3773D4C09651069A15C1A2D30D1D35B05534BFD1AC081623DDD451235B43731BCDA8048B916E1C51435B41F33ACDA8048B4A378FA8B12DA0598D66D3078B440F71D4D8ADA3398D6632048B257A98A3066F15CDE7348F21582CD1C314357B4B6826A7598C81C53E7AA8A2A6D78EE6883483B1B038440F5734C05A51FF91CE3E0516C7D026080DB316D4AFD299A7C2E214DA10A1E1AE85FA233AE739B03895365642C35E0AF54374B639B0780E6DB20F0DBF143ABF44679A0B8B7368C3432890B9E89C3E3A432D589C4B9B9F8A022BA1F55368EF3561B1161D644DB4D72560B1361DEC9AB4B7256171493AEC25680F9782C54BD2206AD033AE058BD7A661F5D1B56B82C5431D583CD481C5431D583CD481C5430DCDDD7FF2957802F31AA04F0000000049454E44AE426082"

CreateImage(FILE_DATA_ORDINARY_BUTTON_IMAGE, A_ScriptDir . "\OrdinaryButtonImage.png")

FILE_DATA_MOUSE_HOVERED_BUTTON_IMAGE := "89504E470D0A1A0A0000000D49484452000000570000005008060000006CCDE9D40000000467414D410000B18F0BFC6105000000097048597300000EC100000EC101B8916BED0000001974455874536F667477617265007061696E742E6E657420342E302E3137336E9F630000082249444154785EEDDBCB6B5D551406F0685FA1D1D847ECD3A6E9431DF9404114073AB282E0488482203A12A482A8883A10144110850A4E8A223855848038A81351D181A250ACF84F24695E4DD3A6D99EB59375CF3ADFF9F6B9E7B1CFBDB778859F7057CEDE7BED2FE7EEDC36A723CEB9A196D0E2501CB43814072D0EC5418B4371D0E22048FE93FF15C2318386167B09038B01D7E8175A6C1306D10BD843AFD0621B70C3FD803DB58D1663C20D0E0AECB30DB4D8146EA4AA993B4E96C6C65781BDC7448B4D60F365B0D09A606B14C13DC4428B7560C34558206D61EB87E09E9AA2C5AAB0C910B6F95E61FD30B8B72668B10A6C8E619BED17D61FC23DD6458B6560430CDBDCA060FD22DC7355B4D80D3681D8660615EBDFC2BD57418B45707184CDCF3D32E92EBFBD3B57EF97CBEFEE72F34F1ECED4D83E2CCCA02C5A2C820B5BB66131FFF421B7FED74DCEFD3BE2965FDF9BFB7AAF2DBFB9C7F7223DF522605A0CC105956DD25AF968DC6F462D3EB79F5ED70B4BAF4C647AB972F6567A1DDB9FC02CCAA0450617B35893DEE409B7FAD5CECE86D62F8EE4EE985E587A391BECEAB931DF1BBB56B03D0ACCA41B5A44B888C59ACB3879DC5D9BDED1D9D8F53F6EF6E730BDB6050BA70FF86F6A27D82F7716062BD83E1566538416112EA05863CCEC3D536EEDC7AD69C03F6FF135766D4C18ECD5AF47FD379B5D8BD87E15E613428B164EAC584345E46E95BB56377AEDBBEDA5375A87FF615A3358C5F62D30A3105A5438A9628D9421E76DE62D9A9CC7DDDEA275F875363FA588B5F3DBDCECDDC7E8B5DDB0FD0BCC8AA14585132AD64459F256D54D8B954FC6E97575D1601B1E412C03CC8AA145819329B67855CBAFEECD04BCFCD61E7A5D55FEE8F9754B1A6C72CEC738DB590E023343B4287022C116AE6BE5C3DB7C00EBFF243FE07EBFD92D3C73905E57D6DC8347DDDA0FDBFC7C32AF841CF35309CB033343BC089328B6686DF219F8F3311FECD56F46DDE57776D73E1767A64EB8E5D7F6FA7964BEEBBFC40D56B03C046667F1224C20D8828D253FBD573E1EF7C15E7AFC889BB9ABE6A7873B8FFBF132CFDA9FC91666120BC90FCC33F2F5A36EE54272449C3D9A1F5711CB05B3B3781126106CB12892402F3D96049B043473A4E62707192701BF3FE6DC6CB2852458B41174332C17CCCECA1760B0628B45231FC7EA06AB92F1F39F267F12BC30E1E6E5F599F134DCE966E7B962B908CC50E50B3050B085FEAF583E98A1CA1760A0608B58F36747336FC1D4B85B24D77BA726DC1A19933D1B0FBA55724DD6A85B3965E6DD3C63F5EB5DCFDA527DA4583E98A1CA1760A0608B588BD3C950D2E006DC7CB7EB13FAD62E152E7C0331ACCE5C79E5FB48B17C3043957D0183849D38A4D3A46DC69C7999BBA0E02CB4EF0076E774D6293843F59AB5E9F1CD90F3DF5CAF411F2C279BA3CABE800102276668B8E6AE4B1B346FD9C01D95DE4DF923A57BB8BAA6049AAE950FA8591F2C279BA3CABE8001C24E1A42C3EDDC19E6CE316F59764788F4AE29384E42E1EA9A9B7D74E6C2001BF6C172B239AAEC0B1820ECA421E9771941636653C1CF9DEC9BB2A95BB8FAF54E609DF5E2F6C172B239AAEC0B1820ECA421E17037E437DB46B8F648D05AE068B821C385B75F1AFAE6B9653615FD58E88411607B6BD807CBC9E6A8B22F6080B0938684C24D37A10D9A8F5678AD57FC83A628DCF41B1996DEA5CDFA6039D91C55F6050C1076D29050B8E986D39FB8E91D91BF6B6C40ECED1A0E370D2B3FCE0469C635E983E5647354D9173040E0C48C6D86C9366FEE8A107AA686C34D83CA7F6C12697FF6EBF5FB6039D91C55F6050C106C7264EF82ACFC79151C335F7CBD08851BAA7798F318EF44DE7B711F2C279BA3CA176090600BC4347BEF949B7B20B9BB8FD5FC9B311957776C452C1FCC50E50B3050B04562997B68D25DF9EC16B7F4D2ED6EEEE1C924A40A7F612E7F4D79E2B81FB7F8C23E377B7FFBCF42B07C3043952FC040C11689417E15B3F6D356FF9088FC9A7DE9CC840F8B5D4BC9DFE13E71D82DBFB1C78F976713DA7ED884E58319AA7C01062AB65013F20B45FD4DEDFADF23EEDAF7DB7D8D5D5B64F6BE291FEAF5DFB66CCCF3ED8ED61E3661B908CC50F1220C166CB1BAFCE34DE7B7757E052ECF195C7AF408BDB68CF9A70EB9F50BE9B30AAB5F143F685717CB05B3B3781126106CB13A58B0319E7C5C7C7E7F674E21BFBA67D735C172C1EC2C5E8409145BB092E4ED6A9F788C15ACD2879B55CC07AE591E02B3B36851E024822D5A5A12AC9C8D9D602F8EB885670FF06B1B90C7A36CC0B11EB8667960668816054EA4D8C25D251FAF72C19E8E1FAC270F9B447EE09AE5203033448B0A2753AC8120D9ECB9B1CE66859C8FF4DA58E0F869FAC035CB00B3626851E1848A35409160E5DF26D06B23F33F38233C70CDF62F302B86162D9C54B146109E7FBD0A56F9A71E1B3C70CDF62D30A3105AB470628B35A4563ED8788A515D7E6F17BDAE6DFE79DD1A0F5CB3FD2ACC288416114E6EB1C6E41FD2D9602568765DAFD479E09AED556036456891C145146BCC3EDD1DFBC9F1BAF4816BB98B175FDC47AF516C9F0233E98616437031C51A9480FD3FA46BE18FA175F97F9A9AFC51997D4DB1FD29CCA31B5A0CC1C5106BF646C2F6A4308B3268B1082E8A58D3838EEDC3C20CCAA2C56E7071C43630A858FF16EEBD0A5A2C039B60D8660605EB17E19EABA2C52AB021866DAE5F587F0CEEB30E5AAC0A1B0B619BED15D60F837B6B8216EBC0268BB0CDB785AD1F827B6A8A169BC086BB618134C5D629827B8885169BC2E6AB628185B0F15560EF31D1622CB8914182BDB6811663C38DF513F6D6265A6C136EB617B0875EA1C55EC22062C035FA8516FB0DC32A826307092D0EC5418B4371D0E2501CB43814072D0EC5E046FE03CC0CF56CF1DCBD380000000049454E44AE426082"

CreateImage(FILE_DATA_MOUSE_HOVERED_BUTTON_IMAGE, A_ScriptDir . "\HoveredButtonImage.png")

FILE_DATA_PRESSED_BUTTON_IMAGE := "89504E470D0A1A0A0000000D49484452000000570000005008060000006CCDE9D40000000467414D410000B18F0BFC6105000000097048597300000EC100000EC101B8916BED0000001974455874536F667477617265007061696E742E6E657420342E302E3137336E9F63000014FF49444154785EED9D097456C515C747129240484848202B0471DFF75D1454D0AA48F5504BF7D6D3A3566B7BBAEFB6B655BBB877B3ADAD756D553697AAB5D65A5BB55A4545AB62B182A2028A065104ADDEDEDFBC7793F93EE6255F42421260CEB9E790EFCDDCB9F7FFDDF9DF3BF3DEF7707DD936DB6C332F83060D72454545AEB8B8D80D1E3CD8959494B8D2D252575656E6860C19E2860E1DEACACBCB7384CFB8461FFA3286B1E840173A4DFF46D54240010470006AD8B061AEB2B2D2555555B9112346B8DADA5A3772E448376AD4282F7575755EEC6FAED187BE8C612C3AD0854E7487406FB0CDA2C80025E2884000011C80AAAFAF778D8D8D6EF4E8D1AEA5A5C58D1D3BD68D1B37CE6DB1C5165EB6DC724B2FF637D7E8435FC630161DE84227BA9983B90C68B3638368386251CAD265391BA0441F808C1933C66DBEF9E61EB86DB6D9C66DBFFDF66EC71D77743BEFBCB3DB65975DDCAEBBEEEA76DB6D37B7FBEEBB7BE1DF7CC635FAD097318C4507BAD0896EE630A0991B1B067C345B8418A844104B9765DCD0D0E09D27F20064871D76F02001DC5E7BEDE5F6D9671FB7FFFEFBBB030F3CD08D1F3FDE1D7CF0C15E264C98E0C5FEE61A7DE8CB18C6A2035DE8443773301773323736608B816C760E9816824AB4E0104BB5A9A9C92FE3ADB6DACA471A91B7E79E7BBA7DF7DDD7830470871E7AA89B3C79326AA43339FAE8A3DD91471EE98E38E2083F86B1E840173AD1CD1CCCC59CCC8D0DD8824D6124F77B803190E546C626A9B01489161C62A912492C61A28B4823F2B445815B170170C09E3871A29F83B99893B9B1015BB009DBB0115BB1B9DF524518AD646C788EA548B2D97AEBADDD4E3BEDE4F6D8630FBA4601E94D99346992A791FDF6DBCFDB802DD8846DD888ADD8DC2FA3D880252B13092C3BB237C905EE236AB4451D5F9F4234431B808C4DD8868DD88ACDD88E0FFD06608C301AA8AEAEF6A510DCB6EDB6DB7ABED31675B4AFE5A0830EF274818DD88ACDD88E0F46137D0A301C45FD48F6656951FA909DB5451D2A54BE33B452BE3B74B87C5FE5CCF2E172767995971FA4627F732D36BE2B72C0010778AA208AB11D1FF0059FF00D1FD77B0B81ADA9A971CDCDCD7E89698B3AD1919C3E240113B000EFC7C3AAE4DC61D572BECA851523E422959FE4099F718D3EF4650C63BB033851BCF7DE7B7B2EC6077CC1A73E013804968C0B67698B1A1E932F950D936F0CA9F0110A183F545000E8021580FB79458D5C5C5923BF52F97565AD5CA2F29BE1B9C2675CA30F7D19C35874A00B9D5D059AF20D9A20D9E113BEAD57808D63BB03EC1715D4AFA7A09EA58E136D441EA0FCC2839900F7BBE123E572952BAB46CA5555A3E46A95DFE7099F718D3EF4650C63D1812E74A29B39982B664F4C4876ECFEF201EE750E366029BE8D0AB4458D0CE573A5E5F2D5B20ABFFC89A61F695411613F53007EA94000CA65299800774DF528B9AEBA4E66AACC52993DA25EE6E4099F718D3EF4650C63D1812E74A29B39988B390B8D64767C06B051043EF71AC028A544B1AA405BD4B0504E2D1D2A5F4829004E8513CF53477F9A82FA5B0580A8230AAF4D8102B41B546E1AD1207FAC69909B556E51B9D54B632AC9675CA30F7D19C35874A00B9DE8660EE6624EE6C6066C89D99B2F50043B3B361C5645F44A9906E7708CC7B6515BD418934F960C91D31458B8F55B1AAD64FD1FAB632421F891A8C271228DA89B95020A5080F62705F0CFB58DF217953B6A9BE4AF2A77E6099F718D3EF4650C63D1812E74A29B39988B39991B1BB0059BB02D667F289C537002C76603DFC1A047F9976F0A52AFA8A8E0CFA8112609B0E5F26505161A80EF4830440E7C0837C29544179176A30A110838B7A760FE6D6493DCA5F28F91CD72B7CA3DC8A866B93715FECD675CA30F7D19C35874A00B9DE8660EE6624EE6C6066CC1266CC3C6981FA1B06D66CBCC59321880458F44AFD1019C03B96B8B1A8084C07E5B9316B52849854C4E76BF5CF9F00FEA244B97E80280DB1408A28F68FC7B0A1800DE376AB4DCAFF22F950790BAD1F260DD182FFC9BCFB8461FFA3286B1E840173AD1CD1CCCC59CCC8D0DD8824DD8868DD81AF32794EDB6DBCE9FAE810158F4083D144207D38B4BE5849232F9B452413EB0646E788F4463D10A47125D1E548D3800211A0109C00070AECA432A0FAB3CA232AFAE2547F88C6BF4A12F63188B0E7479905537733017735A14630B36615B0830B6C7FC43384326C1C1BF3D420F7C3364480E35B44527453E3EB84C4E516029B55866F9C0B224E1BFEBD3688523E14C0FAA0A80108980046080F7687D8B3CA6F26F95C75379A27EAC17FB9B6BF4A12F63188B0E747990553773301773323736600B36E5038CEDF810F3116193C12E0E7A009375AA1EF86638C8D0169D0CF988027BB2D2C1E7D5A86F6A5540B9435666D919B033D419962609074E841F59C2FF5400883600211201C9C07C52419CDF90C853A9FC2715FBDBAED3D7C04607BAD0896EE6602EE6646E6CC0166C3280B1159BB11D1F627E9A400FD4BF6C91C1A65BD1CB37D25912FBC0E052CFB39F559EFD9A1AF53DCDC0E7A891D49664678B589CA17C6289927C8828B892A54CB419A844A58109880B1A3697A755FE6BD2984AFA37D7E8638033161D0632BA9983B99893B9B1015BB0C922185BB119DBF1015F62FE9A503D70C8D3EDE4D659D4BEAFB8C4D301B52C5CC5AE8B429D9D11DBD22B94D78C0A88160396C413462BCBDA400D017D46414416AA2C6A1C1715AE59BF10680319DD611433B7018C4D4611D88ACDD88E0FF8D211FF726783E4D6ADE835AED51655FEDEE2C1F2218DDA933C1D94EB524A78969D10053B3B24764CECA462C09284E6A9E344184B9AA80318A23104F45995E702599C4AF8197D42A0D1812E74A29B39988B3963006323B66233B6E303BEE013BEC5FC47C2E8ED12F7F24D900DB545151FAF51FB098D5A360A6C6B594AD48D70D7A5BAC428DC29E229E84924F01D19DC8065C9C29116AD16A90B53B0DA806C1A27CFA7F242D31639629FD3C700672C3A2C922D8A998B390D606CC1266CC3466CC5666CC7077CC1277CC3C71806C6BDECDC0AAE1CF806A8E1B445954E0DA296AD2D19962D253B1F9616650EC982029E3A939A938402EF59C4B6039B449A45AA811A82F9622712826D205B24A39B390C608B606CC1266CC3466CC5666CC7077CC1277CC3C7180E089503B7EE39D829A8EEA50324AD6D2D65471415CBB48CA8A5A4610714D2013B2676509445F01EE592016B34000816AD06AA01B72495A51962D743A0D1D11EC5ED34D106B0DA802DD8846DD818D2033EE04B21D14BDDCBE13AB7870A4A6C697847954D291AEC2B8413356A3FA77CC4DEDCA2F612FDC6C9BCEC846E4AE9C078961D1589C573AC8FD8B139C086D16AA086202ECB90B08F811C4671083073323736600B3619FF622B36633B3EE08B452F3EE26B0C0FA44B892D8B122669D41EAB51FBD174C340363D43BF59CA1778CAA2960C4CA943E11ED2815505C6B1F9C0E647AA07B03991979AB78C8A5D37A019FBCA4C27AB5F72F2E63227AF7E0A8047CBD27B9CBC7C76B39FDBAA88901EB0159BB1DDA2179FF00D1FF1159F63B81835D89638B311D65955C27B346A29BFD8E67E46EB5A0EBD29BAC9AEDC0DA09C81B7D8665AD452C05367867460C92B06AC456116A02FA712BBC698A5A756CA5BAF3859B35C017E3901F88D254E56BEE0E4A513932417D203B661635BF4AAEDF8802FF8846FF888AFF81CC3056AE0C4ACD3AA21BD105572744009ECC6207B6EA570C2C42E876CCBDEDDB8363F6A298B3C1D28B096BC8C0AF2A3D50033303B13EBFFCAF965F2F643B5B21C9DA754F8085EA500BF7E4D9D9F93B93D3D44A2D7B8171FF0059FF00D1FF1159F63B8201CA873DEC0730F99E066F1ED21838A7D6DFB6105F75325C939AD5102E44F8DC88108BB1EB22F650E7C16462D75670E1D041CBB2EC09AD8B890268C8399CBF8171BB0258C5E6CC5666CC7077CC1277C336AC0677C8FE1C3C325DCADE890773BE2DBE394123EA67CCBC9D757759970D8CC8107CBE7EA138AE4B6394EEEBAD5C9BFEE7432EF5E274F3EE8E4BF8F96CBFCACA83DAC4656E9D27D4B97F0DBBA94FFF7AA93775AF5EF0B5A02D01A64F50A27F25A5CDED56BEFAE289355878700B7C8EB0F273AD1BDEADC317E85588916462FB5EFDCF155F2B8DA8ACDD88E0FF832EB04CE9F93431D7CC5677C8FE103EFF2504926EF12CE59E0528219DF728EC06D1B763156255CFB0D27B7DFE0E4EE3F3B79F02E278FDDE7E4A9879C2C7CCCC9F3F34BE4D90949E96551BBECDA24E9C08D21B08807EC915A6955A0962BB86B22A0E64AA5BCD6F66528B8936BE52DD5834E74AF79B0C6477218BD569A3D75696223B66233B6E303BEDC708D933FFC6888A7067CC5677C8FE1C3ED784ECA32EBDD2CBE1D3FA8488E54BE7D7F717248C3CD46CA93906F677CD3C91D3739B9F78A0AF9BB72173BA0073E3254163DEEE485FF38597266734A091A412757F844B39AA89D599F93C05A2F284BA351C1B9B045C105E07659797D0AE8F50D6B5D33705FD3A8E34B5A33BB5256FBE82D931593DAEB5F6CF0D4F0C961DE366C5C7071ADB7994D05F7E86E3CB558FE789D936B2F73F29BE9C9AD7F5F92A9EF6010C3A9C3A49605EE410A6E98CCD8B170B0CC01C7CFD2126CE6B79CDC79B3937F5E59A185B95509B5F2F4134E5E5CE064E959CD29258C96E5F76B16276A35A2483C4495F1A581F36E1A912BF5EF10C08EC0458C46DE692D9337262B3D6844523D400D9E7B15D8841A9A65B14629B63D775B95AF7BB139E45D7C9A718593CB7E3958CE535FF119DFC120861387E8999B892C702728B86C1E3E986E79394CE6D4284C66B34F77F2B75B9CDC77558566DE04DCB91F2D97E79ED4A85D5022CF4F4CCBAF4347C8CAA50925AC3A6F4C4ED45AE4B55E58962EF7327953B93404AF53704FABF451FF8ED2CAABFAB7AF1E22D4F0CC212364D9426CD3C83DA3D1EFD8C2928CEDF0CC938A65E6954E2EFF55915CB475B5F719DFC120861315C3F0E1C3BB06EE44AD148E5170394F3839A814D81E7237953BAB73BE9D2482FBD364365F13C4338F3A59FC64892C4AF93601B7A60DDCD74FCDAD690D5C00EA2EB8AFE975C07D5B93223A9729FF1A35B42A35E480BB4857D4D36AE72792928CED30772D3850A7DEBD6E4AA9CCBACAC915BF2E929F28B8563180410C270E7132CBB18EC09DAAE05A19C66E85FBFE3170AD52983F578DD644B1787EE2C032A5059FCC0017BEED00DCE5DD0637497E563D7870B57258093568E27C23AD1A7C528B804BBD1B823B43C19D7DB5932B01779B6AEF33BE6795637642D67570831A772D707537D306EED515726FB07978EAB78903CB170D93E74370D93D65D0C28AEED242FAA5584224A959C500B8AB1FA8D1F9D606F7D9339AD60697CDC4C9C509B89714C94F7B15DC422357C1B55B3818FCD8C1D5F28207B754961E42195627AD69E4BE35374D6839E0B6C89BF35200E7D5CA8A103C958EC0E51A8930135C9DB3D59F355031D4C99214DCC5B757CBA36B45EE48B9F16297807BD610BF0DEE35700BE6DC145CF80B70E7E747AE3AB6E49CD2045C1C3E7F4C0EB8BE5250600070CD69B9E0198071708D1254A78E4357420B504FBDBC9E82BBEABA7A6F833F983F4BBF70C0D5A4BBE0F4C61CCEBDF54C27B7CED68D8472EEA5BADAF0B55738B74BD5C25F9D3C728FEDCEB4CCF1D542C2B96D87354DA3A5F501054F1DCED940A411E7C1CD485859E01A95BCBBA27D43D10E6EFB49D9AAA515F2620AEE82866659A4F66223B66233B6E303BEDC32CBC9CCAF54B46D817BA55A28A4CE9D71627152E7DEE1E4E1BB9D3CA1E03DADCBFBB9274A64A1560BE1D6975A939AF3A573CB7C0D9ABB3B4B9251085C2859E0B651C29C8636603DB83A0FE0BE788A6E5C145C4EC8969FD4BE05E6F8F1F1EF94785BB119DBF1E1CE9B8B65CEAEC9D1233EE2EB3AD7B959C78D9DEDD03845E2249FDD0DBB1CBF434B0FC8730F6DDA4FC3C263C6FCA48684E01522E1D8306A9983B9D6DAA1A94DD86607E7E10E0D5FF24FC66C8716C3A7D363473EE8EED9028F6B72932F3C6EE44620CF0D70F26FB775F24FC4C2A3468BB610A418883109C7981E8B5AE6C83F19B3B3056CC3466C0D8F1DF1059FEC8EC43A9F2DD0B2C0EDEC54CC0ECAB9934A422031D87D334E9EB2CE7263D19B0F30120314C9EFD7066C46D4464FC5D4C63099E1437860DE23A762B48EEE9F6D3ACFCD3E2C2FE83C9770A694D0B696828170272204D6E8202B6A7BEA4E04CF2F147427820B03FA1E5A3A3EA403E6602EE664EE3EBB8746CBE25D6420DCFD8D016B74C0DCDDBDFB1BC30329F8EE2F0DCEC87A006FD3730BB9C2AF2EBBF4DC02614D21AC2DAA709A46EFC6F6C44D0C07A4CB4FDCD081F0A666D31655BAE959B1E4573E5D7E568C46786F7ACAB1E3A8EDD6538E34BE01321F19505B54F9C6F07C6ECC6F845F5776FBF95C5A4789CD64437EB23CE6AFC93A3D594EE39B80A43B8A5E6463FB4D043F595DE7DF44D02C7AF986B44527DB987ECDC3ABB57AE4D73C34E35E7E73C5A98FB6E8A41BD2EFD062FE99F4E8EFD0687C336443F6CEDAA2939A0CF45F50C67C32E9F15F50D2F866A8E1D8DE75F6DB5F6420FEF637E64728BCFC0D3AE8F1DFFED25062C9AD237A301948BF5A8FD91F0A6F70EAB55FAD5B0BE98153206D516342E10C94BD3987CDFDED7D0B317BF38557B2F4FAFB1668460FF6A610B887B768688B1A164A7F7A5348CCBE98F02A96F5F6A6101A4AC990708EBDE30692D71635305FA009CA1D0A757642D496384E54B14322D11069EC98883A80EAA977DCC4EC89C961871DE6DF6ABA5EDF7163CD00E6B00272A7E6EB0AC0083B20F86E7DBC9D29367F96F016D33E7B3B9335380752CF079865A42D6A789610C9DC4A21C11061804226871FB91BC0B694EC0E70A1F019D7E8435FC630B62B516AC25B4B7963699FBF57CC5A08B05104B79829B4B5459D2854BAF246BCD8F8AEC8E1871FEEFAD51BF1AC8500B31DB477397242DF57AF732D548E3AEA28FF32E37EF92E476BC6C1564570A011BE85943A515BD4C1BE10DE16CDAB5EFBFD5B48AD6104250A0719DCF288BD3F9744C1BB6BB5459DEE4D39EEB8E39C813AA0DE9F6BCD00E6DE3D871A2C2D0AEFFC373FE3186F61E66DCC24126D5140D645A64F9FEEA64D9BE6A64E9DEAE718D06F7EB686517094D1049140C6A508CF7A6739599A880284638E39C61D7BECB1A88A821613803CFEF8E33D988C45C706F7CEF2B085514CF1CDB691658743705B216FDBE70DFA80C4729E32658A072D143EDBA8DEB61F368C0D4126FBE210D1C252E48489EC4C24C17D9BFE9F886E340C67B98591CC5284E7B82D4DE983F32C55920B8010692C614022F2D8316DFA1F4E3A6816213846FD485626820C68962AA5108090BD49362C63228F532904E010FB9B6BF4A12F63188B0E7419A0CCC15CCC39E023B590867316CD38CD311E49858C0D202C5DC061190314D187709E8AD8DF5CA30F7D19C35874A00B9D0668DF44A973FF072EE9BC87558CB9B50000000049454E44AE426082"

CreateImage(FILE_DATA_PRESSED_BUTTON_IMAGE, A_ScriptDir . "\PressedButtonImage.png")

} ; End of CreateImages()

OnWM_MOUSEMOVE(wParam, lParam, Msg, hWnd) {
    Static Botao_Aceso := False

    If (hWnd == hPic && !Botao_Aceso) {
        GuiControl,, %hPic%, %A_ScriptDir%\HoveredButtonImage.png
        Botao_Aceso := True

    } Else If (hWnd != hPic && Botao_Aceso) {
        GuiControl,, %hPic%, %A_ScriptDir%\OrdinaryButtonImage.png
        Botao_Aceso := False
    }
}

OnWM_SETCURSOR(wParam, lParam, msg, hWnd) {
    If (wParam == hPic) {
        DllCall("SetCursor", "Ptr", hCursorHand)
        Return True
    }
}

OnWM_LBUTTONUP(wParam, lParam, msg, hWnd) {
    If (hWnd == hPic) {
        GuiControl,, %hPic%, %A_ScriptDir%/HoveredButtonImage.png
    }
}

ImageClicked() {
    GuiControl,, %hPic%, %A_ScriptDir%/PressedButtonImage.png
}
Return

CreateImage(HexData, Filename) {
    If (FileExist(Filename)) {
        Return
    }

    Len := StrLen(HexData) / 2
    VarSetCapacity(BinData, Len, 0)
    Loop %Len% {
        NumPut("0x" . SubStr(HexData, A_Index * 2 - 1, 2), BinData, A_Index - 1, "UChar")
    }

    f := FileOpen(Filename, "w")
    f.RawWrite(BinData, Len)
    f.Close()
}
What should be noticed in your script:
• The files are created without checking if they already exist, which may overwrite a user file with the same name.
• The code that creates the files is repeated three times. Why not writing a function for it?
• Unnecessary use of DllCalls: CreateFile, WriteFile and CloseHandle. Why not FileOpen, File.RawWrite and File.Close?
• The first parameter of LoadCursor is hInstance (which should be 0 in this case), not the hWnd of the window.
• There is no need for WM_LBUTTONDOWN, simply assign a g-Label to the picture control.
• There is no need to check the coordinates of the picture in WM_MOUSEMOVE: identify the control by its global hWnd.
• The cursor should be set in WM_SETCURSOR (the style SS_NOTIFY (0x100) is needed in this case).
• The picture button can stay in pressed state when clicked and changed back to hovered state in WM_LBUTTONUP.
• Why including the picture data in the script, instead of providing everything in a compressed file?

When it comes to custom buttons, Class_ImageButton should necessarily be mentioned.
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

13 Sep 2018, 05:01

Also, why do you use UINT with handles and memory addresses? Both are of type UPTR.
Edit: What is "uint", "NULL" :shock:
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

13 Sep 2018, 09:04

Thank you both for the suggestions.
The files are created without checking if they already exist, which may overwrite a user file with the same name.
This is intended behaviour. If the user (not the programmer) tries to change the image files in the scripts folder (so as to change the corresponding image in the GUI) it will not work precisely because the script will overwrite the newly added files with the old ones as soon as it is executed. The original images (the ones the developer choose) are restored on each execution through overwriting of the image files using in-script data. There is also no need to worry about a possibility of overwriting legitimate files: the routine will only overwrite files with those precise names and only if they are located in the same folder as the script. Any files that meet such exclusive criteria were probably set there on purpose (as an attempt to change the GUIs image).
Why including the picture data in the script, instead of providing everything in a compressed file?
The idea is that the script works as a standalone file. Also, it prevents messing with the image data without accessing the source.

All the other suggestions are valid :thumbup:
Also, why do you use UINT with handles and memory addresses? Both are of type UPTR.
Old basic code which i recycled. Changed only what had to be changed.
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

16 Sep 2018, 18:17

Been wondering about this for long time thanks to you and Alguimist


How do you acheive this:
We are storing hex strings which correspond to the image file binaries inside the script
How do you extract this data from an image?
User avatar
SpeedMaster
Posts: 494
Joined: 12 Nov 2016, 16:09

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

16 Sep 2018, 19:02

DRocks wrote:How do you extract this data from an image?
The storage of images in base 64 takes less space than in Hex (base 16)

You can find an encoder\decoder for base 64 here
https://autohotkey.com/boards/viewtopic.php?t=35964
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

16 Sep 2018, 19:25

Ty! :)
So far its one of the coolest things I've tried in AHK. I'm creating a MouseOver Lock icon that move its so fun.
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

16 Sep 2018, 21:44

DRocks wrote:How do you extract this data from an image?
I commented it on the code. I used a third party program called HexEdit. There is a menu option in the program that allows you to export the hex strings (File -> Export -> Hex Text). I then used the SciTE4AutoHotkey text editor to substitute the empty spaces between the hex bytes (A sequence of 2 hex digits is used for each byte, and the sequences come separated by whitespaces when you export the hex from HexEdit).

As a side note, it is also possible to create a routine that obtains hex strings from files directly in AutoHotkey. Might do one when i get the time.

EDIT: Done below.
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

17 Sep 2018, 03:51

Thank you Gio and sorry for missing that info from your OP.

Nice for the in Autohotkey solution!
User avatar
Gio
Posts: 1247
Joined: 30 Sep 2013, 10:54
Location: Brazil

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

18 Sep 2018, 10:16

As promissed, here is a routine that retrieves the Hex String of a chosen image file (PNG, JPG or BMP) and copies it to the clipboard (so that you can paste it in the source code of the script in which you whant to include the images).

Code: Select all

#Persistent
#SingleInstance, Force
FileSelectFile, IMAGE_TO_HEX,,, Select the image file you whant to retrieve a Hex String for, Image files (*.png;*.bmp;*.jpg)
If (ErrorLevel)
{
	msgbox, 0x10, Error, Error reading the file. Close any applications that are using the file and try again.
	ExitApp
}
RESULT_STRING := FILE_TO_HEX_STRING(IMAGE_TO_HEX)
Clipboard := RESULT_STRING
msgbox % "The Hex String has been copied to the clipboard."
Return


FILE_TO_HEX_STRING(FilePath)
{
	STRING_OUT := ""
	ObjFile := FileOpen(FilePath, "rw")
	FILE_LENGTH := ObjFile.RawRead(FILE_CONTENTS, 999999)
	SetFormat, IntegerFast, H
	Loop % FILE_LENGTH
	{
		If (StrLen(NumGet(FILE_CONTENTS, A_Index - 1, "UChar")) = 4)
		{
			STRING_OUT := STRING_OUT . SubStr(NumGet(FILE_CONTENTS, A_Index - 1, "UChar"), 3, 2)
		}
		Else If (StrLen(NumGet(FILE_CONTENTS, A_Index - 1, "UChar")) = 3)
		{
			STRING_OUT := STRING_OUT . "0" . SubStr(NumGet(FILE_CONTENTS, A_Index - 1, "UChar"), 3, 1)
		}
	}
	SetFormat, IntegerFast, D
	Return STRING_OUT
}
:arrow: Use the script above only to obtain the hex string (it is stored in the clipboard once the routine finishes) for pasting in the script whose source should contain the image (In example, you can substitue the string that generates the button images in the example on top of this topic in order to change the button images).
burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

18 Sep 2018, 14:18

@SpeedMaster, I use that SKAN enc/dec script you linked to also. @Gio, that's a nice couple of scripts!
Regards,
burque505
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Storing images in the script itself and than displaying them in an animated button (picture control)

19 Sep 2018, 22:10

Thanks man Ill need this when compiling my script! Awesome tips.

Return to “Tips and Tricks (v1)”

Who is online

Users browsing this forum: No registered users and 23 guests