using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using OnTopReplica.Native; using OnTopReplica.Properties; using OnTopReplica.StartupOptions; using OnTopReplica.Update; using OnTopReplica.WindowSeekers; using WindowsFormsAero.Dwm; using WindowsFormsAero.TaskDialog; namespace OnTopReplica { partial class MainForm : AspectRatioForm { //GUI elements ThumbnailPanel _thumbnailPanel; //Managers readonly MessagePumpManager _msgPumpManager = new MessagePumpManager(); WindowListMenuManager _windowListManager; public FullscreenFormManager FullscreenManager { get; private set; } Options _startupOptions; public MainForm(Options startupOptions) { _startupOptions = startupOptions; FullscreenManager = new FullscreenFormManager(this); //WinForms init pass InitializeComponent(); //Store default values DefaultNonClickTransparencyKey = this.TransparencyKey; DefaultBorderStyle = this.FormBorderStyle; //Thumbnail panel _thumbnailPanel = new ThumbnailPanel { Location = Point.Empty, Dock = DockStyle.Fill }; _thumbnailPanel.CloneClick += new EventHandler(Thumbnail_CloneClick); Controls.Add(_thumbnailPanel); //Set native renderer on context menus Asztal.Szótár.NativeToolStripRenderer.SetToolStripRenderer( menuContext, menuWindows, menuOpacity, menuResize, menuFullscreenContext ); //Set to Key event preview this.KeyPreview = true; } #region Event override protected override void OnHandleCreated(EventArgs e){ base.OnHandleCreated(e); //Window init KeepAspectRatio = false; GlassEnabled = true; GlassMargins = new Margins(-1); //Managers _msgPumpManager.Initialize(this); _windowListManager = new WindowListMenuManager(this, menuWindows); _windowListManager.ParentMenus = new System.Windows.Forms.ContextMenuStrip[] { menuContext, menuFullscreenContext }; //Platform specific form initialization Program.Platform.PostHandleFormInit(this); } protected override void OnShown(EventArgs e) { base.OnShown(e); //Apply startup options _startupOptions.Apply(this); } protected override void OnClosing(CancelEventArgs e) { //Store last thumbnail, if any if (_thumbnailPanel.IsShowingThumbnail && CurrentThumbnailWindowHandle != null) { Settings.Default.RestoreLastWindowTitle = CurrentThumbnailWindowHandle.Title; Settings.Default.RestoreLastWindowHwnd = CurrentThumbnailWindowHandle.Handle.ToInt64(); Settings.Default.RestoreLastWindowClass = CurrentThumbnailWindowHandle.Class; } _msgPumpManager.Dispose(); Program.Platform.CloseForm(this); base.OnClosing(e); } protected override void OnMove(EventArgs e) { base.OnMove(e); AdjustSidePanelLocation(); } protected override void OnResizeEnd(EventArgs e) { base.OnResizeEnd(e); RefreshScreenLock(); } protected override void OnActivated(EventArgs e) { base.OnActivated(e); //Deactivate click-through if form is reactivated if (ClickThroughEnabled) { ClickThroughEnabled = false; } Program.Platform.RestoreForm(this); } protected override void OnDeactivate(EventArgs e) { base.OnDeactivate(e); //HACK: sometimes, even if TopMost is true, the window loses its "always on top" status. // This is a fix attempt that probably won't work... if (!FullscreenManager.IsFullscreen) { //fullscreen mode doesn't use TopMost TopMost = false; TopMost = true; } } protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); if (!FullscreenManager.IsFullscreen) { int change = (int)(e.Delta / 6.0); //assumes a mouse wheel "tick" is in the 80-120 range AdjustSize(change); RefreshScreenLock(); } } protected override void OnMouseDoubleClick(MouseEventArgs e) { base.OnMouseDoubleClick(e); //This is handled by the WM_NCLBUTTONDBLCLK msg handler usually (because the GlassForm translates //clicks on client to clicks on caption). But if fullscreen mode disables GlassForm dragging, we need //this auxiliary handler to switch mode. FullscreenManager.Toggle(); } protected override void OnMouseClick(MouseEventArgs e) { base.OnMouseClick(e); //Same story as above (OnMouseDoubleClick) if (e.Button == System.Windows.Forms.MouseButtons.Right) { OpenContextMenu(null); } } protected override void WndProc(ref Message m) { if (_msgPumpManager != null) { if (_msgPumpManager.PumpMessage(ref m)) { return; } } switch (m.Msg) { case WM.NCRBUTTONUP: //Open context menu if right button clicked on caption (i.e. all of the window area because of glass) if (m.WParam.ToInt32() == HT.CAPTION) { OpenContextMenu(null); m.Result = IntPtr.Zero; return; } break; case WM.NCLBUTTONDBLCLK: //Toggle fullscreen mode if double click on caption (whole glass area) if (m.WParam.ToInt32() == HT.CAPTION) { FullscreenManager.Toggle(); m.Result = IntPtr.Zero; return; } break; case WM.NCHITTEST: //Make transparent to hit-testing if in click through mode if (ClickThroughEnabled && (ModifierKeys & Keys.Alt) != Keys.Alt) { m.Result = (IntPtr)HT.TRANSPARENT; return; } break; } base.WndProc(ref m); } #endregion #region Keyboard event handling protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); //ALT if (e.Modifiers == Keys.Alt) { if (e.KeyCode == Keys.Enter) { e.Handled = true; FullscreenManager.Toggle(); } else if (e.KeyCode == Keys.D1 || e.KeyCode == Keys.NumPad1) { FitToThumbnail(0.25); } else if (e.KeyCode == Keys.D2 || e.KeyCode == Keys.NumPad2) { FitToThumbnail(0.5); } else if (e.KeyCode == Keys.D3 || e.KeyCode == Keys.NumPad3 || e.KeyCode == Keys.D0 || e.KeyCode == Keys.NumPad0) { FitToThumbnail(1.0); } else if (e.KeyCode == Keys.D4 || e.KeyCode == Keys.NumPad4) { FitToThumbnail(2.0); } } //F11 Fullscreen switch else if (e.KeyCode == Keys.F11) { e.Handled = true; FullscreenManager.Toggle(); } //ESCAPE else if (e.KeyCode == Keys.Escape) { //Disable click-through if (ClickThroughEnabled) { ClickThroughEnabled = false; } //Toggle fullscreen else if (FullscreenManager.IsFullscreen) { FullscreenManager.SwitchBack(); } //Disable click forwarding else if (ClickForwardingEnabled) { ClickForwardingEnabled = false; } } } #endregion #region Thumbnail operation /// /// Sets a new thumbnail. /// /// Handle to the window to clone. /// Region of the window to clone or null. public void SetThumbnail(WindowHandle handle, ThumbnailRegion region) { try { System.Diagnostics.Trace.WriteLine(string.Format("Cloning window HWND {0} of class {1}.", handle.Handle, handle.Class)); CurrentThumbnailWindowHandle = handle; _thumbnailPanel.SetThumbnailHandle(handle, region); //Set aspect ratio (this will resize the form), do not refresh if in fullscreen SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, !FullscreenManager.IsFullscreen); } catch (Exception ex) { System.Diagnostics.Trace.Fail("Unable to set thumbnail.", ex.ToString()); ThumbnailError(ex, false, Strings.ErrorUnableToCreateThumbnail); _thumbnailPanel.UnsetThumbnail(); } } /// /// Enables group mode on a list of window handles. /// /// List of window handles. public void SetThumbnailGroup(IList handles) { if (handles.Count == 0) return; //At last one thumbnail SetThumbnail(handles[0], null); //Handle if no real group if (handles.Count == 1) return; CurrentThumbnailWindowHandle = null; _msgPumpManager.Get().EnableGroupMode(handles); } /// /// Disables the cloned thumbnail. /// public void UnsetThumbnail() { //Unset handle CurrentThumbnailWindowHandle = null; _thumbnailPanel.UnsetThumbnail(); //Disable aspect ratio KeepAspectRatio = false; } /// /// Gets or sets the region displayed of the current thumbnail. /// public ThumbnailRegion SelectedThumbnailRegion { get { if (!_thumbnailPanel.IsShowingThumbnail || !_thumbnailPanel.ConstrainToRegion) return null; return _thumbnailPanel.SelectedRegion; } set { if (!_thumbnailPanel.IsShowingThumbnail) return; _thumbnailPanel.SelectedRegion = value; SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, true); FixPositionAndSize(); } } const int FixMargin = 10; /// /// Fixes the form's position and size, ensuring it is fully displayed in the current screen. /// private void FixPositionAndSize() { var screen = Screen.FromControl(this); if (Width > screen.WorkingArea.Width) { Width = screen.WorkingArea.Width - FixMargin; } if (Height > screen.WorkingArea.Height) { Height = screen.WorkingArea.Height - FixMargin; } if (Location.X + Width > screen.WorkingArea.Right) { Location = new Point(screen.WorkingArea.Right - Width - FixMargin, Location.Y); } if (Location.Y + Height > screen.WorkingArea.Bottom) { Location = new Point(Location.X, screen.WorkingArea.Bottom - Height - FixMargin); } } private void ThumbnailError(Exception ex, bool suppress, string title) { if (!suppress) { ShowErrorDialog(title, Strings.ErrorGenericThumbnailHandleError, ex.Message); } UnsetThumbnail(); } /// Automatically sizes the window in order to accomodate the thumbnail p times. /// Scale of the thumbnail to consider. private void FitToThumbnail(double p) { try { Size originalSize = _thumbnailPanel.ThumbnailPixelSize; Size fittedSize = new Size((int)(originalSize.Width * p), (int)(originalSize.Height * p)); ClientSize = fittedSize; RefreshScreenLock(); } catch (Exception ex) { ThumbnailError(ex, false, Strings.ErrorUnableToFit); } } #endregion #region Accessors /// /// Gets the form's thumbnail panel. /// public ThumbnailPanel ThumbnailPanel { get { return _thumbnailPanel; } } /// /// Gets the form's message pump manager. /// public MessagePumpManager MessagePumpManager { get { return _msgPumpManager; } } /// /// Gets the form's window list drop down menu. /// public ContextMenuStrip MenuWindows { get { return menuWindows; } } /// /// Retrieves the window handle of the currently cloned thumbnail. /// public WindowHandle CurrentThumbnailWindowHandle { get; private set; } #endregion } }