/// <summary> /// Initializes a new instance of the <see cref="LcdDisplay"/> class. /// </summary> private LcdDisplay() { m_defaultFont = FontFactory.GetFont("Microsoft Sans Serif", 13.5f); m_bmpLCD = new Bitmap(G15Width, G15Height, PixelFormat.Format24bppRgb); m_bmpLCD.SetResolution(G15DpiX, G15DpiY); m_lcdCanvas = Graphics.FromImage(m_bmpLCD); m_lcdCanvas.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; m_bmpLCDX = new Bitmap(G15Width, G15Height, PixelFormat.Format24bppRgb); m_bmpLCDX.SetResolution(G15DpiX, G15DpiY); m_lcdOverlay = Graphics.FromImage(m_bmpLCDX); m_lcdOverlay.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; m_buttonStateHld = DateTime.Now; m_cycleTime = DateTime.Now.AddSeconds(10); m_cycleQueueInfoTime = DateTime.Now.AddSeconds(5); m_showingCycledQueueInfo = false; m_defaultOffset = Environment.Is64BitProcess ? -2f : 0f; Cycle = false; ShowSystemTime = false; CycleSkillQueueTime = false; m_buttonPressedCheckTimer = new Timer { Interval = 100 }; m_buttonPressedCheckTimer.Elapsed += ButtonPressedCheckTimerOnElapsed; m_buttonPressedCheckTimer.Start(); LcdInterface.Open("EVEMon"); }
/// <summary> /// Fetches the content of the <see cref="Graphics"/> object to the G15 screen. /// </summary> private unsafe void UpdateLcdDisplay() { // Locking should not be necessary but i'll keep it here lock (m_lock) { byte[] buffer = new byte[m_bmpLCD.Width * m_bmpLCD.Height]; Rectangle rect = new Rectangle(0, 0, m_bmpLCD.Width, m_bmpLCD.Height); BitmapData bmData = m_bmpLCD.LockBits(rect, ImageLockMode.ReadOnly, m_bmpLCD.PixelFormat); try { BitmapData bmDataX = m_bmpLCDX.LockBits(rect, ImageLockMode.ReadOnly, m_bmpLCDX.PixelFormat); try { // Extract bits per pixel and length infos int bpp = bmData.Stride / m_bmpLCD.Width; // Copy the content of the bitmap to our buffers // Unsafe code removes the boundaries checks - a lot faster. fixed(byte *buffer0 = buffer) { byte *output = buffer0; byte *inputX = (byte *)bmDataX.Scan0.ToPointer(); byte *input = (byte *)bmData.Scan0.ToPointer(); for (int i = 0; i < m_bmpLCD.Height; i++) { for (int j = 0; j < m_bmpLCD.Width; j++) { *output = (byte)(*input ^ *inputX); inputX += bpp; input += bpp; output++; } } } } finally { m_bmpLCDX.UnlockBits(bmDataX); } } finally { m_bmpLCD.UnlockBits(bmData); } // Fetches the buffer to the LCD screen LcdInterface.DisplayBitmap(buffer); } }
/// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="isDisposing"> /// <c>true</c> to release both managed and unmanaged resources; /// <c>false</c> to release only unmanaged resources. /// </param> private void Dispose(bool isDisposing) { if (!m_disposed) { if (isDisposing || s_singleInstance != null) { LcdInterface.Close(); } m_buttonPressedCheckTimer.Stop(); m_buttonPressedCheckTimer.Dispose(); m_bmpLCD.Dispose(); m_bmpLCDX.Dispose(); s_singleInstance = null; } m_disposed = true; }
/// <summary> /// Occurs when some of the G15 screen buttons are pressed. /// </summary> /// <returns></returns> private void ButtonPressedCheckTimerOnElapsed(object sender, ElapsedEventArgs elapsedEventArgs) { var pressedButtons = 0; if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button0)) { pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button0; } if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button1)) { pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button1; } if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button2)) { pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button2; } if (LcdInterface.ReadSoftButton((int)LogitechLcdConstants.LogiLcdMonoButton.Button3)) { pressedButtons |= (int)LogitechLcdConstants.LogiLcdMonoButton.Button3; } if (m_oldButtonState == pressedButtons) { return; } // Gets all buttons who haven't been pressed last time int press = (m_oldButtonState ^ pressedButtons) & pressedButtons; // Displays the characters' list or move to the next char if the list is already displayed. if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button0) != 0) { DisplayCharactersList(); } // Move to the first character to complete his training if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button1) != 0) { // Select next skill ready char if (!MonitoredCharacters.Any()) { return; } CurrentCharacter = FirstCharacterToCompleteSkill; AutoCycleChanged?.ThreadSafeInvoke(this, new CycleEventArgs(false)); SwitchState(LcdState.Character); } // Forces a refresh from CCP if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button2) != 0) { if (m_state == LcdState.Character || m_state == LcdState.CharacterList) { m_refreshCharacter = CurrentCharacter; ApiUpdateRequested?.ThreadSafeInvoke(this, new CharacterChangedEventArgs(m_refreshCharacter)); SwitchState(LcdState.Refreshing); } } // Switch autocycle ON/OFF if ((press & (int)LogitechLcdConstants.LogiLcdMonoButton.Button3) != 0) { // Switch autocycle on/off SwitchCycle(); AutoCycleChanged?.ThreadSafeInvoke(this, new CycleEventArgs(Cycle)); SwitchState(LcdState.CycleSettings); m_cycleTime = DateTime.Now; } m_oldButtonState = pressedButtons; }