private void MemoryPollingTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { bool exitLoop = false; try { bool procRun = Program.gameMemory.ProcessRunning; int procExitCode = Program.gameMemory.ProcessExitCode; if (!procRun) { Program.gamePID = -1; exitLoop = true; return; } if (Program.programSpecialOptions.Flags.HasFlag(ProgramFlags.AlwaysOnTop)) { bool hasFocus; if (this.InvokeRequired) { hasFocus = PInvoke.HasActiveFocus((IntPtr)this.Invoke(new Func <IntPtr>(() => this.Handle))); } else { hasFocus = PInvoke.HasActiveFocus(this.Handle); } if (!hasFocus) { if (this.InvokeRequired) { this.Invoke(new Action(() => this.TopMost = true)); } else { this.TopMost = true; } } } // Only perform a pointer update occasionally. if (DateTime.UtcNow.Ticks - lastPtrUpdate >= PTR_UPDATE_TICKS) { // Update the last drawn time. lastPtrUpdate = DateTime.UtcNow.Ticks; // Update the pointers. Program.gameMemory.UpdatePointers(); } // Only draw occasionally, not as often as the stats panel. if (DateTime.UtcNow.Ticks - lastFullUIDraw >= FULL_UI_DRAW_TICKS) { // Update the last drawn time. lastFullUIDraw = DateTime.UtcNow.Ticks; // Get the full amount of updated information from memory. Program.gameMemory.Refresh(); // Only draw these periodically to reduce CPU usage. this.playerHealthStatus.Invalidate(); if (!Program.programSpecialOptions.Flags.HasFlag(ProgramFlags.NoInventory)) { this.inventoryPanel.Invalidate(); } } else { // Get a slimmed-down amount of updated information from memory. Program.gameMemory.RefreshSlim(); } // Always draw this as these are simple text draws and contains the IGT/frame count. this.statisticsPanel.Invalidate(); } catch (Exception ex) { Debug.WriteLine("[{0}] {1}\r\n{2}", ex.GetType().ToString(), ex.Message, ex.StackTrace); } finally { // Trigger the timer to start once again. if we're not in fatal error. if (!exitLoop) { ((System.Timers.Timer)sender).Start(); } else { CloseForm(); } } }