/////////////////////////////////////////////////////// // // SaherElm IT Center XTest MQL5 Expert Advisor // ------------------------------------------------- // Name: XBackTester // Description: a Backtest Tools Strategy Tester // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // //////////////////////////////////////////////////////x // // Global Properties ... #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm XBackTester" #property strict // #define ShortName "XBackTester" // // Imports ... #include "../Classes/x-saherelm.x-alert.class.mq5" #include "../Classes/x-saherelm.x-chart.helper.class.mq5" #include "../Classes/x-saherelm.x-trade.class.mq5" // // Import Chart Objects ... #include #include #include #include #include #include #include #include #include #include #include // // Definitions ... // // Inputs ... // // Common ... input group "Common"; input long eaMagicNumber = 78692110; // Magic Number input int eaSlippage = 10; // Slippgae input string eaLogSuffix = ""; // Log Suffix // // Alert ... // Here we Provider All Requirements for // Configuring Alert Provider ... input group "Alert"; input bool eAEnableAlerts = true; // Enable Alerts input bool eALogAlerts = true; // Log Alerts input bool eAMailAlerts = false; // Mail Alerts input bool eAPushAlerts = false; // Push Alerts input bool eATerminalAlerts = false; // Terminal Alerts // // Define Local Variables ... // string eaLogTag; // EA Log Prefix ... XCAlert *eaAlert; // Alert Provider for Expert Adviser ... XCTrade *eaTrader; // Trader of Expert Adviser ... XCChartHelper *mChartHelper; // Chart Helper Class ... // // Object Props ... // string objSuffix; // CButton btnBuy; CButton btnSell; CButton btnClose; CButton btnCloseAll; // CEdit lblPositionId; // CButton *btnSelectedPosInfo; CArrayObj selectedPosInfoArr; // int btnCloseSizeX = 0; int btnCloseSizeY = 0; int btnCloseStartX = 0; int btnCloseStartY = 0; int lblPositionIdSizeX = 0; int lblPositionIdSizeY = 0; int lblPositionIdStartX = 0; int lblPositionIdStartY = 0; // ulong selectedPositionID = 0; // // Position Arrays ... CArrayObj posArray; // // Event Handlers ... // // Initialization ... int OnInit() { // // Validate Inputs and Required Parameters // for EA to Works fine ... if (!ValidateInputs()) { return INIT_PARAMETERS_INCORRECT; } // // Initialize Timer ... if (!InitTimer()) { return INIT_FAILED; } // // Initialize all Requirements ... if (!InitEA()) { return INIT_FAILED; } // // Initialize all GUI Objects and Classes ... if (!InitGUI()) { return INIT_FAILED; } // // Alert Initialization ... string msg = "Initialized Successfully ..."; eaAlert.SendAlert(msg); // // Init Succeed ... return INIT_SUCCEEDED; } // // DeInitialization ... void OnDeinit(const int reason) { // // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function // REASON_REMOVE 1 Program removed from a chart // REASON_RECOMPILE 2 Program recompiled // REASON_CHARTCHANGE 3 A symbol or a chart period is changed // REASON_CHARTCLOSE 4 Chart closed // REASON_PARAMETERS 5 Inputs changed by a user // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings // REASON_TEMPLATE 7 Another chart template applied // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value // REASON_CLOSE 9 Terminal closed // // Destroy Timer ... DestroyTimer(); // // Destroy all GUI Requirements ... DestroyGUI(); // // Alert De Initialization Succeeded ... string msg = "De Initialized Successfully ..."; eaAlert.SendAlert(msg); // // Destroy all EA Requirements ... DestroyEA(); } // // On Tick Handler ... void OnTick() { // UpdateGUI(); } // // Handle On Trade Event ... void OnTrade() { // eaTrader.HandleOnTrade(); } // // On Timer ... void OnTimer() { // // TODO: Implement Time Based Functionalities ... } // // Chart Event Handler ... void OnChartEvent( const int id, const long &lparam, const double &dparam, const string &sparam // ) { } // // Custom Functions ... /** * Validate all Inputs of Expert Adviser ... * * @return ( bool ) */ bool ValidateInputs() { // bool result = false; // string errMessage = ""; // bool isCommonValid = ( // eaSlippage > 0 && eaMagicNumber > 0 // ); if (!isCommonValid) { // errMessage += "common configurations error;" + "\n"; } // result = // // Common ... isCommonValid && // // Otere ... true // ; // if (!result) { // // Since here Logger not Initiallized, we Use Raw Print Command ... Print(ShortName + " Errors: \n", errMessage); } // return result; } /** * Initialize Timer ... * * @return ( bool ) */ bool InitTimer() { // bool result = false; // // TODO: Initialize Timer if necessary ... // result = EventSetTimer(1); // result = EventSetMillisecondTimer(100); result = true; // return result; } /** * Destroy Timer ... */ void DestroyTimer() { // // TODO: Use This ... // EventKillTimer(); } /** * Initialize all Requirements for Working Fine ... * * @return ( bool ) */ bool InitEA() { // bool result = false; // // Locally Apply Changes on Prefix ... eaLogTag = ShortName + ">" + eaLogSuffix; // // Create Instance of Alert Class and Configure it ... eaAlert = new XCAlert(); eaAlert.SetPrefix(eaLogTag); eaAlert.SetLogAlerts(eALogAlerts); eaAlert.SetMailAlerts(eAMailAlerts); eaAlert.SetPushAlerts(eAPushAlerts); eaAlert.SetEnableAlerts(eAEnableAlerts); eaAlert.SetTerminalAlerts(eATerminalAlerts); // // Create Trader Instance and Configure it ... eaTrader = new XCTrade( eaSlippage, eaMagicNumber // ); // // Attach Event Handlers ... eaTrader.AddOnDealsChangedEventHandler(OnDealsChanged); eaTrader.AddOnStopLossEventHandler(OnStopLossTriggered); eaTrader.AddOnOrdersChangedEventHandler(OnOrdersChanged); eaTrader.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); eaTrader.AddOnModifyPositionEventHandler(OnPositionModified); eaTrader.AddOnPositionsChangedEventHandler(OnPositionsChanged); eaTrader.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); eaTrader.AddOnForceClosePositionEventHandler(OnPositionForceClosed); eaTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); // // TODO: Fix This ... result = true; // return result; } /** * Destroy all Initialized EA Requirements ... */ void DestroyEA() { // delete eaAlert; } // // GUI Events ... /** * Initialize all GUI Requirements for EA ... * * @return ( bool ) */ bool InitGUI() { // bool result = false; // int subWindow = 0; ulong chartId = ChartID(); objSuffix = ShortName + "_"; // // Initial Chart Class Instance ... mChartHelper = new XCChartHelper(chartId); // int startX = 5; int startY = 25; // int defaultGap = 5; int defaultWidth = 100; int defaultHeight = 30; // // Buy ... int btnBuyStartX = startX; int btnBuySizeX = startX + defaultWidth; int btnBuyStartY = startY; int btnBuySizeY = startY + defaultHeight; string btnBuyName = objSuffix + "BTN_BUY"; result = btnBuy.Create( chartId, btnBuyName, subWindow, btnBuyStartX, btnBuyStartY, btnBuySizeX, btnBuySizeY // ); if (result) { // // Apply Buy Button Style ... // btnBuy.Text("Buy"); btnBuy.Color(clrYellow); btnBuy.ColorBackground(clrGreen); } // // Sell ... int btnSellStartX = btnBuyStartX + btnBuySizeX; int btnSellSizeX = btnSellStartX + defaultWidth; int btnSellStartY = btnBuyStartY; int btnSellSizeY = btnBuySizeY; string btnSellName = objSuffix + "BTN_SELL"; result = btnSell.Create( chartId, btnSellName, subWindow, btnSellStartX, btnSellStartY, btnSellSizeX, btnSellSizeY // ); if (result) { // // Apply Sell Button Style ... // btnSell.Text("Sell"); btnSell.Color(clrYellow); btnSell.ColorBackground(clrDarkRed); } // // LABEL Position ID ... lblPositionIdStartX = btnBuyStartX; lblPositionIdSizeX = lblPositionIdStartX + defaultWidth; lblPositionIdStartY = btnSellSizeY + defaultGap; lblPositionIdSizeY = lblPositionIdStartY + defaultHeight; string lblPositionIdName = objSuffix + "LBL_POS_ID"; result = lblPositionId.Create( chartId, lblPositionIdName, subWindow, lblPositionIdStartX, lblPositionIdStartY, lblPositionIdSizeX, lblPositionIdSizeY // ); if (result) { // // Apply Label Position ID Style ... lblPositionId.ReadOnly(true); lblPositionId.Text("Pos ID: "); lblPositionId.Color(clrYellow); lblPositionId.ColorBackground(clrDarkGray); } // // Close ... btnCloseStartX = startX; btnCloseSizeX = btnCloseStartX + defaultWidth; btnCloseStartY = lblPositionIdSizeY + defaultGap; btnCloseSizeY = lblPositionIdSizeY + defaultHeight; string btnCloseName = objSuffix + "BTN_CLOSE"; result = btnClose.Create( chartId, btnCloseName, subWindow, btnCloseStartX, btnCloseStartY, btnCloseSizeX, btnCloseSizeY // ); if (result) { // // Apply Close Button Style ... // btnClose.Text("Close"); btnClose.Color(clrYellow); btnClose.ColorBackground(clrDarkOrange); } // // Close All ... int btnCloseAllStartX = btnCloseSizeX + defaultGap; int btnCloseAllSizeX = btnCloseAllStartX + defaultWidth; int btnCloseAllStartY = lblPositionIdSizeY + defaultGap; int btnCloseAllSizeY = lblPositionIdSizeY + defaultHeight; string btnCloseAllName = objSuffix + "BTN_CLOSE_ALL"; result = btnCloseAll.Create( chartId, btnCloseAllName, subWindow, btnCloseAllStartX, btnCloseAllStartY, btnCloseAllSizeX, btnCloseAllSizeY // ); if (result) { // // Apply Close Button Style ... // btnCloseAll.Text("Close All"); btnCloseAll.Color(clrYellow); btnCloseAll.ColorBackground(clrDarkRed); } // UpdateGUIState(); // return result; } /** * Update GUI based on Each Ticks ... */ void UpdateGUI() { // UpdateGUIState(); // // Buy Button Pressed ... if (btnBuy.Pressed()) { // HandleBuyTrade(); btnBuy.Pressed(false); } // // Sell Button Pressed ... if (btnSell.Pressed()) { // HandleSellTrade(); btnSell.Pressed(false); } // // Close Button Pressed ... if (btnClose.Pressed()) { // if (btnClose.IsEnabled()) { // if (selectedPositionID > 0) { HandleCloseTrade(selectedPositionID); } } // btnClose.Pressed(false); } // // Close All Button Pressed ... if (btnCloseAll.Pressed()) { // if (btnCloseAll.IsEnabled()) { HandleCloseTrade(0); } // btnCloseAll.Pressed(false); } // // Check Show Hide Selected Position Info ... if (btnSelectedPosInfo != NULL) { // if (btnSelectedPosInfo.Pressed()) { // // Check Enable ... if (btnSelectedPosInfo.IsEnabled()) { // // Handle Toggle Show/Hide lblSelectedPositionInfo ... CEdit *iLbl = NULL; bool isVisible = false; int count = selectedPosInfoArr.Total(); if (IsValidSize(count)) { // // Loop Through Labels ... for (int i = 0; i < count; i++) { // iLbl = (CEdit *)selectedPosInfoArr.At(i); isVisible = iLbl.IsVisible(); if (isVisible) { iLbl.Hide(); } else { iLbl.Show(); } } // // Update Button Text ... isVisible = iLbl.IsVisible(); string btnText = isVisible ? "Hide Info" : "Show Info"; btnSelectedPosInfo.Text(btnText); } // ZeroMemory(iLbl); } // btnSelectedPosInfo.Pressed(false); } } // // Check Positions Buttons ... int posCount = posArray.Total(); bool has = IsValidSize(posCount); if (has) { // for (int i = 0; i < posCount; i++) { // CButton *iBtn = (CButton *)posArray.At(i); // if (iBtn.Pressed()) { // if (iBtn.IsEnabled()) { // ulong posID = ExtractPositionIDFromButtonName(iBtn.Name()); if (posID > 0 && selectedPositionID != posID) { selectedPositionID = posID; UpdateGUIState(); } } // iBtn.Pressed(false); } // ZeroMemory(iBtn); } } } /** * Destroy all Initialized GUi Requirements ... */ void DestroyGUI() { // delete mChartHelper; ZeroMemory(mChartHelper); // delete btnSelectedPosInfo; ZeroMemory(btnSelectedPosInfo); } // // Trade Event Handlers ... /** * Handle StopLoss Triggered Positions ... * * @param deal: XDeal instance ... */ void OnStopLossTriggered(const XDeal &deal) { // UpdatePositionButtons(); } /** * Handle Take Profit Triggered Positions ... * * @param deal: XDeal instance ... */ void OnTakeProfitTriggered(const XDeal &deal) { // UpdatePositionButtons(); } /** * Handle Force Close a Position ... * * @param ticket: ULONG ... * @param position: XPosition instance ... * @param comment: String ... */ void OnPositionForceClosed( const ulong ticket, const XPosition &position, const string comment // ) { // UpdatePositionButtons(); } /** * Handle Deals Changes ... * * @param count: Integer, Number of Changes ... */ void OnDealsChanged(int count) { } /** * Handle Orders Changes ... * * @param count: Integer, Number of Changes ... */ void OnOrdersChanged(int count) { } /** * Handle Positions Changes ... * * @param count: Integer, Number of Changes ... */ void OnPositionsChanged(int count) { // // Update Position Buttons ... UpdatePositionButtons(); } /** * Handle Position Modified ... * * @param ticket: ulong, Position Ticket ... * @param profit: double, Position Profit ... * @param comment: string, Comment ... */ void OnPositionModified( const ulong ticket, const double profit, const string comment // ) { } /** * Handle Position Partial Closed ... * * @param ticket: ulong, Position Ticket ... * @param profit: double, Position Profit ... * @param comment: string, Comment ... */ void OnPositionPartialClosed( const ulong ticket, const double profit, const string comment // ) { } /** * Handle Trade State Changed ... * * @param state: XOnTradeHandlerState instance ... */ void OnTradeStateChanged(const XOnTradeHandlerState &state) { } // // GUI Event Handlers and Helpers ... // void HandleBuyTrade() { HandleTrade(X_DIRECTION_BULLISH); } // void HandleSellTrade() { HandleTrade(X_DIRECTION_BEARISH); } // void HandleTrade(ENUM_X_DIRECTION dir) { // if (!HasDirection(dir)) { return; } // string symbol = mChartHelper.Symbol(); ENUM_TIMEFRAMES period = mChartHelper.Period(); // bool isBullish = IsSpecifiedBullish(dir); // double r2r = 1.5; double volume = 0.01; double riskInPoints = 100; double point = GetPoints(symbol); double entry = GetEntry(symbol, dir); // double risk = riskInPoints * point; double reward = risk * r2r; // double sl = isBullish ? entry - risk : entry + risk; double tp = isBullish ? entry + reward : entry - reward; // string comment = ShortName + "_POS_" + ToXString(dir); // if (isBullish) { // eaTrader.Buy( symbol, period, volume, entry, sl, tp, comment // ); } else { // eaTrader.Sell( symbol, period, volume, entry, sl, tp, comment // ); } } // void HandleCloseTrade(ulong positionID) { // if (positionID == 0) { // XPosition positions[]; int count = eaTrader.GetPositions( positions // ); bool has = IsValidSize(count); if (has) { // int closedCount = eaTrader.Close(positions); has = IsValidSize(closedCount); } } else { // XPosition position; bool has = eaTrader.GetPosition( positionID, position // ); if (has) { // has = eaTrader.Close(positionID); } } } // ulong ExtractPositionIDFromButtonName(string name) { // ulong result = 0; // string nameParts[]; int namePartsCount = SplitContent(nameParts, name, "_"); bool has = IsValidSize(namePartsCount); if (has) { // string lastPart = nameParts[namePartsCount - 1]; StringReplace(lastPart, "_", ""); result = (long)lastPart; } // ZeroMemory(nameParts); // return result; } // void UpdatePositionButtons() { // // Retrieve Positions ... XPosition positions[]; int count = eaTrader.GetPositions( positions // ); bool has = IsValidSize(count); if (!has) { // posArray.Clear(); selectedPositionID = 0; UpdateGUIState(); return; } // posArray.Clear(); // // Selected Position ID ... bool isSelectdPositionIDExists = false; if (has && selectedPositionID > 0) { // for (int i = 0; i < count; i++) { // if (!isSelectdPositionIDExists && positions[i].ticket == selectedPositionID) { // isSelectdPositionIDExists = true; break; } } } if (!isSelectdPositionIDExists || selectedPositionID == 0) { // XPosition youngest; int youngestIDX = GetXYoungest(youngest, positions); bool hasYoungest = IsValidIndex(youngestIDX) && youngest.IsValid(); if (hasYoungest) { selectedPositionID = youngest.ticket; } // youngest.Clean(); } // int subWindow = 0; ulong chartId = mChartHelper.ChartId(); // int btnWidth = 25; // int lastX = lblPositionIdSizeX + 5; int lastSizeX = lastX + btnWidth; // int lastY = lblPositionIdStartY; int lastSizeY = lblPositionIdSizeY; // for (int i = 0; i < count; i++) { // XPosition iPos = positions[i]; // string posTypeStr = IsLong(iPos.type) ? "LONG" : "SHORT"; // int iPosBtnX = lastX; int iPosBtnSizeX = iPosBtnX + btnWidth; string iPosBtnName = objSuffix + "_" + posTypeStr + "_POS_SELECT_BTN_" + ToXString(iPos.ticket); // CButton *iPosBtn = new CButton(); has = iPosBtn.Create( chartId, iPosBtnName, subWindow, iPosBtnX, lastY, iPosBtnSizeX, lastSizeY // ); if (has) { // // Apply Styles ... string iPosBtnText = ToXString(iPos.ticket); // iPosBtn.Text(iPosBtnText); iPosBtn.Color(clrWhite); // color iPosBtnBG = IsLong(iPos.type) ? clrGreen : clrDarkRed; iPosBtn.ColorBackground(iPosBtnBG); // lastX = iPosBtnSizeX + 5; // if (selectedPositionID == iPos.ticket) { iPosBtn.Disable(); } // posArray.Add(iPosBtn); } // iPos.Clean(); } // ZeroMemory(positions); UpdateGUIState(); } // void UpdateGUIState() { // // Update States Of Position Select Buttons ... int count = posArray.Total(); bool has = IsValidSize(count) && selectedPositionID > 0; if (has) { // for (int i = 0; i < count; i++) { // CButton *iBtn = (CButton *)posArray.At(i); // ulong posID = ExtractPositionIDFromButtonName(iBtn.Name()); // // Select Position ... XPosition iPos; bool hasPosition = eaTrader.GetPosition( posID, iPos // ); string iTooltip = !hasPosition ? "" : IsLong(iPos.type) ? "Long" : "Short"; // if (posID == selectedPositionID) { // iBtn.Disable(); iBtn.ColorBackground(clrDarkGray); } else { // iBtn.Enable(); // color iBtnBG = IsLong(iPos.type) ? clrGreen : clrDarkRed; // iBtn.ColorBackground(iBtnBG); } // ZeroMemory(iBtn); } } // // Update State of Close All ... if (has && count > 1) { // btnCloseAll.Enable(); btnCloseAll.ColorBackground(clrDarkRed); } else { // btnCloseAll.Disable(); btnCloseAll.ColorBackground(clrDarkGray); } // // Update Selected Position Info Button State ... if (has) { // // Reading Global Chart Info ... int subWindow = 0; int chartWidth = mChartHelper.Width(); ulong chartId = mChartHelper.ChartId(); // // Read Selected Position ... XPosition selectedPosition; bool hasPosition = eaTrader.GetPosition( selectedPositionID, selectedPosition // ); // // Read All Positions ... double profits = 0; XPosition positions[]; string positionsInfo = ""; int positionsCount = eaTrader.GetPositions(positions); has = IsValidSize(positionsCount); if (has) { // for (int i = 0; i < positionsCount; i++) { profits += positions[i].profit; } // if (positionsCount > 1) { positionsInfo = "Positions Count: " + ToXString(positionsCount) + ", Profits: " + ToXString(profits); } } // if (hasPosition) { // // Preparing Position Info ... string posTicket = "Ticket: " + ToXString(selectedPosition.ticket); string posType = "Type: " + ToXString(selectedPosition.type); string posSymbolPeriod = "Symbol: " + selectedPosition.symbol + ", " + "Period: " + ToXString(selectedPosition.period); string posProfit = "Profit: " + ToXString(selectedPosition.profit); string posRiskToRewardRatio = "RiskToReward: " + ToXString(selectedPosition.GetRiskRewardRatio()); string accountInfo = "Balance: " + ToXString(eaTrader.mAccount.GetBalance()) + ", " + "Equity: " + ToXString(eaTrader.mAccount.GetEquity()); // string posInfos[]; // // Ticket ... Add( posTicket, posInfos // ); // // Type ... Add( posType, posInfos // ); // // Symbol Period ... Add( posSymbolPeriod, posInfos // ); // // Profit ... Add( posProfit, posInfos // ); // // Risk to Reward Ratio ... Add( posRiskToRewardRatio, posInfos // ); // // Add Positions Info if Exists ... if (IsSpecifiedValid(positionsInfo)) { // Add( positionsInfo, posInfos // ); // // Clear Info Array ... selectedPosInfoArr.Clear(); } // // Adding Account Info ... Add( accountInfo, posInfos // ); // // Create Button If Not Exists ... if (btnSelectedPosInfo == NULL) { // btnSelectedPosInfo = new CButton(); // string name = objSuffix + "BTN_TOOGLE_SPOS_INFO"; // int btnStartX = btnCloseStartX; int btnSizeX = btnStartX + 200 + 5; // int btnStartY = btnCloseSizeY + 5; int btnSizeY = btnStartY + 50; // bool isCreated = btnSelectedPosInfo.Create( chartId, name, subWindow, btnStartX, btnStartY, btnSizeX, btnSizeY // ); if (!isCreated) { // delete btnSelectedPosInfo; ZeroMemory(btnSelectedPosInfo); } else { // // Apply Styles ... btnSelectedPosInfo.Color(clrYellow); btnSelectedPosInfo.ColorBackground(clrDarkBlue); } } // // Check Btn Exists ... has = btnSelectedPosInfo != NULL; if (has) { // int posInfoCount = ArraySize(posInfos); int lblInfoCount = selectedPosInfoArr.Total(); has = IsValidSize(lblInfoCount) && lblInfoCount == posInfoCount; // // Create info Labels ... if (!has) { // selectedPosInfoArr.Clear(); has = IsValidSize(posInfoCount); if (has) { // // Creat Info Control ... // string name = objSuffix + "LBL_SPOS_INFO"; // int lblHeight = 25; int lblWidth = 450; // int startX = chartWidth - lblWidth - 5; int sizeX = startX + lblWidth; // int startY = 5; int sizeY = startY + lblHeight; // // Loop through Position Info's Array to Create Label Controls ... for (int i = 0; i < posInfoCount; i++) { // string iText = posInfos[i]; string iTextMD5 = ToMD5(iText); // string iName = name + "_" + iTextMD5; // int iX1 = startX; int iX2 = sizeX; // int iY1 = startY; int iY2 = startY + lblHeight; // CEdit *iLbl = new CEdit(); bool isCreated = iLbl.Create( chartId, iName, subWindow, iX1, iY1, iX2, iY2 // ); if (isCreated) { // iLbl.Text(iText); iLbl.Color(clrYellow); iLbl.ColorBorder(clrDarkSlateGray); iLbl.ColorBackground(clrDarkSlateGray); // selectedPosInfoArr.Add(iLbl); // startY = iY2; } } } } // // Update Info Labels ... lblInfoCount = selectedPosInfoArr.Total(); has = IsValidSize(lblInfoCount); if (has) { // CEdit *iLbl = NULL; // // Loop Through Infos ... for (int i = 0; i < lblInfoCount; i++) { // iLbl = (CEdit *)selectedPosInfoArr.At(i); // iLbl.Text(posInfos[i]); } // bool isVisible = iLbl.IsVisible(); string btnText = isVisible ? "Hide Info" : "Show Info"; btnSelectedPosInfo.Text(btnText); // ZeroMemory(iLbl); } } // ZeroMemory(posInfos); } // SpecifiedClean(positions); } else { // // Toggle Selected Position Btn ... if (btnSelectedPosInfo != NULL) { // btnSelectedPosInfo.Destroy(); // delete btnSelectedPosInfo; ZeroMemory(btnSelectedPosInfo); } // // Selected Position Lbls ... selectedPosInfoArr.Clear(); } // // Update State of BtnClose and BtnClose All ... if (selectedPositionID == 0) { // btnClose.Disable(); btnClose.ColorBackground(clrDarkGray); } else { // btnClose.Enable(); btnClose.ColorBackground(clrDarkOrange); } } //