Jaenchen Posted March 22, 2010 Author Share Posted March 22, 2010 Hi & "Guetä Morgä!" M23 Thanks for your answers and of course the new code. I don't think that there are lurking away more surprises in my bottomn line. I've played around with the screen resolution but this din't improve the quality of the bitmap but I've found out, that the first time, the window was activated as I took the snapshot (with snagIt from techsmith com). So maybe we have to consider that the code should also work when the window is deactivated (surprise surprise!) :-). I would be useful if the code runs on the deactivated window because of i have lot's of other windows open. I hope this is not unsolvable for a genius like you. At the moment, I don't have a row containing XPD but I'll send you the new PICs as soon I have one. In the meantime, I've made to PICs containing a D from 'USD'. Maybe this is already enough for you. It may be that we get more than 2 rows at the same time so I think we should consider the total of rows in the status row. Because of then it might be easier to determine how many new rows came in and thus must be displayed in the POPUP. I'll now jump over to your next post and aswer the questions from "there". thanks Jan Link to comment Share on other sites More sharing options...
Jaenchen Posted March 22, 2010 Author Share Posted March 22, 2010 (edited) Jaenchen,1. I would like an image of the "D" letter from the screen to confirm what I believe is the pattern to match,2. I would like to know the number of pixels between the vertical line at the left of the "Curr.1" column (where we place the first cross) and the leftmost pixel of the third letter in the currency code. You can do this with the Au3 Window Info tool which you find at "C:\Program Files\AutoIt3\Au3Info.exe" with a standard AutoIt install. Select the "Mouse" tab and then move the target into the correct places on the app and read the values shown. You can use the <Options - Magnify> menu item to get a better guide as to where to place the cursor. I am currently using a figure of 20 pixels based on the blurred image you sent. Alternatively, send me a better quality picture!Ha! M23, Thanks again for the code. It seems to work quite well and please be sure, I'm not cutting the tree, I'm sitting on, by myself.Your App will prevent us from losing PNL :-) just because of one crapy little window out of about 30-40 you have on your desktop, have not been monitored enough. The worstcase would be you're getting a row droped into, the user does not notice it and the prices are going ballistic.... Ofcourse: All will be the users fault and nobody will blame you or anyone else. Your Tool will be a very decent App the user will appreciate very well to work with it. Btw. NICE Messagebox Formatings and the beet is also great. :-)Now back to work:1) I'll send you one as soon as I can create one - in the meantime I hope the one containing USD is sufficient2) I'm placing the mouse on these areas and I'm getting 52/123 and 74/123 = 22 Pixels in the WindoInfoTool.((If everything is getting too complicated - what I not really beleave into after all I've seen here - , the user just would be happy to get messagebox opened saying "NEW ROW IN FX-DEALBLOTTER"))Best regardsJanYes, YOU! Edited March 22, 2010 by Jaenchen Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 22, 2010 Moderators Share Posted March 22, 2010 Jaenchen, And a good morning to you too. Under sunny skies I won the match on the final green with a round of 6 under my handicap - all is well with the world! So to your questions: the code should also work when the window is deactivatedIt will work if the window is visible on screen - it needs to see the pixels, so the app window cannot be minimised or hidden by other windows, it must be visible somewhere on the screen. a D from 'USD'. Maybe this is already enoughIt is - and my guess was correct. It may be that we get more than 2 rows at the same timeThe code as it stands will read up to 13 new rows on each pass - which I hope will be sufficient. I do NOT want to read the status bar - it means another cross to position. 22 Pixels in the WindoInfoToolThanks - that was the final piece of the jigsaw! OK, time to try on the real thing! Make sure the app window is visible, with the GMT, Curr.1 and Amount1 columns showing, and run this script. You will have to place the 2 crosses and then you should see a dialog displaying the first 14 lines of the contents of your app with the correct values. expandcollapse popup#Region ; ----- Includes ----- #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <StaticConstants.au3> #include <Array.au3> #include <Misc.au3> #EndRegion #Region ; ----- Get App handle ----- ; Get handle of app window $iOldMode = Opt("WinTitleMatchMode", 2) $hGUI = WinGetHandle("FX daily deal blotter") If @error Then MsgBox(16, "Disaster!", "Could not find the Window") Opt("WinTitleMatchMode", $iOldMode) #EndRegion ; ----- Find fxddb GUI ----- #Region ; ----- Determine ini path ; Determine location for ini file If @ScriptDir = @ProgramFilesDir Then ; If app in C:\Program Files need to save elsewhere If Not FileExists(@AppDataDir & "\fxddb") Then DirCreate(@AppDataDir & "\fxddb") $sIniFile = @AppDataDir & "\fxddb\fxddb.ini" Else ; Can use app folder $sIniFile = @ScriptDir & "\fxddb.ini" EndIf #EndRegion #Region ; ----- Declarations ----- ; Array of digit and sign codes Global $aChecks[12] = [ _ "011110100001100001100001100001100001100001100001100001011110", _ "000100001100010100000100000100000100000100000100000100000100", _ "011110100001000001000001000001000010000100001000010000111111", _ "011110100001000001000001001110000001000001000001100001011110", _ "000010000110000110001010001010010010010010111111000010000010", _ "011111010000010000100000111110100001000001000001100001011110", _ "011110100001100000100000101110110001100001100001100001011110", _ "111111000010000010000100000100001000001000010000010000010000", _ "011110100001100001100001011110100001100001100001100001011110", _ "011110100001100001100001100011011101000001000001100010011100", _ "000000000000000100000100000100111111000100000100000100000000", _ "000000000000000000000000000000000000000111000000000000000000"] ; Array of Curr.1 letter edges (D, G, T, U) Global $aCurr[4] = [ _ "1111111111", _ "0011111100", _ "1000000000", _ "1111111100"] ; Array to hold numbers read from app Global $aCurrArray[15][3] ; Find position of the app window Global $aAppPos = WinGetPos($hGUI) ; Coords of the 2 points user will mark Global $iX_Cross_1, $iY_Cross_1, $iX_Cross_2, $iY_Cross_2, $iX_Colon = $aAppPos[0] - 1 #EndRegion #Region ; ----- Initialisation ----- ; Get user to mark the points Mark_Cross() #EndRegion #Region ; ----- Read values ----- ; Read the numbers in GMT, Curr.1 and Amount1 columns to set the base array Read_Values() _ArrayDisplay($aCurrArray) Exit #EndRegion #Region ; ----- Read_Values ----- Func Read_Values() ; Coords of zones to check for digit/sign Local $aX_Coords_1[4] = [-15, -8, 3, 10] Local $aX_Coords_2[9] = [65, 58, 51, 47, 40, 33, 26, 15, 8] $iY_Coord = $iY_Cross_1 + 3 ; Reset array Global $aCurrArray[15][3] ; Find colon if not yet set If $iX_Colon = $aAppPos[0] - 1 Then Find_Colon() ; Move down line by line For $iY_Index = 0 To 14 $iBackgroundColour = Hex(PixelGetColor($iX_Colon - 1, $iY_Coord + ($iY_Index * 16) + 1), 6) ; Start in the GMT column ; Zero the code $sCode = "" ; Move through the digit/sign spaces from left For $iX_Index = 0 To 3 ; Move through the space to build the code $sString = "" For $y = 0 To 9 For $x = 0 To 5 $sString &= Read_Pixel($iX_Colon + $aX_Coords_1[$iX_Index] + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Next ; Check in the index for a match $iIndex = _ArraySearch($aChecks, $sString) ; Add the correct digit/sign to the list Switch $iIndex Case 0 To 9 $sCode &= $iIndex EndSwitch ; Add colon in correct place If $iX_Index = 1 Then $sCode &= ":" Next ; Check if we have reached the end of entries If $sCode = ":" Then ExitLoop ; Store the GMT $aCurrArray[$iY_Index][0] = $sCode ; Now move on to Curr.1 column ; To distinguish between the possible values, we need only look at the left edge of the 3rd letter $iX_Curr = $iX_Cross_1 + 22 ; Read the edge line $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($iX_Curr, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next ; Check in the index for a match and write to the array $iIndex = _ArraySearch($aCurr, $sString) Switch $iIndex Case 0 $aCurrArray[$iY_Index][1] = "XPD" Case 1 $aCurrArray[$iY_Index][1] = "XAG" Case 2 $aCurrArray[$iY_Index][1] = "XPT" Case 3 $aCurrArray[$iY_Index][1] = "XAU" EndSwitch ; Now move on to the Amount1 column ; Zero the code $sCode = "" ; Move through the digit/sign spaces from left For $iX_Index = 0 To 8 ; Move through the space $sString = "" For $y = 0 To 9 For $x = 0 To 5 $sString &= Read_Pixel($iX_Cross_2 - $aX_Coords_2[$iX_Index] + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Next ; Check in the index for a match $iIndex = _ArraySearch($aChecks, $sString) ; Add the correct digit/sign to the list Switch $iIndex Case 0 To 9 $sCode &= $iIndex Case 10 $sCode &= "+" Case 11 $sCode &= "-" EndSwitch If $iX_Index = 2 Then ; If we did not find a digit at the thousands point, check for a sign ; If we did, add a comma If $iIndex > 0 Then $iX_Index = 3 $sCode &= "," EndIf EndIf ; Add the decimal at the correct point If $iX_Index = 6 Then $sCode &= "." Next ; Store the Amount 1 $aCurrArray[$iY_Index][2] = $sCode Next EndFunc ;==>Read_Values #EndRegion #Region ; ----- Find_Colon ----- Func Find_Colon() ; Set Y coord $iY_Coord = $iY_Cross_1 + 3 ; Check colour of background $iBackgroundColour = Hex(PixelGetColor($iX_Cross_1 - 1, $iY_Coord), 6) ; Move across app window to find colon For $x = $iX_Cross_1 To $aAppPos[0] Step -1 $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($x, $iY_Coord + $y, $iBackgroundColour) Next ; Found it If $sString = "0001000001" Then ExitLoop Next ; Set the coordinate to the colon $iX_Colon = $x EndFunc ;==>Find_Colon #EndRegion #Region ; ----- Read_ Pixel ----- Func Read_Pixel($iX_Pixel, $iY_Pixel, $iBackgroundColour) $sColour = Hex(PixelGetColor($iX_Pixel, $iY_Pixel), 6) ; If pixel colour is not the background colour - set the code If $sColour <> $iBackgroundColour Then Return "1" Else Return "0" EndIf EndFunc ;==>Read_Pixel #EndRegion #Region ; ----- Mark_Cross ----- Func Mark_Cross() ; Open dll for _IsPressed Local $UserDLL = DllOpen("user32.dll") While 1 ; Read ini values for GMT cross intial position Local $iX_Start = IniRead($sIniFile, "GMT Cross", "X-Coord", 45) + $aAppPos[0] Local $iY_Start = IniRead($sIniFile, "GMT Cross", "Y-Coord", 100) + $aAppPos[1] ;SplashImageOn("Place the cross here", "fxddb_Splash_1.jpg", 250, 76) ; Set GMT cross $aRet = Move_Cross($iX_Start, $iY_Start, "fxddb_Splash_1.jpg", $UserDLL) $iX_Cross_1 = $aRet[0] $iY_Cross_1 = $aRet[1] $iCheckSum_1 = PixelChecksum($iX_Cross_1 - 1, $iY_Cross_1 - 1, $iX_Cross_1 + 1, $iY_Cross_1) ; Read ini values for Amount1 cross intial position Local $iX_Start = IniRead($sIniFile, "Amount1 Cross", "X-Coord", 200) + $aAppPos[0] Local $iY_Start = IniRead($sIniFile, "Amount1 Cross", "Y-Coord", 100) + $aAppPos[1] ;SplashImageOn("Place the cross here", "fxddb_Splash_2.jpg", 250, 76) ; Set Amount1 cross $aRet = Move_Cross($iX_Start, $iY_Start, "fxddb_Splash_2.jpg", $UserDLL) $iX_Cross_2 = $aRet[0] $iY_Cross_2 = $aRet[1] $iCheckSum_2 = PixelChecksum($iX_Cross_2 - 1, $iY_Cross_2 - 1, $iX_Cross_2 + 1, $iY_Cross_2) ;SplashOff() ; Check for confirmation of correct positioning If $iCheckSum_1 = $iCheckSum_2 Then ExitLoop Else MsgBox(48, "fxddb Error", "The crosses were not properly positioned" & @CRLF & "Please try again") EndIf While _IsPressed("0D", $UserDLL) Sleep(10) WEnd WEnd ; Save values 1 pixel off IniWrite($sIniFile, "GMT Cross", "X-Coord", $iX_Cross_1 - $aAppPos[0] - 1) IniWrite($sIniFile, "GMT Cross", "Y-Coord", $iY_Cross_1 - $aAppPos[1] - 1) IniWrite($sIniFile, "Amount1 Cross", "X-Coord", $iX_Cross_2 - $aAppPos[0] - 1) IniWrite($sIniFile, "Amount1 Cross", "Y-Coord", $iY_Cross_2 - $aAppPos[1] - 1) ; Close dll DllClose($UserDLL) EndFunc ;==>Mark_Cross #EndRegion #Region ; ----- Move_Cross ----- Func Move_Cross($iX_Mark, $iY_Mark, $sImage, $UserDLL) Local $aRet[2] ; Determine location of example GUI $iX_Loc = $aAppPos[0] - 250 If $aAppPos[0] < 300 Then $iX_Loc = $aAppPos[0] + $aAppPos[2] $iY_Loc = $aAppPos[1] + 100 ; Create example GUI $hExampleGUI = GUICreate("Place the cross here", 250, 96, $iX_Loc, $iY_Loc, $WS_POPUPWINDOW, -1, WinGetHandle(AutoitWinGetTitle())) GUICtrlCreateLabel("Place cross on intersection in centre of circle", 0, 0, 250, 20, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, 0xFFFF00) GUICtrlCreatePic($sImage, 0, 20, 250, 76) GUISetState() ; Create transparent GUI over the app with Cross cursor $hCross_GUI = GUICreate("Test", $aAppPos[2], $aAppPos[3], $aAppPos[0], $aAppPos[1], $WS_POPUP, $WS_EX_TOPMOST) WinSetTrans($hCross_GUI, "", 8) GUISetState(@SW_SHOW, $hCross_GUI) GUISetCursor(3, 1, $hCross_GUI) MouseMove($iX_Mark, $iY_Mark, 0) ; Wait for adjustments or confirmation While 1 If _IsPressed("25", $UserDLL) Then $iX_Mark -= 1 While _IsPressed("25", $UserDLL) Sleep(10) WEnd EndIf If _IsPressed("26", $UserDLL) Then $iY_Mark -= 1 While _IsPressed("26", $UserDLL) Sleep(10) WEnd EndIf If _IsPressed("27", $UserDLL) Then While _IsPressed("27", $UserDLL) Sleep(10) WEnd $iX_Mark += 1 EndIf If _IsPressed("28", $UserDLL) Then While _IsPressed("28", $UserDLL) Sleep(10) WEnd $iY_Mark += 1 EndIf If _IsPressed("0D", $UserDLL) Then While _IsPressed("0D", $UserDLL) Sleep(10) WEnd $aRet[0] = $iX_Mark $aRet[1] = $iY_Mark GUIDelete($hCross_GUI) GUIDelete($hExampleGUI) Return $aRet EndIf MouseMove($iX_Mark, $iY_Mark) WEnd EndFunc ;==>Move_Cross #EndRegion Let me know how it works - my fingers are firmly crossed! M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Jaenchen Posted March 22, 2010 Author Share Posted March 22, 2010 Wahoo! Hello again M23 Ok, the Window get's found it reads 14 rows, GMT is correct, Curr1. there's only XPD filled from 14:18, Amount1 are all ok. I would say, that's qute a good work until here, dear M23. Unfortunately I don't play Golf but if I would have time for, I'd like to start with.. As you maybe have seen, we've got also a KPT in the Curr1 List. Does this matter as you only check the last Char? For me, K=X. Ah, yes. Can we limit the trys of positioning the + to 3 because of otherwise it ends up in a loop. Do you have any Idea why it's not recognizing the Curr1. ? Back to you. Jan ..Added new PIC containing all Curr.1 Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 22, 2010 Moderators Share Posted March 22, 2010 Jaenchen,It is not recognising the Curr.1 data because there are only 20 pixels between the cross and the third letter and not 22 as we measured last time! I will have to work on an algoritm to find the letter rather than just rely on a pixel count. Can we limit the trys of positioning the + to 3 because of otherwise it ends up in a loopOf course, but if you do not position the crosses, you do not get the results!See you tomorrow with a new version. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Jaenchen Posted March 22, 2010 Author Share Posted March 22, 2010 (edited) M23I've re-checked the Pixcels from the top left Curr.1 to the last letter and I've seen, that it's 20 now (odd) if I replace the 22 with 20 in your code, all works well, except the "KPT". Should we reduce the check to the last Char of the Curr.1 Picture? So: All my fault! Sorry for wasting your time in that case. This just as an update from my (learning) side.JanUpdate: "KPT" works with 21 all the rest with 20. So it must be depending on the first letter X or K. :-( Edited March 22, 2010 by Jaenchen Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 22, 2010 Moderators Share Posted March 22, 2010 Jaenchen,I now have a working algorithm to detect the start of the third letter (it depends on the size of the 2 previous letters ), so at least that is taken care of. What other currency abbreviations might appear in that column? I ask because at the moment I am only checking the left edge of the third letter (as that is enough to distinguish between D, G, T and U. If there are other abbreviations this might not be enough to distinguish between them and the 4 we are looking for. Do all the codes you are interested in begin with X? Is that a unique identifier? I do not want to have to identify all 26 letters, but if we have to....... M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Jaenchen Posted March 22, 2010 Author Share Posted March 22, 2010 (edited) M23What other currency abbreviations might appear in that column?There are only 2. X and K at the begining, so total max 8. :-)Jan Edited March 22, 2010 by Jaenchen Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 22, 2010 Moderators Share Posted March 22, 2010 (edited) Jaenchen, Try this script - it should return an array with the Curr.1 codes that begin with X written in full and anything else marked as "Other". Is that good enough? expandcollapse popup#Region ; ----- Includes ----- #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <StaticConstants.au3> #include <Array.au3> #include <Misc.au3> #EndRegion #Region ; ----- Get App handle ----- ; Get handle of app window $iOldMode = Opt("WinTitleMatchMode", 2) $hGUI = WinGetHandle("FX daily deal blotter") If @error Then MsgBox(16, "Disaster!", "Could not find the Window") Opt("WinTitleMatchMode", $iOldMode) #EndRegion ; ----- Find fxddb GUI ----- #Region ; ----- Determine ini path ; Determine location for ini file If @ScriptDir = @ProgramFilesDir Then ; If app in C:\Program Files need to save elsewhere If Not FileExists(@AppDataDir & "\fxddb") Then DirCreate(@AppDataDir & "\fxddb") $sIniFile = @AppDataDir & "\fxddb\fxddb.ini" Else ; Can use app folder $sIniFile = @ScriptDir & "\fxddb.ini" EndIf #EndRegion #Region ; ----- Declarations ----- ; Array of digit and sign codes Global $aChecks[12] = [ _ "011110100001100001100001100001100001100001100001100001011110", _ "000100001100010100000100000100000100000100000100000100000100", _ "011110100001000001000001000001000010000100001000010000111111", _ "011110100001000001000001001110000001000001000001100001011110", _ "000010000110000110001010001010010010010010111111000010000010", _ "011111010000010000100000111110100001000001000001100001011110", _ "011110100001100000100000101110110001100001100001100001011110", _ "111111000010000010000100000100001000001000010000010000010000", _ "011110100001100001100001011110100001100001100001100001011110", _ "011110100001100001100001100011011101000001000001100010011100", _ "000000000000000100000100000100111111000100000100000100000000", _ "000000000000000000000000000000000000000111000000000000000000"] ; Array of Curr.1 letter edges (D, G, T, U) Global $aCurr[4] = [ _ "1111111111", _ "0011111100", _ "1000000000", _ "1111111100"] ; Array to hold numbers read from app Global $aCurrArray[15][3] ; Find position of the app window Global $aAppPos = WinGetPos($hGUI) ; Coords of the 2 points user will mark Global $iX_Cross_1, $iY_Cross_1, $iX_Cross_2, $iY_Cross_2, $iX_Colon = $aAppPos[0] - 1, $iX_3Letter #EndRegion #Region ; ----- Initialisation ----- ; Get user to mark the points Mark_Cross() #EndRegion #Region ; ----- Read values ----- ; Read the numbers in GMT, Curr.1 and Amount1 columns to set the base array Read_Values() _ArrayDisplay($aCurrArray) Exit #EndRegion #Region ; ----- Read_Values ----- Func Read_Values() ; Coords of zones to check for digit/sign Local $aX_Coords_1[4] = [-15, -8, 3, 10] Local $aX_Coords_2[9] = [65, 58, 51, 47, 40, 33, 26, 15, 8] $iY_Coord = $iY_Cross_1 + 3 ; Reset array Global $aCurrArray[15][3] ; Find colon if not yet set If $iX_Colon = $aAppPos[0] - 1 Then Find_Colon() ; Move down line by line For $iY_Index = 0 To 14 $iBackgroundColour = Hex(PixelGetColor($iX_Colon - 1, $iY_Coord + ($iY_Index * 16) + 1), 6) ; Start in the GMT column ; Zero the code $sCode = "" ; Move through the digit/sign spaces from left For $iX_Index = 0 To 3 ; Move through the space to build the code $sString = "" For $y = 0 To 9 For $x = 0 To 5 $sString &= Read_Pixel($iX_Colon + $aX_Coords_1[$iX_Index] + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Next ; Check in the index for a match $iIndex = _ArraySearch($aChecks, $sString) ; Add the correct digit/sign to the list Switch $iIndex Case 0 To 9 $sCode &= $iIndex EndSwitch ; Add colon in correct place If $iX_Index = 1 Then $sCode &= ":" Next ; Check if we have reached the end of entries If $sCode = ":" Then ExitLoop ; Store the GMT $aCurrArray[$iY_Index][0] = $sCode ; Now move on to Curr.1 column ; Determine the X-Coord for the third letter $iX_3Letter = Find_Letter($iY_Coord, $iY_Index, $iBackgroundColour) ; Check if the first letter is an X If $iX_3Letter = 0 Then $aCurrArray[$iY_Index][1] = "Other" Else ; To distinguish between the possible values, we need only look at the left edge of the 3rd letter $iX_Curr = $iX_Cross_1 + $iX_3Letter ; Read the edge line $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($iX_Curr, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next ; Check in the index for a match and write to the array $iIndex = _ArraySearch($aCurr, $sString) Switch $iIndex Case 0 $aCurrArray[$iY_Index][1] = "XPD" Case 1 $aCurrArray[$iY_Index][1] = "XAG" Case 2 $aCurrArray[$iY_Index][1] = "XPT" Case 3 $aCurrArray[$iY_Index][1] = "XAU" EndSwitch EndIf ; Now move on to the Amount1 column ; Zero the code $sCode = "" ; Move through the digit/sign spaces from left For $iX_Index = 0 To 8 ; Move through the space $sString = "" For $y = 0 To 9 For $x = 0 To 5 $sString &= Read_Pixel($iX_Cross_2 - $aX_Coords_2[$iX_Index] + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Next ; Check in the index for a match $iIndex = _ArraySearch($aChecks, $sString) ; Add the correct digit/sign to the list Switch $iIndex Case 0 To 9 $sCode &= $iIndex Case 10 $sCode &= "+" Case 11 $sCode &= "-" EndSwitch If $iX_Index = 2 Then ; If we did not find a digit at the thousands point, check for a sign ; If we did, add a comma If $iIndex > 0 Then $iX_Index = 3 $sCode &= "," EndIf EndIf ; Add the decimal at the correct point If $iX_Index = 6 Then $sCode &= "." Next ; Store the Amount 1 $aCurrArray[$iY_Index][2] = $sCode Next EndFunc ;==>Read_Values #EndRegion #Region ; ----- Find_Colon ----- Func Find_Colon() ; Set Y coord $iY_Coord = $iY_Cross_1 + 3 ; Check colour of background $iBackgroundColour = Hex(PixelGetColor($iX_Cross_1 - 1, $iY_Coord), 6) ; Move across app window to find colon For $x = $iX_Cross_1 To $aAppPos[0] Step -1 $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($x, $iY_Coord + $y, $iBackgroundColour) Next ; Found it If $sString = "0001000001" Then ExitLoop Next ; Set the coordinate to the colon $iX_Colon = $x EndFunc ;==>Find_Colon #EndRegion Func Find_Letter($iY_Coord, $iY_Index, $iBackgroundColour) ; Move across app to ID first letter For $x = 2 To 10 $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($iX_Cross_1 + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Switch $sString ; If blank keep going to find start of letter Case "0000000000" ContinueLoop ; If X Then ExitLoop to find 3rd letter Case "1000000001" ExitLoop Case Else Return 0 EndSwitch Next Local $fBlank = False ; Move across app window to find third letter For $x = 15 To 30 $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($iX_Cross_1 + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Switch $fBlank Case False ; Check for blank line If $sString = "0000000000" Then $fBlank = True Case True ; Check for beginning of letter If $sString <> "0000000000" Then ExitLoop EndSwitch Next ; Set the cordinate to the left edge of the third letter Return $x EndFunc #Region ; ----- Read_ Pixel ----- Func Read_Pixel($iX_Pixel, $iY_Pixel, $iBackgroundColour) $sColour = Hex(PixelGetColor($iX_Pixel, $iY_Pixel), 6) ; If pixel colour is not the background colour - set the code If $sColour <> $iBackgroundColour Then Return "1" Else Return "0" EndIf EndFunc ;==>Read_Pixel #EndRegion #Region ; ----- Mark_Cross ----- Func Mark_Cross() ; Open dll for _IsPressed Local $UserDLL = DllOpen("user32.dll") For $i = 1 To 3 ; Read ini values for GMT cross intial position Local $iX_Start = IniRead($sIniFile, "GMT Cross", "X-Coord", 45) + $aAppPos[0] Local $iY_Start = IniRead($sIniFile, "GMT Cross", "Y-Coord", 100) + $aAppPos[1] ; Set GMT cross $aRet = Move_Cross($iX_Start, $iY_Start, "fxddb_Splash_1.jpg", $UserDLL) $iX_Cross_1 = $aRet[0] $iY_Cross_1 = $aRet[1] $iCheckSum_1 = PixelChecksum($iX_Cross_1 - 1, $iY_Cross_1 - 1, $iX_Cross_1 + 1, $iY_Cross_1) ; Read ini values for Amount1 cross intial position Local $iX_Start = IniRead($sIniFile, "Amount1 Cross", "X-Coord", 200) + $aAppPos[0] Local $iY_Start = IniRead($sIniFile, "Amount1 Cross", "Y-Coord", 100) + $aAppPos[1] ; Set Amount1 cross $aRet = Move_Cross($iX_Start, $iY_Start, "fxddb_Splash_2.jpg", $UserDLL) $iX_Cross_2 = $aRet[0] $iY_Cross_2 = $aRet[1] $iCheckSum_2 = PixelChecksum($iX_Cross_2 - 1, $iY_Cross_2 - 1, $iX_Cross_2 + 1, $iY_Cross_2) ; Check for confirmation of correct positioning If $iY_Cross_1 <> $iY_Start And $iY_Cross_1 = $iY_Cross_2 Then ; Save values 1 pixel off IniWrite($sIniFile, "GMT Cross", "X-Coord", $iX_Cross_1 - $aAppPos[0] - 1) IniWrite($sIniFile, "GMT Cross", "Y-Coord", $iY_Cross_1 - $aAppPos[1] - 1) IniWrite($sIniFile, "Amount1 Cross", "X-Coord", $iX_Cross_2 - $aAppPos[0] - 1) IniWrite($sIniFile, "Amount1 Cross", "Y-Coord", $iY_Cross_2 - $aAppPos[1] - 1) ; Close dll DllClose($UserDLL) Return Else If $i = 3 Then MsgBox(48, "fxddb Error", "If you do not want to set me up properly then I am not going to play!") Exit Else MsgBox(48, "fxddb Error", "The crosses were not properly positioned" & @CRLF & "Please try again") EndIf EndIf While _IsPressed("0D", $UserDLL) Sleep(10) WEnd Next EndFunc ;==>Mark_Cross #EndRegion #Region ; ----- Move_Cross ----- Func Move_Cross($iX_Mark, $iY_Mark, $sImage, $UserDLL) Local $aRet[2] ; Determine location of example GUI $iX_Loc = $aAppPos[0] - 250 If $aAppPos[0] < 300 Then $iX_Loc = $aAppPos[0] + $aAppPos[2] $iY_Loc = $aAppPos[1] + 100 ; Create example GUI $hExampleGUI = GUICreate("Place the cross here", 250, 96, $iX_Loc, $iY_Loc, $WS_POPUPWINDOW, -1, WinGetHandle(AutoitWinGetTitle())) GUICtrlCreateLabel("Place cross on intersection in centre of circle", 0, 0, 250, 20, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, 0xFFFF00) GUICtrlCreatePic($sImage, 0, 20, 250, 76) GUISetState() ; Create transparent GUI over the app with Cross cursor $hCross_GUI = GUICreate("Test", $aAppPos[2], $aAppPos[3], $aAppPos[0], $aAppPos[1], $WS_POPUP, $WS_EX_TOPMOST) WinSetTrans($hCross_GUI, "", 8) GUISetState(@SW_SHOW, $hCross_GUI) GUISetCursor(3, 1, $hCross_GUI) MouseMove($iX_Mark, $iY_Mark, 0) ; Wait for adjustments or confirmation While 1 If _IsPressed("25", $UserDLL) Then $iX_Mark -= 1 While _IsPressed("25", $UserDLL) Sleep(10) WEnd EndIf If _IsPressed("26", $UserDLL) Then $iY_Mark -= 1 While _IsPressed("26", $UserDLL) Sleep(10) WEnd EndIf If _IsPressed("27", $UserDLL) Then While _IsPressed("27", $UserDLL) Sleep(10) WEnd $iX_Mark += 1 EndIf If _IsPressed("28", $UserDLL) Then While _IsPressed("28", $UserDLL) Sleep(10) WEnd $iY_Mark += 1 EndIf If _IsPressed("0D", $UserDLL) Then While _IsPressed("0D", $UserDLL) Sleep(10) WEnd $aRet[0] = $iX_Mark $aRet[1] = $iY_Mark GUIDelete($hCross_GUI) GUIDelete($hExampleGUI) Return $aRet EndIf MouseMove($iX_Mark, $iY_Mark) WEnd EndFunc ;==>Move_Cross #EndRegion M23 Edit: Typnig! Edited March 22, 2010 by Melba23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Jaenchen Posted March 22, 2010 Author Share Posted March 22, 2010 M23, Thanks for the fixes. Yes, this would work. In that case, the messagebox then could be "NEW ROW in FX-Dealblotter" But if we want to make it perfect, then the tool should maybe figure out X or K at the begining and then start from if X, then 20 else 19 and we would get the correct Curr.1 too. What do you think? Jan Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 22, 2010 Moderators Share Posted March 22, 2010 (edited) Jaenchen,No need for 19 or 20 - the script is now much cleverer than that. It will find the actual edge of the first and third letters - no matter where in the column. Detecting X or K as the first letter of the Curr.1 code is easy - but I am now confused (not uncommon ) about what exactly you want. Is this correct?- You want "BUY/SELL" messageboxes if the Curr.1 code is XPD, XAG, APT or XAU and the limits you mentioned earlier are exceeded.- You want a "NEW ENTRY" messagebox if any other Curr.1 code arrives in the app.- What happens if one of the "X" codes arrives and does NOT exceed the limits? Do you want any kind of alert when that happens? It is really easy to produce a "NEW ENTRY" messagebox. That is all simple to code - just let me know if I am right tomorrow M23Edit: A few changes above and.....There are only 2. X and K at the begining, so total max 8I missed this earlier. Does this mean we are looking at XPD, XAG, APT, XAU, KPD, KAG, KPT and KAU as the only options in the Curr.1 column? I do hope so as it simplifies things enormously! Edited March 22, 2010 by Melba23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Jaenchen Posted March 23, 2010 Author Share Posted March 23, 2010 I missed this earlier. Does this mean we are looking at XPD, XAG, APT, XAU, KPD, KAG, KPT and KAU as the only options in the Curr.1 column? I do hope so as it simplifies things enormously! Hi M23Yes, that means exactly we're looking (checking exceeding amounts) for - XAU, XAG, XPD, XPT (this is representing Ouces)- KAU, KAG, KPD, KPT (this is representing Kilogram)Sorry (again) for not beeing that clear. Fouuuuuuur!!!!!! or Foooooooor!!!!! :-)back to you.jan Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2010 Moderators Share Posted March 23, 2010 Jaenchen,Good Morning,Ok final (I hope!) questions:- You imply you have limits for the K codes as well? If so, what are they?- Would you like the possibilty to adjust these limits as and when necessary? It is trivial to do this and it would save you having to rewrite the code if the limits change.- If the trade does not meet or exceed the limit you want a simple notification alert. Otherwise a BUY/SELL alert. Correct?Once you give me answers to these questios I believe we are very close to the solution. I am off to the gym now - I will be back after lunch.M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Jaenchen Posted March 23, 2010 Author Share Posted March 23, 2010 (edited) - You imply you have limits for the K codes as well? If so, what are they?- Would you like the possibilty to adjust these limits as and when necessary? It is trivial to do this and it would save you having to rewrite the code if the limits change.- If the trade does not meet or exceed the limit you want a simple notification alert. Otherwise a BUY/SELL alert. Correct?M23,Good question(s)! I hope, I can now provide the final Answers too - Yes but the Values coming with K could be multiplyed with 32.1507425 so we're getting the Ounces and could check against them. For sure it would be useful to have a nice GUI to maintain the limits so we (yes you!) wouldn't have to rewrite the code all the timeI suggest a gui like Monitor: ON/OFF LIMITS: Oz / KG XAU 1000 / 30 XAG 25000 / 777 XPT 1000 / 30 XPD 1000 / 30- No messagebox/action at all if a trade don't exceed the limitHave fun at the gym, I should do some too, the summer is close! Enjoy your salad(!?!) Jan Edited March 23, 2010 by Jaenchen Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2010 Moderators Share Posted March 23, 2010 Jaenchen, Feeling very virtuous after my exercise , I return to offer what I hope is a pretty definitive version to be run on your app. When you first run the script, you will be asked to insert the transaction limit values you require (I know you told me what they are, but you need to get them into the ini file ). Then the crosses are placed as usual and - I hope - you will be alerted whenever a transaction passes the limit (you might want to set some artificially low limits initially to check this). The code: expandcollapse popup#region ; ----- Includes ----- #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <StaticConstants.au3> #include <Array.au3> #include <Misc.au3> #endregion ; ----- Includes ----- ; ############# fxddb ############# ; ; Reading from the FX daily deal blotter ; ; Initial release ; ; Script Version: 1.0.0.0 ; As at 23 Mar 10 ; #region ; ----- Get App handle ----- ; Get handle of app window Global $iOldMode = Opt("WinTitleMatchMode", 2) Global $hGUI = WinGetHandle("FX daily deal blotter") If @error Then MsgBox(16, "fxddb Disaster!", "Cannot find the window!") Exit EndIf Opt("WinTitleMatchMode", $iOldMode) #endregion ; ----- Get App handle ----- #region ; ----- HotKey Exit ----- ; Set exit strategy HotKeySet("{ESC}", "On_Exit") #endregion ; ----- HotKey Exit ----- #region ; ----- Declarations ----- ; Array of digit and sign codes Global $aChecks[12] = [ _ "011110100001100001100001100001100001100001100001100001011110", _ "000100001100010100000100000100000100000100000100000100000100", _ "011110100001000001000001000001000010000100001000010000111111", _ "011110100001000001000001001110000001000001000001100001011110", _ "000010000110000110001010001010010010010010111111000010000010", _ "011111010000010000100000111110100001000001000001100001011110", _ "011110100001100000100000101110110001100001100001100001011110", _ "111111000010000010000100000100001000001000010000010000010000", _ "011110100001100001100001011110100001100001100001100001011110", _ "011110100001100001100001100011011101000001000001100010011100", _ "000000000000000100000100000100111111000100000100000100000000", _ "000000000000000000000000000000000000000111000000000000000000"] ; Array of Curr.1 letter edges (D, G, T, U) Global $aCurr[4] = [ _ "1111111111", _ "0011111100", _ "1000000000", _ "1111111100"] ; Array to hold numbers read from app Global $aCurrArray[15][3], $aOldArray[15][3] ; Find position of the app window Global $aAppPos = WinGetPos($hGUI) ; Coords of the 2 points user will mark Global $iX_Cross_1, $iY_Cross_1, $iX_Cross_2, $iY_Cross_2, $iX_Colon = $aAppPos[0] - 1, $iX_3Letter ; Checksum of top line Global $iChecksum ; Conversion from kilos to ounces Global $nConvFactor = 32.1507425 #endregion ; ----- Declarations ----- #region ; ----- Determine ini path Global $sIniFile ; Determine location for ini file If @ScriptDir = @ProgramFilesDir Then ; If app in C:\Program Files need to save elsewhere If Not FileExists(@AppDataDir & "\fxddb") Then DirCreate(@AppDataDir & "\fxddb") $sIniFile = @AppDataDir & "\fxddb\fxddb.ini" Else ; Can use app folder $sIniFile = @ScriptDir & "\fxddb.ini" EndIf IniReadSection($sIniFile, "Limits") If @error Then MsgBox(48, "fxddb Alert", "No transaction limits haver been set" & @CRLF & "Please set them now") On_Limits() EndIf #endregion ; ----- Determine ini path #region ; ----- Tray menu ----- Opt("TrayOnEventMode", 1) ; Use event trapping for tray menu Opt("TrayMenuMode", 3) ; Default tray menu items will not be shown. ; Create tray menu TrayCreateItem("Set Limits") TrayItemSetOnEvent(-1, "On_Limits") TrayCreateItem("") TrayCreateItem("About") TrayItemSetOnEvent(-1, "On_About") TrayCreateItem("") TrayCreateItem("Exit") TrayItemSetOnEvent(-1, "On_Exit") #endregion ; ----- Tray menu ----- #region ; ----- Initialisation ----- ; Get user to mark the points Mark_Cross() ; Read the numbers in GMT, Curr.1 and Amount1 columns to set the base array Read_Values() $aOldArray = $aCurrArray ; Set the original checksum for the top line Global $iCurrChecksum = PixelChecksum($aAppPos[0], $iY_Cross_1 + 3, $aAppPos[0] + $aAppPos[2], $iY_Cross_1 + 13) #endregion ; ----- Initialisation ----- #region ; ----- Main loop ----- ; Now start infinite loop While 1 ; Check if the top line has changed $iChecksum = PixelChecksum($aAppPos[0], $iY_Cross_1 + 3, $aAppPos[0] + $aAppPos[2], $iY_Cross_1 + 13) If $iChecksum <> $iCurrChecksum Then ; Retain new checksum for future checks $iCurrChecksum = $iChecksum ; Read the values in GMT, Curr.1 and Amount1 columns Read_Values() ; Check the new values and send any necessary alerts Check_Values() ; All warnings sent so replace $aOldArray $aOldArray = $aCurrArray EndIf ; Idle 10 Secs before relooping Sleep(10000) WEnd ; ~~~~~ Functions ~~~~~ #endregion ; ----- Main loop ----- #region ; ----- Read_Values ----- Func Read_Values() ; Coords of zones to check for digit/sign Local $aX_Coords_1[4] = [-15, -8, 3, 10] Local $aX_Coords_2[9] = [65, 58, 51, 47, 40, 33, 26, 15, 8] Local $iY_Coord = $iY_Cross_1 + 3 ; Reset array Global $aCurrArray[15][3] ; Find colon if not yet set If $iX_Colon = $aAppPos[0] - 1 Then Find_Colon() ; Move down line by line For $iY_Index = 0 To 14 Local $iBackgroundColour = Hex(PixelGetColor($iX_Colon - 1, $iY_Coord + ($iY_Index * 16) + 1), 6) ; Start in the GMT column ; Zero the code Local $sCode = "" ; Move through the digit/sign spaces from left For $iX_Index = 0 To 3 ; Move through the space to build the code Local $sString = "" For $y = 0 To 9 For $x = 0 To 5 $sString &= Read_Pixel($iX_Colon + $aX_Coords_1[$iX_Index] + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Next ; Check in the index for a match Local $iIndex = _ArraySearch($aChecks, $sString) ; Add the correct digit/sign to the list Switch $iIndex Case 0 To 9 $sCode &= $iIndex EndSwitch ; Add colon in correct place If $iX_Index = 1 Then $sCode &= ":" Next ; Check if we have reached the end of entries If $sCode = ":" Then ExitLoop ; Store the GMT $aCurrArray[$iY_Index][0] = $sCode ; Now move on to Curr.1 column ; Determine the first letter and the X-Coord for the third letter Local $aLetters = Find_Letters($iY_Coord, $iY_Index, $iBackgroundColour) $iX_3Letter = $aLetters[1] ; To distinguish between the possible values, we need only look at the left edge of the 3rd letter Local $iX_Curr = $iX_Cross_1 + $iX_3Letter ; Read the edge line $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($iX_Curr, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next ; Check in the index for a match and write to the array $iIndex = _ArraySearch($aCurr, $sString) Switch $iIndex Case 0 $aCurrArray[$iY_Index][1] = $aLetters[0] & "PD" Case 1 $aCurrArray[$iY_Index][1] = $aLetters[0] & "AG" Case 2 $aCurrArray[$iY_Index][1] = $aLetters[0] & "PT" Case 3 $aCurrArray[$iY_Index][1] = $aLetters[0] & "AU" EndSwitch ; Now move on to the Amount1 column ; Zero the code $sCode = "" ; Move through the digit/sign spaces from left For $iX_Index = 0 To 8 ; Move through the space $sString = "" For $y = 0 To 9 For $x = 0 To 5 $sString &= Read_Pixel($iX_Cross_2 - $aX_Coords_2[$iX_Index] + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Next ; Check in the index for a match $iIndex = _ArraySearch($aChecks, $sString) ; Add the correct digit/sign to the list Switch $iIndex Case 0 To 9 $sCode &= $iIndex Case 10 $sCode &= "+" Case 11 $sCode &= "-" EndSwitch If $iX_Index = 2 Then ; If we did not find a digit at the thousands point, check for a sign ; If we did, add a comma If $iIndex > 0 Then $iX_Index = 3 $sCode &= "," EndIf EndIf ; Add the decimal at the correct point If $iX_Index = 6 Then $sCode &= "." Next ; Store the Amount 1 $aCurrArray[$iY_Index][2] = $sCode Next EndFunc ;==>Read_Values #endregion ; ----- Read_Values ----- #region ; ----- Find_Colon ----- Func Find_Colon() ; Set Y coord Local $iY_Coord = $iY_Cross_1 + 3 ; Check colour of background Local $iBackgroundColour = Hex(PixelGetColor($iX_Cross_1 - 1, $iY_Coord), 6) ; Move across app window to find colon For $x = $iX_Cross_1 To $aAppPos[0] Step -1 Local $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($x, $iY_Coord + $y, $iBackgroundColour) Next ; Found it If $sString = "0001000001" Then ExitLoop Next ; Set the coordinate to the colon $iX_Colon = $x EndFunc ;==>Find_Colon #endregion ; ----- Find_Colon ----- #region ; ----- Find Letter ----- Func Find_Letters($iY_Coord, $iY_Index, $iBackgroundColour) ; Move across app to ID first letter Local $aRet[2] For $x = 2 To 10 Local $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($iX_Cross_1 + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Switch $sString ; If blank keep going to find start of letter Case "0000000000" ContinueLoop ; If X Then ExitLoop to find 3rd letter Case "1000000001" $aRet[0] = "X" ExitLoop Case Else $aRet[0] = "K" ExitLoop EndSwitch Next Local $fBlank = False ; Move across app window to find third letter For $x = 15 To 30 $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($iX_Cross_1 + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Switch $fBlank Case False ; Check for blank line If $sString = "0000000000" Then $fBlank = True Case True ; Check for beginning of letter If $sString <> "0000000000" Then ExitLoop EndSwitch Next ; We now have the cordinate to the left edge of the third letter $aRet[1] = $x Return $aRet EndFunc ;==>Find_Letters #endregion ; ----- Find Letter ----- #region ; ----- Read_ Pixel ----- Func Read_Pixel($iX_Pixel, $iY_Pixel, $iBackgroundColour) Local $sColour = Hex(PixelGetColor($iX_Pixel, $iY_Pixel), 6) ; If pixel colour is not the background colour - set the code If $sColour <> $iBackgroundColour Then Return "1" Else Return "0" EndIf EndFunc ;==>Read_Pixel #endregion ; ----- Read_ Pixel ----- #region ; ----- Mark_Cross ----- Func Mark_Cross() ; Open dll for _IsPressed Local $UserDLL = DllOpen("user32.dll") For $i = 1 To 3 ; Read ini values for GMT cross intial position Local $iX_Start = IniRead($sIniFile, "GMT Cross", "X-Coord", 45) + $aAppPos[0] Local $iY_Start = IniRead($sIniFile, "GMT Cross", "Y-Coord", 100) + $aAppPos[1] ; Set GMT cross Local $aRet = Move_Cross($iX_Start, $iY_Start, "fxddb_Splash_1.jpg", $UserDLL) $iX_Cross_1 = $aRet[0] $iY_Cross_1 = $aRet[1] Local $iCheckSum_1 = PixelChecksum($iX_Cross_1 - 1, $iY_Cross_1 - 1, $iX_Cross_1 + 1, $iY_Cross_1) ConsoleWrite("CheckSum 1: " & $iCheckSum_1 & @CRLF) ; Read ini values for Amount1 cross intial position $iX_Start = IniRead($sIniFile, "Amount1 Cross", "X-Coord", 200) + $aAppPos[0] $iY_Start = IniRead($sIniFile, "Amount1 Cross", "Y-Coord", 100) + $aAppPos[1] ; Set Amount1 cross $aRet = Move_Cross($iX_Start, $iY_Start, "fxddb_Splash_2.jpg", $UserDLL) $iX_Cross_2 = $aRet[0] $iY_Cross_2 = $aRet[1] Local $iCheckSum_2 = PixelChecksum($iX_Cross_2 - 1, $iY_Cross_2 - 1, $iX_Cross_2 + 1, $iY_Cross_2) ConsoleWrite("CheckSum 2: " & $iCheckSum_2 & @CRLF) ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; Check for confirmation of correct positioning If $iY_Cross_1 <> $iY_Start And $iY_Cross_1 = $iY_Cross_2 Then ; Save values 1 pixel off IniWrite($sIniFile, "GMT Cross", "X-Coord", $iX_Cross_1 - $aAppPos[0] - 1) IniWrite($sIniFile, "GMT Cross", "Y-Coord", $iY_Cross_1 - $aAppPos[1] - 1) IniWrite($sIniFile, "Amount1 Cross", "X-Coord", $iX_Cross_2 - $aAppPos[0] - 1) IniWrite($sIniFile, "Amount1 Cross", "Y-Coord", $iY_Cross_2 - $aAppPos[1] - 1) ; Close dll DllClose($UserDLL) Return Else If $i = 3 Then MsgBox(16, "fxddb Error", "If you do not want to set me up properly then I am not going to play!") Exit Else MsgBox(48, "fxddb Error", "The crosses were not properly positioned" & @CRLF & "Please try again") EndIf EndIf While _IsPressed("0D", $UserDLL) Sleep(10) WEnd Next EndFunc ;==>Mark_Cross #endregion ; ----- Mark_Cross ----- #region ; ----- Move_Cross ----- Func Move_Cross($iX_Mark, $iY_Mark, $sImage, $UserDLL) Local $aRet[2] ; Determine location of example GUI Local $iX_Loc = $aAppPos[0] - 250 If $aAppPos[0] < 300 Then $iX_Loc = $aAppPos[0] + $aAppPos[2] Local $iY_Loc = $aAppPos[1] + 100 ; Create example GUI Local $hExampleGUI = GUICreate("Place the cross here", 250, 96, $iX_Loc, $iY_Loc, $WS_POPUPWINDOW, -1, WinGetHandle(AutoItWinGetTitle())) GUICtrlCreateLabel("Place cross on intersection in centre of circle", 0, 0, 250, 20, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, 0xFFFF00) GUICtrlCreatePic($sImage, 0, 20, 250, 76) GUISetState() ; Create transparent GUI over the app with Cross cursor Local $hCross_GUI = GUICreate("Test", $aAppPos[2], $aAppPos[3], $aAppPos[0], $aAppPos[1], $WS_POPUP, $WS_EX_TOPMOST) WinSetTrans($hCross_GUI, "", 8) GUISetState(@SW_SHOW, $hCross_GUI) GUISetCursor(3, 1, $hCross_GUI) MouseMove($iX_Mark, $iY_Mark, 0) ; Wait for adjustments or confirmation While 1 If _IsPressed("25", $UserDLL) Then $iX_Mark -= 1 While _IsPressed("25", $UserDLL) Sleep(10) WEnd EndIf If _IsPressed("26", $UserDLL) Then $iY_Mark -= 1 While _IsPressed("26", $UserDLL) Sleep(10) WEnd EndIf If _IsPressed("27", $UserDLL) Then While _IsPressed("27", $UserDLL) Sleep(10) WEnd $iX_Mark += 1 EndIf If _IsPressed("28", $UserDLL) Then While _IsPressed("28", $UserDLL) Sleep(10) WEnd $iY_Mark += 1 EndIf If _IsPressed("0D", $UserDLL) Then While _IsPressed("0D", $UserDLL) Sleep(10) WEnd $aRet[0] = $iX_Mark $aRet[1] = $iY_Mark GUIDelete($hCross_GUI) GUIDelete($hExampleGUI) Return $aRet EndIf MouseMove($iX_Mark, $iY_Mark) WEnd EndFunc ;==>Move_Cross #endregion ; ----- Move_Cross ----- #region ; ----- Check values ----- Func Check_Values() Local $iThreshold For $i = 0 To 14 Local $sNewLine = $aCurrArray[$i][0] & $aCurrArray[$i][1] & $aCurrArray[$i][2] Local $sOldTopLine = $aOldArray[0][0] & $aOldArray[0][1] & $aOldArray[0][2] If $sNewLine <> $sOldTopLine Then ; New line so get code If $aCurrArray[$i][1] = "Other" Then Show_Alert("ALERT", $i, 0x80FF80) Else Local $nNumber = Number(StringReplace($aCurrArray[$i][2], ",", "")) ; Convert to ounces if necessary If StringLeft($aCurrArray[$i][1], 1) = "K" Then $nNumber *= $nConvFactor ; Set Threshold value Switch StringRight($aCurrArray[$i][1], 2) Case "AG" $iThreshold = IniRead($sIniFile, "Limits", "AG", "Error") Case "AU" $iThreshold = IniRead($sIniFile, "Limits", "AU", "Error") Case "PD" $iThreshold = IniRead($sIniFile, "Limits", "PD", "Error") Case "PT" $iThreshold = IniRead($sIniFile, "Limits", "PT", "Error") EndSwitch ; Check we have valid limits If $iThreshold = "Error" Then MsgBox(16, "fxddb Error", "Limits are invalid" & @CRLF & "Please reset the limit values and restart!") On_Limits() Exit EndIf ; Check if limit exceeded If Abs($nNumber) >= $iThreshold Then Local $sAction = "BUY" Local $iColour = 0xFF8000 If StringLeft($aCurrArray[$i][2], 1) = "-" Then $sAction = "SELL" $iColour = 0xFFFF00 EndIf Show_Alert($sAction, $i, $iColour) EndIf EndIf Else ; We have reached the top line of the last array so stop checking ExitLoop EndIf Next EndFunc ;==>Check_Values #endregion ; ----- Check values ----- #region ; ----- Show_Alert ----- Func Show_Alert($sAction, $iIndex, $iColour) ; Create Alert GUI Local $hAlert = GUICreate("New Trade at " & $aCurrArray[$iIndex][0], 500, 160, Default, Default, BitOR($WS_POPUPWINDOW, $WS_CAPTION), $WS_EX_TOPMOST, WinGetHandle(AutoItWinGetTitle())) GUISetBkColor($iColour, $hAlert) GUICtrlCreateLabel("", 10, 10, 480, 100, $SS_CENTER) GUICtrlSetBkColor(-1, $iColour) GUICtrlSetFont(-1, 24) GUICtrlSetData(-1, "NEW TRADE" & @CRLF & "YOU " & $sAction & " " & $aCurrArray[$iIndex][1] & " : " & $aCurrArray[$iIndex][2]) Local $hButton = GUICtrlCreateButton("OK", 210, 120, 80, 30, $BS_DEFPUSHBUTTON) GUISetState() Beep(500, 500) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE, $hButton GUIDelete($hAlert) Return EndSwitch WEnd EndFunc ;==>Show_Alert #endregion ; ----- Show_Alert ----- #region ; ----- On Limits ----- Func On_Limits() Local $aLimits[4][3] ; Read current limits $aLimits[0][1] = IniRead($sIniFile, "Limits", "AG", "Not Set") $aLimits[1][1] = IniRead($sIniFile, "Limits", "AU", "Not Set") $aLimits[2][1] = IniRead($sIniFile, "Limits", "PD", "Not Set") $aLimits[3][1] = IniRead($sIniFile, "Limits", "PT", "Not Set") ; Create GUI Local $hLimits = GUICreate("Set Limits", 220, 190) GUICtrlCreateLabel("Metal" & @TAB & "Ounces" & @TAB & @TAB & "Kilos", 10, 10, 280, 20) GUICtrlCreateLabel("AG", 10, 30, 30, 20) GUICtrlCreateLabel("AU", 10, 60, 30, 20) GUICtrlCreateLabel("PD", 10, 90, 30, 20) GUICtrlCreateLabel("PT", 10, 120, 30, 20) ; Create inputs $aLimits[0][0] = GUICtrlCreateInput($aLimits[0][1], 50, 30, 70, 20) $aLimits[1][0] = GUICtrlCreateInput($aLimits[1][1], 50, 60, 70, 20) $aLimits[2][0] = GUICtrlCreateInput($aLimits[2][1], 50, 90, 70, 20) $aLimits[3][0] = GUICtrlCreateInput($aLimits[3][1], 50, 120, 70, 20) ; Show kilo equivalents For $i = 0 To 3 If $aLimits[$i][1] = "Not Set" Then $aLimits[$i][2] = GUICtrlCreateLabel("Not Set", 130, 30 * ($i + 1), 70, 20) Else $aLimits[$i][2] = GUICtrlCreateLabel(Round($aLimits[$i][0] / $nConvFactor, 7), 130, 30 * ($i + 1), 70, 20) EndIf Next Local $hAccept_Button = GUICtrlCreateButton("Accept", 130, 150, 80, 30) Local $hCancel_Button = GUICtrlCreateButton("Cancel", 10, 150, 80, 30) GUISetState(@SW_SHOW, $hLimits) While 1 Switch GUIGetMsg() Case $hAccept_Button ; Read required limits For $i = 0 To 3 $aLimits[$i][1] = GUICtrlRead($aLimits[$i][0]) Next ; Write limits to ini file IniWrite($sIniFile, "Limits", "AG", $aLimits[0][1]) IniWrite($sIniFile, "Limits", "AU", $aLimits[1][1]) IniWrite($sIniFile, "Limits", "PD", $aLimits[2][1]) IniWrite($sIniFile, "Limits", "PT", $aLimits[3][1]) ContinueCase Case $GUI_EVENT_CLOSE, $hCancel_Button GUIDelete($hLimits) Return EndSwitch ; Keep kilo values synchronised with ounce inputs For $i = 0 To 3 Local $nKVal = Round(GUICtrlRead($aLimits[$i][0]) / $nConvFactor, 7) If GUICtrlRead($aLimits[$i][2]) <> $nKVal Then GUICtrlSetData($aLimits[$i][2], $nKVal) Next WEnd EndFunc ;==>On_Limits #endregion ; ----- On Limits ----- #region ; ----- On_About ----- Func On_About() Local $sMsg = "fxddb v1.0" & @CRLF & "(c) Melba23 UK 2010" & @CRLF & @CRLF & _ "This software is released as Freeware. It is provided 'as-is', without any express or implied warranty. " & _ "In no event shall the author be held liable for any damages arising from the use of this software." & @CRLF & @CRLF & _ "fxddb built using AutoIt v" & @AutoItVersion & @CRLF & "(www.autoitscript.com/autoit3)" MsgBox(64, "About fxddb", $sMsg) EndFunc ;==>On_About #endregion ; ----- On_About ----- #region ; ----- On_Exit ----- Func On_Exit() Exit EndFunc ;==>On_Exit #endregion ; ----- On_Exit ----- Let me know how it goes. M23 P.S. PD = palladium? Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Jaenchen Posted March 23, 2010 Author Share Posted March 23, 2010 Feeling very virtuous after my exercise P.S. PD = palladium?Houh! You must have done Pilates or something similar or you've just done too much of sport. What did you do? A Marathon? Yes PD = Palladium 461.50 / 463.50 $ per Oz at the mom.Thanks for the final code. Good thing with the Kilo limit calculations! also the ability to amend them at the statusbar.With the "About" I'm happy to see your name in there and the statement you've made inthere. Will test the code now and let you know as soon there's a new line droping in. At the mom it's spinning..Some question: What happens if - I accidently move the appwindow of the FX Dealblotter during the code is running? ==> Reset of the + needed?- another Window from a different app temporarily (5 seconds / 20 Seconds hides the dealblotter (partially/full)? ==>does it get stale?- is it possible for autoIt so set the FxDealblotter Appwindow = allwaysOnTopI hope you're feeling already better after your 4h of gymWill Keep you updated.1'000'0000 and more Thanks.Jan Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2010 Moderators Share Posted March 23, 2010 Jaenchen,4hrs = trip to gym + gym + lunch + trip home + coding the required changes to the script. Gym itself is about 90 minutes of that - and that is quite long enough at my age! Some question: What happens if - I accidently move the appwindow of the FX Dealblotter during the code is running? ==> Reset of the + needed?- another Window from a different app temporarily (5 seconds / 20 Seconds hides the dealblotter (partially/full)? ==>does it get stale?- is it possible for autoIt so set the FxDealblotter Appwindow = allwaysOnTop- At present the script will fail, but it is trivial to fix that. - The script checks for updates every 10 secs. If it cannot read the window it will probably fail at present - I assumed you would not want to cover the window. I will have a think about what we can do to get over that.- We can certainly try, but some windows are resistant to this. I will think over these points while I am waiting for you tell me if the script works in the wild. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Jaenchen Posted March 23, 2010 Author Share Posted March 23, 2010 (edited) M23 I'll make it short: IT WORKS! Yeah! YOU ARE ABSOLUTELY GREAT! 4 Shure I'll make a donnation to the hosting costs of AutoIt (of course out of my personal pocket) and will do lobbying as much I can. What do you think? Can you make the errorcatching for the "accidently moving" window. The rest I think, the user can live with. Especially if we have 3 Users running all your script, so the chance it quite low that it fails 3 times at the same time on 3 diff workstations. Take a break, relax! You've done a very good work! Also in the documentation/commention of the code. That's real professional work! You deserve my respectful! Jan Edited: Just found out, that we should have the abortion of the app put to something else than {ESC} maybe {CTRL}+{ESC} otherwise it may exit accidently Edited March 23, 2010 by Jaenchen Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 23, 2010 Moderators Share Posted March 23, 2010 Jaenchen, I am really pleased to hear that! it has been a fun project! Here is a new version which can cope with being hidden (it just sulks in the corner ) and being moved (it relocates the app window each time it tries to read it). Of course, you get no updates while the app is hidden. expandcollapse popup#region ; ----- Includes ----- #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <StaticConstants.au3> #include <Array.au3> #include <Misc.au3> #include <WinAPI.au3> #endregion ; ----- Includes ----- ; ############# fxddb ############# ; ; Reading from the FX daily deal blotter ; ; Initial release ; ; Script Version: 1.0.0.0 ; As at 23 Mar 10 ; #region ; ----- Get App handle ----- ; Get handle of app window Global $iOldMode = Opt("WinTitleMatchMode", 2) Global $hGUI = WinGetHandle("FX daily deal blotter") If @error Then MsgBox(16, "fxddb Disaster!", "Cannot find the window!") Exit EndIf Opt("WinTitleMatchMode", $iOldMode) #endregion ; ----- Get App handle ----- #region ; ----- Declarations ----- ; Array of digit and sign codes Global $aChecks[12] = [ _ "011110100001100001100001100001100001100001100001100001011110", _ "000100001100010100000100000100000100000100000100000100000100", _ "011110100001000001000001000001000010000100001000010000111111", _ "011110100001000001000001001110000001000001000001100001011110", _ "000010000110000110001010001010010010010010111111000010000010", _ "011111010000010000100000111110100001000001000001100001011110", _ "011110100001100000100000101110110001100001100001100001011110", _ "111111000010000010000100000100001000001000010000010000010000", _ "011110100001100001100001011110100001100001100001100001011110", _ "011110100001100001100001100011011101000001000001100010011100", _ "000000000000000100000100000100111111000100000100000100000000", _ "000000000000000000000000000000000000000111000000000000000000"] ; Array of Curr.1 letter edges (D, G, T, U) Global $aCurr[4] = [ _ "1111111111", _ "0011111100", _ "1000000000", _ "1111111100"] ; Array to hold numbers read from app Global $aCurrArray[15][3], $aOldArray[15][3] ; Find position of the app window Global $aAppPos = WinGetPos($hGUI) ; Coords of the 2 points user will mark Global $iX_Cross_1, $iY_Cross_1, $iX_Cross_2, $iY_Cross_2, $iX_Colon = -1, $iX_3Letter ; Checksum of top line Global $iChecksum ; Struct for window visible check Global $tPOINT = DllStructCreate("int X;int Y") ; Conversion from kilos to ounces Global $nConvFactor = 32.1507425 #endregion ; ----- Declarations ----- #region ; ----- Determine ini path Global $sIniFile ; Determine location for ini file If @ScriptDir = @ProgramFilesDir Then ; If app in C:\Program Files need to save elsewhere If Not FileExists(@AppDataDir & "\fxddb") Then DirCreate(@AppDataDir & "\fxddb") $sIniFile = @AppDataDir & "\fxddb\fxddb.ini" Else ; Can use app folder $sIniFile = @ScriptDir & "\fxddb.ini" EndIf IniReadSection($sIniFile, "Limits") If @error Then MsgBox(48, "fxddb Alert", "No transaction limits have been set" & @CRLF & "Please set them now") On_Limits() EndIf #endregion ; ----- Determine ini path #region ; ----- Tray menu ----- Opt("TrayOnEventMode", 1) ; Use event trapping for tray menu Opt("TrayMenuMode", 3) ; Default tray menu items will not be shown. ; Create tray menu TrayCreateItem("Set Limits") TrayItemSetOnEvent(-1, "On_Limits") TrayCreateItem("") TrayCreateItem("About") TrayItemSetOnEvent(-1, "On_About") TrayCreateItem("") TrayCreateItem("Exit") TrayItemSetOnEvent(-1, "On_Exit") #endregion ; ----- Tray menu ----- #region ; ----- Initialisation ----- ; Get user to mark the points Mark_Cross() ; Get base window handle DllStructSetData($tPOINT, "X", $aAppPos[0] + $iX_Cross_1) DllStructSetData($tPOINT, "Y", $aAppPos[1] + $iY_Cross_1) $hHandle = _WinAPI_WindowFromPoint($tPOINT) ; Read the numbers in GMT, Curr.1 and Amount1 columns to set the base array Read_Values() $aOldArray = $aCurrArray ; Set the original checksum for the top line Global $iCurrChecksum = PixelChecksum($aAppPos[0], $iY_Cross_1 + 3, $aAppPos[0] + $aAppPos[2], $iY_Cross_1 + 13) #endregion ; ----- Initialisation ----- #region ; ----- Main loop ----- ; Now start infinite loop While 1 ; Check position of the app $aAppPos = WinGetPos($hGUI) ; Check if app is visible DllStructSetData($tPOINT, "X", $aAppPos[0] + $iX_Cross_1) DllStructSetData($tPOINT, "Y", $aAppPos[1] + $iY_Cross_1) If _WinAPI_WindowFromPoint($tPOINT) = $hHandle Then ; Check if the top line has changed $iChecksum = PixelChecksum($aAppPos[0], $aAppPos[1] + $iY_Cross_1 + 3, $aAppPos[0] + $aAppPos[2], $aAppPos[1] + $iY_Cross_1 + 13) If $iChecksum <> $iCurrChecksum Then ; Retain new checksum for future checks $iCurrChecksum = $iChecksum ; Read the values in GMT, Curr.1 and Amount1 columns Read_Values() ; Check the new values and send any necessary alerts Check_Values() ; All warnings sent so replace $aOldArray $aOldArray = $aCurrArray EndIf EndIf ; Idle 10 Secs before relooping Sleep(10000) WEnd ; ~~~~~ Functions ~~~~~ #endregion ; ----- Main loop ----- #region ; ----- Read_Values ----- Func Read_Values() ; Coords of zones to check for digit/sign Local $aX_Coords_1[4] = [-15, -8, 3, 10] Local $aX_Coords_2[9] = [65, 58, 51, 47, 40, 33, 26, 15, 8] Local $iY_Coord = $aAppPos[1] + $iY_Cross_1 + 3 ; Reset array Global $aCurrArray[15][3] ; Find colon if not yet set If $iX_Colon = -1 Then Find_Colon($iY_Coord) ; Move down line by line For $iY_Index = 0 To 14 Local $iBackgroundColour = Hex(PixelGetColor($aAppPos[0] + $iX_Cross_1 - 1, $iY_Coord + ($iY_Index * 16) + 1), 6) ; Start in the GMT column ; Zero the code Local $sCode = "" ; Set the x-coord for this column Local $iX_Coord = $aAppPos[0] + $iX_Colon ; Move through the digit/sign spaces from left For $iX_Index = 0 To 3 ; Move through the space to build the code Local $sString = "" For $y = 0 To 9 For $x = 0 To 5 $sString &= Read_Pixel($iX_Coord + $aX_Coords_1[$iX_Index] + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Next ; Check in the index for a match Local $iIndex = _ArraySearch($aChecks, $sString) ; Add the correct digit/sign to the list Switch $iIndex Case 0 To 9 $sCode &= $iIndex EndSwitch ; Add colon in correct place If $iX_Index = 1 Then $sCode &= ":" Next ; Check if we have reached the end of entries If $sCode = ":" Then ExitLoop ; Store the GMT $aCurrArray[$iY_Index][0] = $sCode ; Now move on to Curr.1 column ; Determine the first letter and the X-Coord for the third letter Local $aLetters = Find_Letters($iY_Coord, $iY_Index, $iBackgroundColour) $iX_3Letter = $aLetters[1] ; To distinguish between the possible values, we need only look at the left edge of the 3rd letter Local $iX_Curr = $aAppPos[0] + $iX_Cross_1 + $iX_3Letter ; Read the edge line $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($iX_Curr, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next ; Check in the index for a match and write to the array $iIndex = _ArraySearch($aCurr, $sString) Switch $iIndex Case 0 $aCurrArray[$iY_Index][1] = $aLetters[0] & "PD" Case 1 $aCurrArray[$iY_Index][1] = $aLetters[0] & "AG" Case 2 $aCurrArray[$iY_Index][1] = $aLetters[0] & "PT" Case 3 $aCurrArray[$iY_Index][1] = $aLetters[0] & "AU" EndSwitch ; Now move on to the Amount1 column ; Set base x-coord $iX_Coord = $aAppPos[0] + $iX_Cross_2 ; Zero the code $sCode = "" ; Move through the digit/sign spaces from left For $iX_Index = 0 To 8 ; Move through the space $sString = "" For $y = 0 To 9 For $x = 0 To 5 $sString &= Read_Pixel($iX_Coord - $aX_Coords_2[$iX_Index] + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Next ; Check in the index for a match $iIndex = _ArraySearch($aChecks, $sString) ; Add the correct digit/sign to the list Switch $iIndex Case 0 To 9 $sCode &= $iIndex Case 10 $sCode &= "+" Case 11 $sCode &= "-" EndSwitch If $iX_Index = 2 Then ; If we did not find a digit at the thousands point, check for a sign ; If we did, add a comma If $iIndex > 0 Then $iX_Index = 3 $sCode &= "," EndIf EndIf ; Add the decimal at the correct point If $iX_Index = 6 Then $sCode &= "." Next ; Store the Amount 1 $aCurrArray[$iY_Index][2] = $sCode Next EndFunc ;==>Read_Values #endregion ; ----- Read_Values ----- #region ; ----- Find_Colon ----- Func Find_Colon($iY_Coord) ; Check colour of background Local $iBackgroundColour = Hex(PixelGetColor($aAppPos[0] + $iX_Cross_1 - 1, $iY_Coord), 6) ; Move across app window to find colon For $x = $aAppPos[0] + $iX_Cross_1 To $aAppPos[0] Step -1 Local $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($x, $iY_Coord + $y, $iBackgroundColour) Next ; Found it If $sString = "0001000001" Then ExitLoop Next ; Set the coordinate to the colon $iX_Colon = $x - $aAppPos[0] EndFunc ;==>Find_Colon #endregion ; ----- Find_Colon ----- #region ; ----- Find Letter ----- Func Find_Letters($iY_Coord, $iY_Index, $iBackgroundColour) ; Move across app to ID first letter Local $aRet[2] For $x = 2 To 10 Local $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($aAppPos[0] + $iX_Cross_1 + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Switch $sString ; If blank keep going to find start of letter Case "0000000000" ContinueLoop ; If X Then ExitLoop to find 3rd letter Case "1000000001" $aRet[0] = "X" ExitLoop Case Else $aRet[0] = "K" ExitLoop EndSwitch Next Local $fBlank = False ; Move across app window to find third letter For $x = 15 To 30 $sString = "" For $y = 0 To 9 $sString &= Read_Pixel($aAppPos[0] + $iX_Cross_1 + $x, $iY_Coord + ($iY_Index * 16) + $y, $iBackgroundColour) Next Switch $fBlank Case False ; Check for blank line If $sString = "0000000000" Then $fBlank = True Case True ; Check for beginning of letter If $sString <> "0000000000" Then ExitLoop EndSwitch Next ; We now have the cordinate to the left edge of the third letter $aRet[1] = $x Return $aRet EndFunc ;==>Find_Letters #endregion ; ----- Find Letter ----- #region ; ----- Read_ Pixel ----- Func Read_Pixel($iX_Pixel, $iY_Pixel, $iBackgroundColour) Local $sColour = Hex(PixelGetColor($iX_Pixel, $iY_Pixel), 6) ; If pixel colour is not the background colour - set the code If $sColour <> $iBackgroundColour Then Return "1" Else Return "0" EndIf EndFunc ;==>Read_Pixel #endregion ; ----- Read_ Pixel ----- #region ; ----- Mark_Cross ----- Func Mark_Cross() ; Open dll for _IsPressed Local $UserDLL = DllOpen("user32.dll") For $i = 1 To 3 ; Read ini values for GMT cross intial position Local $iX_Start = IniRead($sIniFile, "GMT Cross", "X-Coord", 45) + $aAppPos[0] Local $iY_Start = IniRead($sIniFile, "GMT Cross", "Y-Coord", 100) + $aAppPos[1] ; Set GMT cross Local $aRet = Move_Cross($iX_Start, $iY_Start, "fxddb_Splash_1.jpg", $UserDLL) $iX_Cross_1 = $aRet[0] $iY_Cross_1 = $aRet[1] Local $iCheckSum_1 = PixelChecksum($iX_Cross_1 - 1, $iY_Cross_1 - 1, $iX_Cross_1 + 1, $iY_Cross_1) ; Read ini values for Amount1 cross intial position $iX_Start = IniRead($sIniFile, "Amount1 Cross", "X-Coord", 200) + $aAppPos[0] $iY_Start = IniRead($sIniFile, "Amount1 Cross", "Y-Coord", 100) + $aAppPos[1] ; Set Amount1 cross $aRet = Move_Cross($iX_Start, $iY_Start, "fxddb_Splash_2.jpg", $UserDLL) $iX_Cross_2 = $aRet[0] $iY_Cross_2 = $aRet[1] Local $iCheckSum_2 = PixelChecksum($iX_Cross_2 - 1, $iY_Cross_2 - 1, $iX_Cross_2 + 1, $iY_Cross_2) ; Check for confirmation of correct positioning If $iY_Cross_1 <> $iY_Start And $iY_Cross_1 = $iY_Cross_2 Then ; Set coords relative to the app window $iX_Cross_1 -= $aAppPos[0] $iY_Cross_1 -= $aAppPos[1] $iX_Cross_2 -= $aAppPos[0] $iY_Cross_2 -= $aAppPos[1] ; Save values 1 pixel off IniWrite($sIniFile, "GMT Cross", "X-Coord", $iX_Cross_1 - 1) IniWrite($sIniFile, "GMT Cross", "Y-Coord", $iY_Cross_1 - 1) IniWrite($sIniFile, "Amount1 Cross", "X-Coord", $iX_Cross_2 - 1) IniWrite($sIniFile, "Amount1 Cross", "Y-Coord", $iY_Cross_2 - 1) ; Close dll DllClose($UserDLL) Return Else If $i = 3 Then MsgBox(16, "fxddb Error", "If you do not want to set me up properly then I am not going to play!") Exit Else MsgBox(48, "fxddb Error", "The crosses were not properly positioned" & @CRLF & "Please try again") EndIf EndIf While _IsPressed("0D", $UserDLL) Sleep(10) WEnd Next EndFunc ;==>Mark_Cross #endregion ; ----- Mark_Cross ----- #region ; ----- Move_Cross ----- Func Move_Cross($iX_Mark, $iY_Mark, $sImage, $UserDLL) Local $aRet[2] ; Determine location of example GUI Local $iX_Loc = $aAppPos[0] - 250 If $aAppPos[0] < 300 Then $iX_Loc = $aAppPos[0] + $aAppPos[2] Local $iY_Loc = $aAppPos[1] + 100 ; Create example GUI Local $hExampleGUI = GUICreate("Place the cross here", 250, 96, $iX_Loc, $iY_Loc, $WS_POPUPWINDOW, -1, WinGetHandle(AutoItWinGetTitle())) GUICtrlCreateLabel("Place cross on intersection in centre of circle", 0, 0, 250, 20, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, 0xFFFF00) GUICtrlCreatePic($sImage, 0, 20, 250, 76) GUISetState() ; Create transparent GUI over the app with Cross cursor Local $hCross_GUI = GUICreate("Test", $aAppPos[2], $aAppPos[3], $aAppPos[0], $aAppPos[1], $WS_POPUP, $WS_EX_TOPMOST) WinSetTrans($hCross_GUI, "", 8) GUISetState(@SW_SHOW, $hCross_GUI) GUISetCursor(3, 1, $hCross_GUI) MouseMove($iX_Mark, $iY_Mark, 0) ; Wait for adjustments or confirmation While 1 If _IsPressed("25", $UserDLL) Then $iX_Mark -= 1 While _IsPressed("25", $UserDLL) Sleep(10) WEnd EndIf If _IsPressed("26", $UserDLL) Then $iY_Mark -= 1 While _IsPressed("26", $UserDLL) Sleep(10) WEnd EndIf If _IsPressed("27", $UserDLL) Then While _IsPressed("27", $UserDLL) Sleep(10) WEnd $iX_Mark += 1 EndIf If _IsPressed("28", $UserDLL) Then While _IsPressed("28", $UserDLL) Sleep(10) WEnd $iY_Mark += 1 EndIf If _IsPressed("0D", $UserDLL) Then While _IsPressed("0D", $UserDLL) Sleep(10) WEnd $aRet[0] = $iX_Mark $aRet[1] = $iY_Mark GUIDelete($hCross_GUI) GUIDelete($hExampleGUI) Return $aRet EndIf MouseMove($iX_Mark, $iY_Mark) WEnd EndFunc ;==>Move_Cross #endregion ; ----- Move_Cross ----- #region ; ----- Check values ----- Func Check_Values() Local $iThreshold For $i = 0 To 14 Local $sNewLine = $aCurrArray[$i][0] & $aCurrArray[$i][1] & $aCurrArray[$i][2] Local $sOldTopLine = $aOldArray[0][0] & $aOldArray[0][1] & $aOldArray[0][2] If $sNewLine <> $sOldTopLine Then ; New line so get code If $aCurrArray[$i][1] = "Other" Then Show_Alert("ALERT", $i, 0x80FF80) Else Local $nNumber = Number(StringReplace($aCurrArray[$i][2], ",", "")) ; Convert to ounces if necessary If StringLeft($aCurrArray[$i][1], 1) = "K" Then $nNumber *= $nConvFactor ; Set Threshold value Switch StringRight($aCurrArray[$i][1], 2) Case "AG" $iThreshold = IniRead($sIniFile, "Limits", "AG", "Error") Case "AU" $iThreshold = IniRead($sIniFile, "Limits", "AU", "Error") Case "PD" $iThreshold = IniRead($sIniFile, "Limits", "PD", "Error") Case "PT" $iThreshold = IniRead($sIniFile, "Limits", "PT", "Error") EndSwitch ; Check we have valid limits If $iThreshold = "Error" Then MsgBox(16, "fxddb Error", "Limits are invalid" & @CRLF & "Please reset the limit values and restart!") On_Limits() Exit EndIf ; Check if limit exceeded If Abs($nNumber) >= $iThreshold Then Local $sAction = "BUY" Local $iColour = 0xFF8000 If StringLeft($aCurrArray[$i][2], 1) = "-" Then $sAction = "SELL" $iColour = 0xFFFF00 EndIf Show_Alert($sAction, $i, $iColour) EndIf EndIf Else ; We have reached the top line of the last array so stop checking ExitLoop EndIf Next EndFunc ;==>Check_Values #endregion ; ----- Check values ----- #region ; ----- Show_Alert ----- Func Show_Alert($sAction, $iIndex, $iColour) ; Create Alert GUI Local $hAlert = GUICreate("New Trade at " & $aCurrArray[$iIndex][0], 500, 160, Default, Default, BitOR($WS_POPUPWINDOW, $WS_CAPTION), $WS_EX_TOPMOST, WinGetHandle(AutoItWinGetTitle())) GUISetBkColor($iColour, $hAlert) GUICtrlCreateLabel("", 10, 10, 480, 100, $SS_CENTER) GUICtrlSetBkColor(-1, $iColour) GUICtrlSetFont(-1, 24) GUICtrlSetData(-1, "NEW TRADE" & @CRLF & "YOU " & $sAction & " " & $aCurrArray[$iIndex][1] & " : " & $aCurrArray[$iIndex][2]) Local $hButton = GUICtrlCreateButton("OK", 210, 120, 80, 30, $BS_DEFPUSHBUTTON) GUISetState() Beep(500, 500) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE, $hButton GUIDelete($hAlert) Return EndSwitch WEnd EndFunc ;==>Show_Alert #endregion ; ----- Show_Alert ----- #region ; ----- On Limits ----- Func On_Limits() Local $aLimits[4][3] ; Read current limits $aLimits[0][1] = IniRead($sIniFile, "Limits", "AG", "Not Set") $aLimits[1][1] = IniRead($sIniFile, "Limits", "AU", "Not Set") $aLimits[2][1] = IniRead($sIniFile, "Limits", "PD", "Not Set") $aLimits[3][1] = IniRead($sIniFile, "Limits", "PT", "Not Set") ; Create GUI Local $hLimits = GUICreate("Set Limits", 220, 190) GUICtrlCreateLabel("Metal" & @TAB & "Ounces" & @TAB & @TAB & "Kilos", 10, 10, 280, 20) GUICtrlCreateLabel("AG", 10, 30, 30, 20) GUICtrlCreateLabel("AU", 10, 60, 30, 20) GUICtrlCreateLabel("PD", 10, 90, 30, 20) GUICtrlCreateLabel("PT", 10, 120, 30, 20) ; Create inputs $aLimits[0][0] = GUICtrlCreateInput($aLimits[0][1], 50, 30, 70, 20) $aLimits[1][0] = GUICtrlCreateInput($aLimits[1][1], 50, 60, 70, 20) $aLimits[2][0] = GUICtrlCreateInput($aLimits[2][1], 50, 90, 70, 20) $aLimits[3][0] = GUICtrlCreateInput($aLimits[3][1], 50, 120, 70, 20) ; Show kilo equivalents For $i = 0 To 3 If $aLimits[$i][1] = "Not Set" Then $aLimits[$i][2] = GUICtrlCreateLabel("Not Set", 130, 30 * ($i + 1), 70, 20) Else $aLimits[$i][2] = GUICtrlCreateLabel(Round($aLimits[$i][0] / $nConvFactor, 7), 130, 30 * ($i + 1), 70, 20) EndIf Next Local $hAccept_Button = GUICtrlCreateButton("Accept", 130, 150, 80, 30) Local $hCancel_Button = GUICtrlCreateButton("Cancel", 10, 150, 80, 30) GUISetState(@SW_SHOW, $hLimits) While 1 Switch GUIGetMsg() Case $hAccept_Button ; Read required limits For $i = 0 To 3 $aLimits[$i][1] = GUICtrlRead($aLimits[$i][0]) Next ; Write limits to ini file IniWrite($sIniFile, "Limits", "AG", $aLimits[0][1]) IniWrite($sIniFile, "Limits", "AU", $aLimits[1][1]) IniWrite($sIniFile, "Limits", "PD", $aLimits[2][1]) IniWrite($sIniFile, "Limits", "PT", $aLimits[3][1]) ContinueCase Case $GUI_EVENT_CLOSE, $hCancel_Button GUIDelete($hLimits) Return EndSwitch ; Keep kilo values synchronised with ounce inputs For $i = 0 To 3 Local $nKVal = Round(GUICtrlRead($aLimits[$i][0]) / $nConvFactor, 7) If GUICtrlRead($aLimits[$i][2]) <> $nKVal Then GUICtrlSetData($aLimits[$i][2], $nKVal) Next WEnd EndFunc ;==>On_Limits #endregion ; ----- On Limits ----- #region ; ----- On_About ----- Func On_About() Local $sMsg = "fxddb v1.0" & @CRLF & "(c) Melba23 UK 2010" & @CRLF & @CRLF & _ "This software is released as Freeware. It is provided 'as-is', without any express or implied warranty. " & _ "In no event shall the author be held liable for any damages arising from the use of this software." & @CRLF & @CRLF & _ "fxddb built using AutoIt v" & @AutoItVersion & @CRLF & "(www.autoitscript.com/autoit3)" MsgBox(64, "About fxddb", $sMsg) EndFunc ;==>On_About #endregion ; ----- On_About ----- #region ; ----- On_Exit ----- Func On_Exit() Exit EndFunc ;==>On_Exit #endregion ; ----- On_Exit ----- I have removed the HotKey to exit - Windows uses too many Modifier+Esc key combinations already and we have the tray icon menu to exit gracefully now. Now, would you be interested in the single compiled exe version with the example images stored inside? It would not be difficult to do - just let me know. I'll make a donnation to the hosting costs of AutoItThat is extremely generous and I am sure Jon (the owner and original author of AutoIt) woudl be most grateful. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
Jaenchen Posted March 23, 2010 Author Share Posted March 23, 2010 Now, would you be interested in the single compiled exe version with the example images stored inside? It would not be difficult to do - just let me know.That is extremely generous and I am sure Jon (the owner and original author of AutoIt) woudl be most grateful. Of course I'm interested to learn on how to compile it to a single exe containing also the images stored in it.You are verry welcome! And of course just let me know if I can help you with anything else (except "DATA DVDs") Have a great evening!Jan Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now