diff --git a/Eve-O-Preview/DwmAPI/DwmApiNativeMethods.cs b/Eve-O-Preview/DwmAPI/DwmApiNativeMethods.cs index 445252a..e3c663f 100644 --- a/Eve-O-Preview/DwmAPI/DwmApiNativeMethods.cs +++ b/Eve-O-Preview/DwmAPI/DwmApiNativeMethods.cs @@ -117,5 +117,18 @@ namespace EveOPreview public const UInt32 WS_EX_LAYOUTRTL = 0x00400000; // Right to left mirroring public const UInt32 WS_EX_COMPOSITED = 0x02000000; public const UInt32 WS_EX_NOACTIVATE = 0x08000000; - } + + public const int WM_SIZE = 5; + public const int SIZE_RESTORED = 0; + public const int SIZE_MINIMIZED = 1; + public const int SIZE_MAXIMIZED = 2; + public const int SIZE_MAXSHOW = 3; + public const int SIZE_MAXHIDE = 4; + + [DllImport("user32.dll")] + public static extern int GetWindowRect(IntPtr hwnd, out RECT rect); + + [DllImport("user32.dll")] + public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); + } } \ No newline at end of file diff --git a/Eve-O-Preview/Eve-O-Preview.csproj b/Eve-O-Preview/Eve-O-Preview.csproj index f5ea476..f88d2a7 100644 --- a/Eve-O-Preview/Eve-O-Preview.csproj +++ b/Eve-O-Preview/Eve-O-Preview.csproj @@ -108,7 +108,6 @@ - diff --git a/Eve-O-Preview/GUI/GuiNativeMethods.cs b/Eve-O-Preview/GUI/GuiNativeMethods.cs deleted file mode 100644 index d46dfb1..0000000 --- a/Eve-O-Preview/GUI/GuiNativeMethods.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace EveOPreview -{ - // TODO This is a really bad name for this class - static class GuiNativeMethods - { - public const int WM_SIZE = 5; - public const int SIZE_RESTORED = 0; - public const int SIZE_MINIMIZED = 1; - public const int SIZE_MAXIMIZED = 2; - public const int SIZE_MAXSHOW = 3; - public const int SIZE_MAXHIDE = 4; - - [DllImport("user32.dll")] - public static extern int GetWindowRect(IntPtr hwnd, out RECT rect); - - [DllImport("user32.dll")] - public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); - } -} \ No newline at end of file diff --git a/Eve-O-Preview/GUI/MainForm.cs b/Eve-O-Preview/GUI/MainForm.cs index 389ea25..3aa95aa 100644 --- a/Eve-O-Preview/GUI/MainForm.cs +++ b/Eve-O-Preview/GUI/MainForm.cs @@ -151,8 +151,7 @@ namespace EveOPreview if (!_previews.ContainsKey(process.MainWindowHandle) && process.MainWindowTitle != "") { - _previews[process.MainWindowHandle] = new Preview(process.MainWindowHandle, "...", this, sync_size); - _previews[process.MainWindowHandle].set_render_area_size(sync_size);// TODO Remove + _previews[process.MainWindowHandle] = new Preview(this, process.MainWindowHandle, "...", sync_size); // apply more thumbnail specific options _previews[process.MainWindowHandle].MakeTopMost(Properties.Settings.Default.always_on_top); @@ -202,7 +201,6 @@ namespace EveOPreview previews_check_listbox.Items.Remove(_previews[processHandle]); previews_check_listbox.EndUpdate(); - _previews[processHandle].overlay.Close(); _previews[processHandle].Close(); _previews.Remove(processHandle); } @@ -215,7 +213,7 @@ namespace EveOPreview { if (Properties.Settings.Default.track_client_windows && _clientLayout.ContainsKey(process.MainWindowTitle)) { - GuiNativeMethods.MoveWindow(process.MainWindowHandle, _clientLayout[process.MainWindowTitle].X, + DwmApiNativeMethods.MoveWindow(process.MainWindowHandle, _clientLayout[process.MainWindowTitle].X, _clientLayout[process.MainWindowTitle].Y, _clientLayout[process.MainWindowTitle].Width, _clientLayout[process.MainWindowTitle].Height, true); } @@ -397,7 +395,7 @@ namespace EveOPreview foreach (Process process in processes) { RECT rect = new RECT(); - GuiNativeMethods.GetWindowRect(process.MainWindowHandle, out rect); + DwmApiNativeMethods.GetWindowRect(process.MainWindowHandle, out rect); int left = Math.Abs(rect.Left); int right = Math.Abs(rect.Right); @@ -426,8 +424,6 @@ namespace EveOPreview foreach (KeyValuePair entry in _previews) { entry.Value.MakeTopMost(Properties.Settings.Default.always_on_top); - //makes the PreviewOverlay topmost - entry.Value.overlay.MakeTopMost(); } } @@ -450,7 +446,7 @@ namespace EveOPreview bool active_window_is_right_type = false; foreach (KeyValuePair entry in _previews) { - if (entry.Key == window || entry.Value.Handle == window || this.Handle == window || entry.Value.overlay.Handle == window) + if (entry.Key == window || entry.Value.IsPreviewHandle(window)) { active_window_is_right_type = true; } @@ -489,8 +485,6 @@ namespace EveOPreview } entry.Value.hover_zoom = Properties.Settings.Default.zoom_on_hover; entry.Value.show_overlay = Properties.Settings.Default.show_overlay; - //makes the PreviewOverlay TopMost - entry.Value.overlay.MakeTopMost(); if (!entry.Value.is_hovered_over) { entry.Value.Opacity = Properties.Settings.Default.opacity; @@ -518,7 +512,7 @@ namespace EveOPreview { if (entry.Value.Handle != DwmApiNativeMethods.GetForegroundWindow()) { - entry.Value.set_render_area_size(sync_size); + entry.Value.SetSize(sync_size); } } @@ -824,16 +818,16 @@ namespace EveOPreview { switch (m.Msg) { - case GuiNativeMethods.WM_SIZE: + case DwmApiNativeMethods.WM_SIZE: switch (m.WParam.ToInt32()) { - case GuiNativeMethods.SIZE_RESTORED: + case DwmApiNativeMethods.SIZE_RESTORED: OnRestored(EventArgs.Empty); break; - case GuiNativeMethods.SIZE_MINIMIZED: + case DwmApiNativeMethods.SIZE_MINIMIZED: OnMinimized(EventArgs.Empty); break; - case GuiNativeMethods.SIZE_MAXIMIZED: + case DwmApiNativeMethods.SIZE_MAXIMIZED: OnMaximized(EventArgs.Empty); break; } diff --git a/Eve-O-Preview/Preview/Preview.Designer.cs b/Eve-O-Preview/Preview/Preview.Designer.cs index 9a83820..d33bce3 100644 --- a/Eve-O-Preview/Preview/Preview.Designer.cs +++ b/Eve-O-Preview/Preview/Preview.Designer.cs @@ -31,6 +31,8 @@ namespace EveOPreview this.RenderAreaPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize; this.RenderAreaPictureBox.TabIndex = 0; this.RenderAreaPictureBox.TabStop = false; + this.RenderAreaPictureBox.MouseLeave += new System.EventHandler(this.preview_MouseLeave); + this.RenderAreaPictureBox.MouseHover += new System.EventHandler(this.preview_MouseHover); this.RenderAreaPictureBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.render_area_Click); // // Preview diff --git a/Eve-O-Preview/Preview/Preview.cs b/Eve-O-Preview/Preview/Preview.cs index 23806db..5e2e654 100644 --- a/Eve-O-Preview/Preview/Preview.cs +++ b/Eve-O-Preview/Preview/Preview.cs @@ -6,50 +6,151 @@ namespace EveOPreview { public partial class Preview : Form { + #region Private fields + private readonly bool _isInitializing; + private readonly IntPtr _sourceWindow; + private readonly MainForm _parentForm; + private readonly PreviewOverlay _overlay; + + private Size _normalSize; + private Point _normalPosition; + + private bool _isThumbnailSetUp; + private DWM_THUMBNAIL_PROPERTIES _Thumbnail; + private IntPtr _ThumbnailHandle; + #endregion + + // TODO Hide the parent form behind an interface + public Preview(MainForm parent, IntPtr sourceWindow, String title, Size size) + { + this._isInitializing = true; + + this._sourceWindow = sourceWindow; + this._parentForm = parent; + + this._isThumbnailSetUp = false; + + InitializeComponent(); + + this.Text = title; + + this._overlay = new PreviewOverlay(this.render_area_Click); + + this._isInitializing = false; + + this.SetSize(size); + } + + public bool IsPreviewHandle(IntPtr handle) + { + return (this.Handle == handle) || (this._overlay.Handle == handle); + } + + public void SetSize(Size size) + { + this.Size = size; + this._normalSize = this.Size; + this._normalPosition = this.Location; + } + + public void MakeTopMost(bool topmost) + { + if (!this.hide) + { + return; + } + + this.TopMost = topmost; + this.MakeOverlayTopMost(); + } + + protected override CreateParams CreateParams + { + get + { + var Params = base.CreateParams; + Params.ExStyle |= (int)DwmApiNativeMethods.WS_EX_TOOLWINDOW; + return Params; + } + } + + private void MakeOverlayTopMost() + { + this._overlay.TopMost = true; + } + + private void RefreshPreview() + { + if (this._isInitializing) + { + return; + } + + if (DwmApiNativeMethods.DwmIsCompositionEnabled()) + { + if (this._isThumbnailSetUp == false) + { + this.SetUpThumbnail(); + } + + this._Thumbnail.rcDestination = new RECT(0, 0, this.ClientRectangle.Right, this.ClientRectangle.Bottom); + DwmApiNativeMethods.DwmUpdateThumbnailProperties(this._ThumbnailHandle, this._Thumbnail); + } + else + { + this._isThumbnailSetUp = false; + } + + Size overlaySize = this.RenderAreaPictureBox.Size; + overlaySize.Width -= 2 * 5; + overlaySize.Height -= 2 * 5; + + Point overlayLocation = this.Location; + overlayLocation.X += 5 + (this.Size.Width - this.RenderAreaPictureBox.Size.Width) / 2; + overlayLocation.Y += 5 + (this.Size.Height - this.RenderAreaPictureBox.Size.Height) - (this.Size.Width - this.RenderAreaPictureBox.Size.Width) / 2; + + this._overlay.Size = overlaySize; + this._overlay.Location = overlayLocation; + } + + private void SetUpThumbnail() + { + // TODO Remove this API call on Win 8+ hosts + if (this._isThumbnailSetUp || !DwmApiNativeMethods.DwmIsCompositionEnabled()) + { + return; + } + + this._ThumbnailHandle = DwmApiNativeMethods.DwmRegisterThumbnail(this.Handle, this._sourceWindow); + + this._Thumbnail = new DWM_THUMBNAIL_PROPERTIES(); + this._Thumbnail.dwFlags = DWM_THUMBNAIL_PROPERTIES.DWM_TNP_VISIBLE + + DWM_THUMBNAIL_PROPERTIES.DWM_TNP_OPACITY + + DWM_THUMBNAIL_PROPERTIES.DWM_TNP_RECTDESTINATION + + DWM_THUMBNAIL_PROPERTIES.DWM_TNP_SOURCECLIENTAREAONLY; + this._Thumbnail.opacity = 255; + this._Thumbnail.fVisible = true; + this._Thumbnail.fSourceClientAreaOnly = true; + this._Thumbnail.rcDestination = new RECT(0, 0, ClientRectangle.Right, ClientRectangle.Bottom); + + DwmApiNativeMethods.DwmUpdateThumbnailProperties(_ThumbnailHandle, _Thumbnail); + + _isThumbnailSetUp = true; + } + + public bool show_overlay = true; public bool hover_zoom = true; public bool is_zoomed = false; public bool is_hovered_over = false; private bool mouse_over_lock = false; - private Size old_size; - private Point old_position; - private IntPtr m_hThumbnail; - public IntPtr sourceWindow; - private DWM_THUMBNAIL_PROPERTIES m_ThumbnailProperties; - private bool has_been_set_up = false; - private bool thumbnail_has_been_set_up = false; - private MainForm spawner; + private Hotkey hotkey; private bool hide = false; - public PreviewOverlay overlay; - - - public Preview(IntPtr sourceWindow, String title, MainForm spawner, Size size) - { - has_been_set_up = false; - - this.sourceWindow = sourceWindow; - this.spawner = spawner; - - InitializeComponent(); - - this.Text = title; - - this.overlay = new PreviewOverlay(this); - - this.RenderAreaPictureBox.MouseHover += new System.EventHandler(this.preview_MouseHover); - this.RenderAreaPictureBox.MouseLeave += new System.EventHandler(this.preview_MouseLeave); - - this.old_size = this.Size; - this.old_position = this.Location; - - has_been_set_up = true; - } - public void MakeHidden(bool wha) { hide = wha; @@ -60,11 +161,6 @@ namespace EveOPreview return this.Text; } - public void MakeTopMost(bool topmost) - { - this.TopMost = topmost && !(this.hide); - } - public void preview_MouseHover(object sender, System.EventArgs e) { if (!mouse_over_lock) @@ -73,24 +169,13 @@ namespace EveOPreview if (hover_zoom) doZoom(); - TopMost = true; - overlay.TopMost = true; + this.MakeTopMost(true); } this.Opacity = 1.0f; this.is_hovered_over = true; RefreshPreview(); } - protected override CreateParams CreateParams - { - get - { - var Params = base.CreateParams; - Params.ExStyle |= 0x80; - return Params; - } - } - public void registerShortcut(string shortcut) { if (shortcut == "") @@ -116,7 +201,8 @@ namespace EveOPreview key = key & ~Keys.Shift & ~Keys.Alt & ~Keys.Control; hotkey.KeyCode = key; hotkey.Register(this); - hotkey.Pressed += delegate { bring_client_to_foreground(); spawner.preview_did_switch(); }; + // TODO Make this a method + hotkey.Pressed += (s, e) => { bring_client_to_foreground(); this._parentForm.preview_did_switch(); }; this.hotkey = hotkey; } @@ -130,8 +216,8 @@ namespace EveOPreview float hover_zoom_factor = Properties.Settings.Default.zoom_amount; - old_size = Size; - old_position = Location; + _normalSize = Size; + _normalPosition = Location; Size = new Size((int)(hover_zoom_factor * (float)Size.Width), (int)(hover_zoom_factor * (float)Size.Height)); @@ -140,30 +226,30 @@ namespace EveOPreview case (ZoomAnchor.NW): break; case (ZoomAnchor.N): - Location = new Point(Location.X - Size.Width / 2 + old_size.Width / 2, Location.Y); + Location = new Point(Location.X - Size.Width / 2 + _normalSize.Width / 2, Location.Y); break; case (ZoomAnchor.NE): - Location = new Point(Location.X - Size.Width + old_size.Width, Location.Y); + Location = new Point(Location.X - Size.Width + _normalSize.Width, Location.Y); break; case (ZoomAnchor.W): - Location = new Point(Location.X, Location.Y - Size.Height / 2 + old_size.Height / 2); + Location = new Point(Location.X, Location.Y - Size.Height / 2 + _normalSize.Height / 2); break; case (ZoomAnchor.C): - Location = new Point(Location.X - Size.Width / 2 + old_size.Width / 2, Location.Y - Size.Height / 2 + old_size.Height / 2); + Location = new Point(Location.X - Size.Width / 2 + _normalSize.Width / 2, Location.Y - Size.Height / 2 + _normalSize.Height / 2); break; case (ZoomAnchor.E): - Location = new Point(Location.X - Size.Width + old_size.Width, Location.Y - Size.Height / 2 + old_size.Height / 2); + Location = new Point(Location.X - Size.Width + _normalSize.Width, Location.Y - Size.Height / 2 + _normalSize.Height / 2); break; case (ZoomAnchor.SW): - Location = new Point(Location.X, Location.Y - Size.Height + old_size.Height); + Location = new Point(Location.X, Location.Y - Size.Height + _normalSize.Height); break; case (ZoomAnchor.S): - Location = new Point(Location.X - Size.Width / 2 + old_size.Width / 2, Location.Y - Size.Height + old_size.Height); + Location = new Point(Location.X - Size.Width / 2 + _normalSize.Width / 2, Location.Y - Size.Height + _normalSize.Height); break; case (ZoomAnchor.SE): - Location = new Point(Location.X - Size.Width + old_size.Width, Location.Y - Size.Height + old_size.Height); + Location = new Point(Location.X - Size.Width + _normalSize.Width, Location.Y - Size.Height + _normalSize.Height); break; } } @@ -173,8 +259,8 @@ namespace EveOPreview if (!is_zoomed) return; - Size = old_size; - Location = old_position; + Size = _normalSize; + Location = _normalPosition; is_zoomed = false; } @@ -197,22 +283,23 @@ namespace EveOPreview { RefreshPreview(); base.OnResize(e); - if (has_been_set_up && !mouse_over_lock) - this.spawner.syncronize_preview_size(this.Size); + + if (!this._isInitializing && !mouse_over_lock) + this._parentForm.syncronize_preview_size(this.Size); } protected override void OnMove(EventArgs e) { base.OnMove(e); - if (has_been_set_up && !mouse_over_lock) - this.spawner.register_preview_position(this.Text, this.Location); + if (!this._isInitializing && !mouse_over_lock) + this._parentForm.register_preview_position(this.Text, this.Location); RefreshPreview(); } public void doMove(Point position) { - if (has_been_set_up && !mouse_over_lock) + if (!this._isInitializing && !mouse_over_lock) Location = position; RefreshPreview(); @@ -221,39 +308,7 @@ namespace EveOPreview public void SetLabel(String label) { this.Text = label; - this.overlay.SetOverlayLabel(label); - } - - public void RefreshPreview() - { - if (has_been_set_up) - { - if (DwmApiNativeMethods.DwmIsCompositionEnabled()) - { - if (thumbnail_has_been_set_up == false) - { - this.SetUpThumbnail(); - } - m_ThumbnailProperties.rcDestination = new RECT(0, 0, ClientRectangle.Right, ClientRectangle.Bottom); - DwmApiNativeMethods.DwmUpdateThumbnailProperties(m_hThumbnail, m_ThumbnailProperties); - } - else - { - thumbnail_has_been_set_up = false; - } - - Size overlay_size = this.RenderAreaPictureBox.Size; - overlay_size.Width -= 2 * 5; - overlay_size.Height -= 2 * 5; - - Point overlay_location = this.Location; - overlay_location.X += 5 + (this.Size.Width - this.RenderAreaPictureBox.Size.Width) / 2; - overlay_location.Y += 5 + (this.Size.Height - this.RenderAreaPictureBox.Size.Height) - (this.Size.Width - this.RenderAreaPictureBox.Size.Width) / 2; - - this.overlay.Size = overlay_size; - this.overlay.Location = overlay_location; - - } + this._overlay.SetOverlayLabel(label); } new public void Show() @@ -262,43 +317,31 @@ namespace EveOPreview { base.Show(); if (show_overlay) - this.overlay.Show(); + { + this._overlay.Show(); + this.MakeOverlayTopMost(); + } else - this.overlay.Hide(); + { + this._overlay.Hide(); + } } else { this.Hide(); - this.overlay.Hide(); } } new public void Hide() { base.Hide(); - this.overlay.Hide(); + this._overlay.Hide(); } - private void SetUpThumbnail() + new public void Close() { - if (DwmApiNativeMethods.DwmIsCompositionEnabled() && !thumbnail_has_been_set_up) - { - m_hThumbnail = DwmApiNativeMethods.DwmRegisterThumbnail(this.Handle, sourceWindow); - - m_ThumbnailProperties = new DWM_THUMBNAIL_PROPERTIES(); - m_ThumbnailProperties.dwFlags = DWM_THUMBNAIL_PROPERTIES.DWM_TNP_VISIBLE - + DWM_THUMBNAIL_PROPERTIES.DWM_TNP_OPACITY - + DWM_THUMBNAIL_PROPERTIES.DWM_TNP_RECTDESTINATION - + DWM_THUMBNAIL_PROPERTIES.DWM_TNP_SOURCECLIENTAREAONLY; - m_ThumbnailProperties.opacity = 255; - m_ThumbnailProperties.fVisible = true; - m_ThumbnailProperties.fSourceClientAreaOnly = true; - m_ThumbnailProperties.rcDestination = new RECT(0, 0, ClientRectangle.Right, ClientRectangle.Bottom); - - DwmApiNativeMethods.DwmUpdateThumbnailProperties(m_hThumbnail, m_ThumbnailProperties); - - thumbnail_has_been_set_up = true; - } + this._overlay.Close(); + base.Close(); } private void Preview_Load(object sender, EventArgs e) @@ -308,15 +351,15 @@ namespace EveOPreview public void bring_client_to_foreground() { - DwmApiNativeMethods.SetForegroundWindow(sourceWindow); - int style = DwmApiNativeMethods.GetWindowLong(sourceWindow, DwmApiNativeMethods.GWL_STYLE); + DwmApiNativeMethods.SetForegroundWindow(this._sourceWindow); + int style = DwmApiNativeMethods.GetWindowLong(this._sourceWindow, DwmApiNativeMethods.GWL_STYLE); if ((style & DwmApiNativeMethods.WS_MAXIMIZE) == DwmApiNativeMethods.WS_MAXIMIZE) { //It's maximized } else if ((style & DwmApiNativeMethods.WS_MINIMIZE) == DwmApiNativeMethods.WS_MINIMIZE) { - DwmApiNativeMethods.ShowWindowAsync(sourceWindow, DwmApiNativeMethods.SW_SHOWNORMAL); + DwmApiNativeMethods.ShowWindowAsync(this._sourceWindow, DwmApiNativeMethods.SW_SHOWNORMAL); } } @@ -325,7 +368,7 @@ namespace EveOPreview if (e.Button == MouseButtons.Left) { bring_client_to_foreground(); - spawner.preview_did_switch(); + this._parentForm.preview_did_switch(); } if (e.Button == MouseButtons.Right) { @@ -336,10 +379,5 @@ namespace EveOPreview // do smth cool? } } - - public void set_render_area_size(Size size) - { - this.Size = size; - } } } \ No newline at end of file diff --git a/Eve-O-Preview/Preview/PreviewOverlay.cs b/Eve-O-Preview/Preview/PreviewOverlay.cs index b3a11d5..a2aec56 100644 --- a/Eve-O-Preview/Preview/PreviewOverlay.cs +++ b/Eve-O-Preview/Preview/PreviewOverlay.cs @@ -1,25 +1,21 @@ -using System.Windows.Forms; +using System; +using System.Windows.Forms; namespace EveOPreview { public partial class PreviewOverlay : Form { - private readonly Preview _parent; + private readonly Action _areaClickAction; - public PreviewOverlay(Preview parent) + public PreviewOverlay(Action areaClickAction) { - this._parent = parent; + this._areaClickAction = areaClickAction; InitializeComponent(); } private void OverlayArea_Click(object sender, MouseEventArgs e) { - this._parent.render_area_Click(sender, e); - } - - public void MakeTopMost() - { - this.TopMost = true; + this._areaClickAction(sender, e); } public void SetOverlayLabel(string label) @@ -32,7 +28,7 @@ namespace EveOPreview get { var Params = base.CreateParams; - Params.ExStyle |= 0x80; + Params.ExStyle |= (int)DwmApiNativeMethods.WS_EX_TOOLWINDOW; return Params; } }