diff --git a/ScreenRecorder/App.xaml.cs b/ScreenRecorder/App.xaml.cs index f0cd588..41369d3 100644 --- a/ScreenRecorder/App.xaml.cs +++ b/ScreenRecorder/App.xaml.cs @@ -2,7 +2,6 @@ using System.Text.RegularExpressions; using System.Threading; using System.Windows; -using System.Diagnostics; namespace ScreenRecorder { @@ -12,28 +11,6 @@ namespace ScreenRecorder public partial class App : Application { public volatile static Mutex Mutex = null; - public System.Windows.Forms.NotifyIcon NotifyIcon { get; private set; } - - public App() - { - NotifyIcon = new System.Windows.Forms.NotifyIcon(); - NotifyIcon.Visible = false; - NotifyIcon.Click += OnNotifyIconClick; - NotifyIcon.Text = AppConstants.AppName; - var iconUri = new Uri("/icon.ico", UriKind.Relative); - using (var iconStream = Application.GetResourceStream(iconUri).Stream) - { - NotifyIcon.Icon = new System.Drawing.Icon(iconStream); - } - } - - void OnNotifyIconClick(object sender, EventArgs e) - { - // restore program from system tray to desktop - MainWindow.Visibility = Visibility.Visible; - MainWindow.WindowState = WindowState.Normal; - NotifyIcon.Visible = false; - } protected override void OnStartup(StartupEventArgs e) { @@ -53,7 +30,6 @@ protected override void OnStartup(StartupEventArgs e) VideoClockEvent.Start(); AppManager.Instance.Initialize(); - AppManager.Instance.PropertyChanged += Instance_PropertyChanged; AppConfig.Instance.WhenChanged(() => { VideoClockEvent.Framerate = AppConfig.Instance.AdvancedSettings ? @@ -77,38 +53,12 @@ protected override void OnStartup(StartupEventArgs e) } } - private void Instance_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) - { - if (e.PropertyName.Equals("IsStarted") - || e.PropertyName.Equals("IsStartedWithEncode") - || e.PropertyName.Equals("IsPaused") - || e.PropertyName.Equals("IsStopped") - ) - { - Debug.WriteLine($"{e.PropertyName}: isStart: {AppManager.Instance.ScreenEncoder.IsStarted}, isEncode:{AppManager.Instance.ScreenEncoder.IsStartedWithEncode}"); - NotifyIcon.Text = AppConstants.AppName; - if (AppManager.Instance.ScreenEncoder.IsStarted && !AppManager.Instance.ScreenEncoder.IsStartedWithEncode) - NotifyIcon.Text += " waiting for start ..."; - else if (AppManager.Instance.ScreenEncoder.IsStarted && AppManager.Instance.ScreenEncoder.IsStartedWithEncode) - NotifyIcon.Text += " recording ..."; - else if (AppManager.Instance.ScreenEncoder.IsPaused) - NotifyIcon.Text += " paused ..."; - else if (AppManager.Instance.ScreenEncoder.IsStopped) - NotifyIcon.Text += " stopped ..."; - } - } - protected override void OnExit(ExitEventArgs e) { AppCommands.Instance.Dispose(); AppConfig.Instance.Dispose(); AppManager.Instance.Dispose(); VideoClockEvent.Stop(); - - // maybe not neccessary - NotifyIcon.Click -= OnNotifyIconClick; - NotifyIcon.Visible = false; - NotifyIcon.Dispose(); base.OnExit(e); } diff --git a/ScreenRecorder/AppCommands.cs b/ScreenRecorder/AppCommands.cs index 58367e1..761d7fa 100644 --- a/ScreenRecorder/AppCommands.cs +++ b/ScreenRecorder/AppCommands.cs @@ -2,12 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.Windows; -using System.Diagnostics; using System.Windows.Input; using ScreenRecorder.Command; using ScreenRecorder.Config; using ScreenRecorder.Encoder; -using ScreenRecorder.DirectX; namespace ScreenRecorder { @@ -183,7 +181,6 @@ public void Dispose() private DelegateCommand startScreenRecordCommand; private DelegateCommand pauseScreenRecordCommand; private DelegateCommand stopScreenRecordCommand; - private DelegateCommand selectRegionCommand; private DelegateCommand openFolderInWindowExplorerCommand; private DelegateCommand openRecordDirecotryCommand; private DelegateCommand selectRecordDirectory; @@ -191,81 +188,8 @@ public void Dispose() private DelegateCommand openShortcutSettingsCommand; private DelegateCommand windowCloseCommand; - private DelegateCommand windowMinimizeCommand; #endregion - private Rect? SelectDisplayAndRect (object o) - { - var region = new Rect(0, 0, double.MaxValue, double.MaxValue); - var regionSelectorWindow = new Region.RegionSelectorWindow() - { - RegionSelectionMode = AppConfig.Instance.RegionSelectionMode - }; - try - { - if (!regionSelectorWindow.ShowDialog().Value) - return null; - - var result = regionSelectorWindow.RegionSelectionResult; - if (result != null) - { - string displayDeviceName = result.DeviceName; - var monitorInfo = MonitorInfo.GetMonitorInfo(displayDeviceName); - Debug.Assert(monitorInfo != null); - region = result.Region; - - if (AppConfig.Instance.ForceSourceSize && result.Hwnd != IntPtr.Zero) - { - int cx = AppConfig.Instance.ForcedSourceWidth; - int cy = AppConfig.Instance.ForcedSourceHeight; - // sichern gerader Zahlen ? - cx &= ~0x01; - cy &= ~0x01; - - region.Width = cx; - region.Height = cy; - - // rect size check with coordinates relative to according screen - Rect monitorBounds = monitorInfo.Bounds; - monitorBounds.Offset(-monitorInfo.Left, -monitorInfo.Top); - double offsetX = (region.Right > monitorBounds.Right) ? monitorBounds.Right - region.Right : 0; - double offsetY = (region.Bottom > monitorBounds.Bottom) ? monitorBounds.Bottom - region.Bottom : 0; - region.Offset(offsetX, offsetY); - // change window size on display with absolute coordinates - region.Offset(monitorInfo.Left, monitorInfo.Top); - Region.WindowRegion.SizeWindow(result.Hwnd, (int)(region.Left), (int)(region.Top), cx, cy, true); - // get absolute coordinates after resizing - region = Region.WindowRegion.GetWindowRectangle(result.Hwnd); - // shift absolute coordinates relative to screen with 0,0 as left,top - region.Offset(-monitorInfo.Left, -monitorInfo.Top); - } - else - { - // Ensure even numbers ? - region.Width = ((int)region.Width) & (~0x01); - region.Height = ((int)region.Height) & (~0x01); - } - - if (region.Width < 100 || region.Height < 100) - { - MessageBox.Show(ScreenRecorder.Properties.Resources.RegionSizeError, - AppConstants.AppName, MessageBoxButton.OK, MessageBoxImage.Error); - return null; - } - - AppConfig.Instance.ScreenCaptureRect = region; - AppConfig.Instance.ScreenCaptureMonitor = displayDeviceName; - AppManager.Instance.ScreenCaptureMonitorDescription = monitorInfo.Description; - } - } - finally - { - AppConfig.Instance.RegionSelectionMode = regionSelectorWindow.RegionSelectionMode; - } - - return region; - } - #region Record Commands public DelegateCommand StartScreenRecordCommand => startScreenRecordCommand ?? (startScreenRecordCommand = new DelegateCommand(o => @@ -293,6 +217,8 @@ public void Dispose() if (exts != null && exts.Length > 0) ext += exts[0]; + DateTime now = DateTime.Now; + string filePath = string.Format("{0}\\{1}-{2}{3}", AppConfig.Instance.RecordDirectory, AppConstants.AppName, @@ -305,39 +231,63 @@ public void Dispose() AppConfig.Instance.SelectedRecordVideoCodec : MediaEncoder.VideoCodec.H264; var audioCodec = AppConfig.Instance.AdvancedSettings ? AppConfig.Instance.SelectedRecordAudioCodec : MediaEncoder.AudioCodec.Aac; + var displayDeviceName = o is string target ? target : AppConfig.Instance.ScreenCaptureMonitor; + var region = new Rect(0, 0, double.MaxValue, double.MaxValue); - if (!AppConfig.Instance.ScreenCaptureRect.HasValue || AppConfig.Instance.ScreenCaptureRect.Value.IsEmpty) + switch(displayDeviceName) { - // select ScreenCaptureRect and ScreenCaptureMonitor, update ScreenCaptureMonitorDescription - if (!SelectDisplayAndRect(o).HasValue) - { - MessageBox.Show("Unknown capture rect", AppConstants.AppName, MessageBoxButton.OK, MessageBoxImage.Error); - return; - } + case CaptureTarget.PrimaryCaptureTargetDeviceName: + #region Select PrimayDisplay + displayDeviceName = System.Windows.Forms.Screen.PrimaryScreen.DeviceName; + #endregion + break; + case CaptureTarget.ByUserChoiceTargetDeviceName: + #region Select Region + var regionSelectorWindow = new Region.RegionSelectorWindow() + { + RegionSelectionMode = AppConfig.Instance.RegionSelectionMode + }; + try + { + if (!regionSelectorWindow.ShowDialog().Value) + { + return; + } + + var result = regionSelectorWindow.RegionSelectionResult; + if (result != null) + { + displayDeviceName = result.DeviceName; + region = result.Region; + + region.Width = ((int)region.Width) & (~0x01); + region.Height = ((int)region.Height) & (~0x01); + + if(region.Width < 100 || region.Height < 100) + { + MessageBox.Show(ScreenRecorder.Properties.Resources.RegionSizeError, + AppConstants.AppName, MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + } + } + finally + { + AppConfig.Instance.RegionSelectionMode = regionSelectorWindow.RegionSelectionMode; + } + break; + #endregion } - MonitorInfo monitorInfo = MonitorInfo.GetMonitorInfo(AppConfig.Instance.ScreenCaptureMonitor); - if (monitorInfo == null) - throw new ArgumentException($"{AppConfig.Instance.ScreenCaptureMonitor} does not exist"); - - // securety check (coordinates relative to selected monitor with 0,0 as left,top) - Rect monitorRegion = new Rect(0, 0, monitorInfo.Width, monitorInfo.Height); - AppConfig.Instance.ScreenCaptureRect = Rect.Intersect(AppConfig.Instance.ScreenCaptureRect.Value, monitorRegion); - // Start Record try { - DateTime? captureStart = AppConfig.Instance.CaptureTimeControlled ? AppConfig.Instance.CaptureStartTime : (DateTime?)null; - DateTime? captureEnd = AppConfig.Instance.CaptureTimeControlled ? AppConfig.Instance.CaptureEndTime : (DateTime?)null; - AppManager.Instance.ScreenEncoder.Start(encodeFormat.Format, filePath, videoCodec, AppConfig.Instance.SelectedRecordVideoBitrate, audioCodec, AppConfig.Instance.SelectedRecordAudioBitrate, - monitorInfo.DeviceName, AppConfig.Instance.ScreenCaptureRect.Value, + displayDeviceName, region, AppConfig.Instance.ScreenCaptureCursorVisible, - AppConfig.Instance.RecordMicrophone, - captureStart, captureEnd - ); + AppConfig.Instance.RecordMicrophone); } catch { @@ -358,13 +308,7 @@ public void Dispose() public DelegateCommand PauseScreenRecordCommand => pauseScreenRecordCommand ?? (pauseScreenRecordCommand = new DelegateCommand(o => { - if (AppManager.Instance.ScreenEncoder.Status == Encoder.EncoderStatus.Wait) - { - // prevent closing of program for manual stop of time controlled capture - AppManager.Instance.ScreenEncoder.StopByAutomatic = false; - AppManager.Instance.ScreenEncoder.Stop(); - } - else if (AppManager.Instance.ScreenEncoder.Status == Encoder.EncoderStatus.Start) + if (AppManager.Instance.ScreenEncoder.Status == Encoder.EncoderStatus.Start) { AppManager.Instance.ScreenEncoder.Pause(); } @@ -375,22 +319,10 @@ public void Dispose() { if (AppManager.Instance.ScreenEncoder.Status != Encoder.EncoderStatus.Stop) { - // prevent closing of program for manual stop of time controlled capture - AppManager.Instance.ScreenEncoder.StopByAutomatic = false; AppManager.Instance.ScreenEncoder.Stop(); } })); - public DelegateCommand SelectRegionCommand => selectRegionCommand ?? - (selectRegionCommand = new DelegateCommand(o => - { - if (AppManager.Instance.ScreenEncoder.Status != Encoder.EncoderStatus.Stop) - return; - - AppManager.Instance.RecordSettingChecked = false; - SelectDisplayAndRect(o); - })); - public DelegateCommand SelectRecordDirectory => selectRecordDirectory ?? (selectRecordDirectory = new DelegateCommand(o => { @@ -466,7 +398,6 @@ public void Dispose() #endregion #region Window Commands - public DelegateCommand WindowCloseCommand => windowCloseCommand ?? (windowCloseCommand = new DelegateCommand(o => { @@ -478,20 +409,6 @@ public void Dispose() { return o is Window; })); - - public DelegateCommand WindowMinimizeCommand => windowMinimizeCommand ?? - (windowMinimizeCommand = new DelegateCommand(o => - { - var mainWnd = Application.Current.MainWindow; - if (Application.Current is App myApp) - { - myApp.NotifyIcon.Visible = true; - mainWnd.Hide(); - } - else - SystemCommands.MinimizeWindow(mainWnd); - })); - #endregion } } diff --git a/ScreenRecorder/AppConfig.cs b/ScreenRecorder/AppConfig.cs index 22eab5a..8a66b80 100644 --- a/ScreenRecorder/AppConfig.cs +++ b/ScreenRecorder/AppConfig.cs @@ -1,12 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Windows; -using System.Globalization; using MediaEncoder; using ScreenRecorder.Config; using ScreenRecorder.Region; -using ScreenRecorder.DirectX; namespace ScreenRecorder { @@ -67,7 +64,6 @@ public void Save(string filePath) Dictionary config = new Dictionary(); config.Add(nameof(ScreenCaptureMonitor), ScreenCaptureMonitor); config.Add(nameof(ScreenCaptureCursorVisible), ScreenCaptureCursorVisible.ToString()); - config.Add(nameof(ScreenCaptureRect), ScreenCaptureRect?.ToString(CultureInfo.InvariantCulture)??""); config.Add(nameof(AdvancedSettings), AdvancedSettings.ToString()); @@ -84,18 +80,8 @@ public void Save(string filePath) config.Add(nameof(RecordMicrophone), RecordMicrophone.ToString()); - config.Add(nameof(WindowLeft), WindowLeft.ToString(CultureInfo.InvariantCulture)); - config.Add(nameof(WindowTop), WindowTop.ToString(CultureInfo.InvariantCulture)); - - config.Add(nameof(CaptureTimeControlled), CaptureTimeControlled.ToString()); - config.Add(nameof(CaptureStartTime), CaptureStartTime.ToString(CultureInfo.InvariantCulture)); - config.Add(nameof(CaptureEndTime), CaptureEndTime.ToString(CultureInfo.InvariantCulture)); - config.Add(nameof(ExitProgram), ExitProgram.ToString()); - config.Add(nameof(ShutDown), ShutDown.ToString()); - - config.Add(nameof(ForceSourceSize), ForceSourceSize.ToString()); - config.Add(nameof(ForcedSourceHeight), ForcedSourceHeight.ToString()); - config.Add(nameof(ForcedSourceWidth), ForcedSourceWidth.ToString()); + config.Add(nameof(WindowLeft), WindowLeft.ToString()); + config.Add(nameof(WindowTop), WindowTop.ToString()); Config.Config.SaveToFile(filePath, config); } @@ -105,49 +91,32 @@ public void Load(string filePath) { lock (this) { - SetDefault(); - Dictionary config = Config.Config.LoadFromFile(filePath, true); + if (config != null) { - ScreenCaptureMonitor = Config.Config.GetString(config, nameof(ScreenCaptureMonitor), ScreenCaptureMonitor); - ScreenCaptureCursorVisible = Config.Config.GetBool(config, nameof(ScreenCaptureCursorVisible), ScreenCaptureCursorVisible); - ScreenCaptureRect = Config.Config.GetRect(config, nameof(ScreenCaptureRect), ScreenCaptureRect); - AppManager.Instance.ScreenCaptureMonitorDescription = MonitorInfo.GetMonitorInfo(ScreenCaptureMonitor)?.Description ?? ""; - - AdvancedSettings = Config.Config.GetBool(config, nameof(AdvancedSettings), AdvancedSettings); - - SelectedRecordFormat = Config.Config.GetString(config, nameof(SelectedRecordFormat), SelectedRecordFormat); - SelectedRecordVideoCodec = Config.Config.GetEnum(config, nameof(SelectedRecordVideoCodec), SelectedRecordVideoCodec); - SelectedRecordAudioCodec = Config.Config.GetEnum(config, nameof(SelectedRecordAudioCodec), SelectedRecordAudioCodec); - SelectedRecordVideoBitrate = Config.Config.GetInt32(config, nameof(SelectedRecordVideoBitrate), SelectedRecordVideoBitrate); - SelectedRecordAudioBitrate = Config.Config.GetInt32(config, nameof(SelectedRecordAudioBitrate), SelectedRecordAudioBitrate); - SelectedRecordFrameRate = Config.Config.GetInt32(config, nameof(SelectedRecordFrameRate), SelectedRecordFrameRate); - RecordDirectory = Config.Config.GetString(config, nameof(RecordDirectory), RecordDirectory); - RegionSelectionMode = Config.Config.GetEnum(config, nameof(RegionSelectionMode), RegionSelectionMode); - - RecordMicrophone = Config.Config.GetBool(config, nameof(RecordMicrophone), RecordMicrophone); - - WindowLeft = Config.Config.GetDouble(config, nameof(WindowLeft), WindowLeft); - WindowTop = Config.Config.GetDouble(config, nameof(WindowTop), WindowTop); - - CaptureTimeControlled = Config.Config.GetBool(config, nameof(CaptureTimeControlled), CaptureTimeControlled); - var now = DateTime.Now; - now -= TimeSpan.FromMilliseconds(now.Second * 1000 + now.Millisecond); - CaptureStartTime = Config.Config.GetDateTime(config, nameof(CaptureStartTime), now); - CaptureStartTime -= TimeSpan.FromMilliseconds(CaptureStartTime.Second * 1000 + CaptureStartTime.Millisecond); - if (CaptureStartTime < now) - CaptureStartTime = now; - CaptureEndTime = Config.Config.GetDateTime(config, nameof(CaptureEndTime), now + TimeSpan.FromMinutes(10)); - CaptureEndTime -= TimeSpan.FromMilliseconds(CaptureEndTime.Second * 1000 + CaptureEndTime.Millisecond); - if (CaptureEndTime <= CaptureStartTime) - CaptureEndTime = CaptureStartTime + TimeSpan.FromMinutes(10); - ExitProgram = Config.Config.GetBool(config, nameof(ExitProgram), ExitProgram); - ShutDown = Config.Config.GetBool(config, nameof(ShutDown), ShutDown); - - ForceSourceSize = Config.Config.GetBool(config, nameof(ForceSourceSize), ForceSourceSize); - ForcedSourceWidth = Config.Config.GetInt32(config, nameof(ForcedSourceWidth), ForcedSourceWidth); - ForcedSourceHeight = Config.Config.GetInt32(config, nameof(ForcedSourceHeight), ForcedSourceHeight); + ScreenCaptureMonitor = Config.Config.GetString(config, nameof(ScreenCaptureMonitor), CaptureTarget.PrimaryCaptureTargetDeviceName); + ScreenCaptureCursorVisible = Config.Config.GetBool(config, nameof(ScreenCaptureCursorVisible), true); + + AdvancedSettings = Config.Config.GetBool(config, nameof(AdvancedSettings), false); + + SelectedRecordFormat = Config.Config.GetString(config, nameof(SelectedRecordFormat), "mp4"); + SelectedRecordVideoCodec = Config.Config.GetEnum(config, nameof(SelectedRecordVideoCodec), VideoCodec.H264); + SelectedRecordAudioCodec = Config.Config.GetEnum(config, nameof(SelectedRecordAudioCodec), AudioCodec.Aac); + SelectedRecordVideoBitrate = Config.Config.GetInt32(config, nameof(SelectedRecordVideoBitrate), 5000000); + SelectedRecordAudioBitrate = Config.Config.GetInt32(config, nameof(SelectedRecordAudioBitrate), 160000); + SelectedRecordFrameRate = Config.Config.GetInt32(config, nameof(SelectedRecordFrameRate), 60); + RecordDirectory = Config.Config.GetString(config, nameof(RecordDirectory), Environment.GetFolderPath(Environment.SpecialFolder.MyVideos)); + RegionSelectionMode = Config.Config.GetEnum(config, nameof(RegionSelectionMode), RegionSelectionMode.UserRegion); + + RecordMicrophone = Config.Config.GetBool(config, nameof(RecordMicrophone), false); + + WindowLeft = Config.Config.GetDouble(config, nameof(WindowLeft), -1.0d); + WindowTop = Config.Config.GetDouble(config, nameof(WindowTop), -1.0d); + } + else + { + SetDefault(); } } } @@ -157,12 +126,7 @@ public void SetDefault() WindowLeft = -1.0d; WindowTop = -1.0d; - // default is full primary monitor - ScreenCaptureMonitor = MonitorInfo.GetPrimaryMonitorInfo()?.DeviceName; - var monitorInfo = MonitorInfo.GetMonitorInfo(ScreenCaptureMonitor); - ScreenCaptureRect = monitorInfo == null ? (Rect?)null : new Rect(monitorInfo.Left, monitorInfo.Top, monitorInfo.Width, monitorInfo.Height); - AppManager.Instance.ScreenCaptureMonitorDescription = monitorInfo?.Description ?? ""; - + ScreenCaptureMonitor = CaptureTarget.PrimaryCaptureTargetDeviceName; ScreenCaptureCursorVisible = true; AdvancedSettings = false; @@ -177,15 +141,6 @@ public void SetDefault() RegionSelectionMode = RegionSelectionMode.UserRegion; RecordMicrophone = false; - - ForceSourceSize = false; - ForcedSourceWidth = 1280; // HDREADY - ForcedSourceHeight = 720; // HDREADY - - CaptureTimeControlled = false; - CaptureStartTime = DateTime.Now; - CaptureStartTime -= TimeSpan.FromMilliseconds(CaptureStartTime.Second * 1000 + CaptureStartTime.Millisecond); - CaptureEndTime = CaptureStartTime + TimeSpan.FromMinutes(10); } #endregion @@ -305,56 +260,6 @@ public bool ScreenCaptureCursorVisible get => screenCaptureCursorVisible; set => SetProperty(ref screenCaptureCursorVisible, value); } - - public Rect? ScreenCaptureRect - { - get => new Rect(ScreenCaptureRectLeft, ScreenCaptureRectTop, ScreenCaptureRectWidth, screenCaptureRectHeight); - set - { - if (value.HasValue) - { - ScreenCaptureRectTop = value.Value.Top; - ScreenCaptureRectLeft = value.Value.Left; - ScreenCaptureRectWidth = value.Value.Width; - ScreenCaptureRectHeight = value.Value.Height; - } - else - { - ScreenCaptureRectTop = 0; - ScreenCaptureRectLeft = 0; - ScreenCaptureRectWidth = 0; - ScreenCaptureRectHeight = 0; - } - } - } - - private double screenCaptureRectLeft; - public double ScreenCaptureRectLeft - { - get => Math.Max(0, screenCaptureRectLeft); - set => SetProperty(ref screenCaptureRectLeft, value); - } - - private double screenCaptureRectTop; - public double ScreenCaptureRectTop - { - get => Math.Max(0, screenCaptureRectTop); - set => SetProperty(ref screenCaptureRectTop, value); - } - - private double screenCaptureRectWidth; - public double ScreenCaptureRectWidth - { - get => Math.Max(0, screenCaptureRectWidth); - set => SetProperty(ref screenCaptureRectWidth, value); - } - - private double screenCaptureRectHeight; - public double ScreenCaptureRectHeight - { - get => Math.Max(0, screenCaptureRectHeight); - set => SetProperty(ref screenCaptureRectHeight, value); - } #endregion #region Audio @@ -366,78 +271,6 @@ public bool RecordMicrophone } #endregion - #region Force resize of source window - - private bool forceSourceSize; - public bool ForceSourceSize - { - get => forceSourceSize; - set => SetProperty(ref forceSourceSize, value); - } - - private int forcedSourceWidth; - public int ForcedSourceWidth - { - get => forcedSourceWidth; - set => SetProperty(ref forcedSourceWidth, value); - } - - private int forcedSourceHeight; - public int ForcedSourceHeight - { - get => forcedSourceHeight; - set => SetProperty(ref forcedSourceHeight, value); - } - - #endregion - - #region Time controlled capture - - private bool captureTimeControlled; - public bool CaptureTimeControlled - { - get => captureTimeControlled; - set => SetProperty(ref captureTimeControlled, value); - } - - private DateTime captureStartTime; - public DateTime CaptureStartTime - { - get => captureStartTime; - set => SetProperty(ref captureStartTime, value); - } - - private DateTime captureEndTime; - public DateTime CaptureEndTime - { - get => captureEndTime; - set => SetProperty(ref captureEndTime, value); - } - - private bool exitProgram; - public bool ExitProgram - { - get => exitProgram; - set - { - if (SetProperty(ref exitProgram, value) && !value) - ShutDown = false; - } - } - - private bool shutDown; - public bool ShutDown - { - get => shutDown; - set - { - if (SetProperty(ref shutDown, value) && value) - ExitProgram = true; - } - } - - #endregion - private bool advancedSettings; public bool AdvancedSettings { diff --git a/ScreenRecorder/AppManager.cs b/ScreenRecorder/AppManager.cs index 5ff4f01..7a17d53 100644 --- a/ScreenRecorder/AppManager.cs +++ b/ScreenRecorder/AppManager.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using System.Windows; @@ -99,27 +98,12 @@ public bool NotSupportedHwHevc private set => SetProperty(ref notSupportedHwHevc, value); } - private string screenCaptureMonitorDescription; - public string ScreenCaptureMonitorDescription - { - get => screenCaptureMonitorDescription; - set => SetProperty(ref screenCaptureMonitorDescription, value); - } - - private bool recordSettingChecked = false; - public bool RecordSettingChecked - { - get => recordSettingChecked; - set => SetProperty(ref recordSettingChecked, value); - } - public void Initialize() { if (IsInitialized) return; ScreenEncoder = new ScreenEncoder(); - ScreenEncoder.PropertyChanged += ScreenEncoder_PropertyChanged; EncoderFormats = new EncoderFormat[] { // recording @@ -154,11 +138,6 @@ public void Initialize() IsInitialized = true; } - private void ScreenEncoder_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) - { - NotifyPropertyChanged(new[] { e.PropertyName }); - } - private async void CheckHardwareCodec() { await Task.Run(() => @@ -171,13 +150,7 @@ await Task.Run(() => private void CompositionTarget_Rendering(object sender, EventArgs e) { - if (screenEncoder.TimeBeforeCapture != null) - { - var time = screenEncoder.TimeBeforeCapture.Value; - EncodeTime = $"{time.Hours:00}:{time.Minutes:00}:{time.Seconds:00} ..."; - } - else - EncodeTime = Utils.VideoFramesCountToStringTime(screenEncoder.VideoFramesCount); + EncodeTime = Utils.VideoFramesCountToStringTime(screenEncoder.VideoFramesCount); } public void Dispose() diff --git a/ScreenRecorder/CustomConverter/CustomConverter.cs b/ScreenRecorder/CustomConverter/CustomConverter.cs index 001445f..fc83f0b 100644 --- a/ScreenRecorder/CustomConverter/CustomConverter.cs +++ b/ScreenRecorder/CustomConverter/CustomConverter.cs @@ -90,19 +90,4 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu #endregion } - - public class InvertBooleanConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (!(value is bool)) - return DependencyProperty.UnsetValue; - return !(bool)value; - } - - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - return Convert(value, targetType, parameter, culture); - } - } } diff --git a/ScreenRecorder/Encoder/Encoder.cs b/ScreenRecorder/Encoder/Encoder.cs index 30338c0..fd273ab 100644 --- a/ScreenRecorder/Encoder/Encoder.cs +++ b/ScreenRecorder/Encoder/Encoder.cs @@ -2,8 +2,6 @@ using System.Collections.Concurrent; using System.Runtime.InteropServices; using System.Threading; -using System.Diagnostics; -using System.Timers; using MediaEncoder; using ScreenRecorder.AudioSource; using ScreenRecorder.VideoSource; @@ -352,9 +350,6 @@ private class EncoderArguments public int VideoBitrate { get; set; } public int AudioBitrate { get; set; } public VideoSize VideoSize { get; set; } - - public DateTime? StartTime { get; set; } - public DateTime? EndTime { get; set; } } private ulong videoFramesCount; @@ -402,16 +397,6 @@ private set } } - private bool isStartedWithEncode = false; - public bool IsStartedWithEncode - { - get => isStartedWithEncode; - private set - { - SetProperty(ref isStartedWithEncode, value); - } - } - private bool isPaused = false; public bool IsPaused { @@ -440,8 +425,7 @@ private set { if (SetProperty(ref status, value)) { - IsStarted = (value == EncoderStatus.Start || value == EncoderStatus.Wait); - IsStartedWithEncode = (value == EncoderStatus.Start); + IsStarted = (value == EncoderStatus.Start); IsPaused = (value == EncoderStatus.Pause); IsStopped = (value == EncoderStatus.Stop); } @@ -486,8 +470,7 @@ protected virtual void OnEncoderStopped(EncoderStoppedEventArgs args) private Thread workerThread = null; private ManualResetEvent needToStop = null; - public void Start(string format, string url, IVideoSource videoSource, VideoCodec videoCodec, int videoBitrate, VideoSize videoSize, - IAudioSource audioSource, AudioCodec audioCodec, int audioBitrate, DateTime? captureStart, DateTime? captureEnd) + public void Start(string format, string url, IVideoSource videoSource, VideoCodec videoCodec, int videoBitrate, VideoSize videoSize, IAudioSource audioSource, AudioCodec audioCodec, int audioBitrate) { if (IsRunning) return; @@ -509,8 +492,6 @@ public void Start(string format, string url, IVideoSource videoSource, VideoCode VideoSize = videoSize, AudioCodec = audioCodec, AudioBitrate = audioBitrate, - StartTime = captureStart, - EndTime = captureEnd }); } @@ -532,22 +513,23 @@ public void Pause() public void Stop() { - needToStop?.Set(); - _captureCanBegin?.Set(); + if (!IsRunning) + return; + if (needToStop != null) + { + needToStop.Set(); + } if (workerThread != null) { if (workerThread.IsAlive && !workerThread.Join(3000)) workerThread.Abort(); - } - workerThread = null; + workerThread = null; - needToStop?.Close(); - needToStop = null; - _captureCanBegin?.Close(); - _captureCanBegin = null; - _waitTimer?.Dispose(); - _waitTimer = null; + if (needToStop != null) + needToStop.Close(); + needToStop = null; + } VideoFramesCount = 0; AudioSamplesCount = 0; @@ -555,53 +537,12 @@ public void Stop() Status = EncoderStatus.Stop; } - public TimeSpan? TimeBeforeCapture { get; private set; } - - private System.Timers.Timer _waitTimer; - private DateTime _captureStart; - private ManualResetEvent _captureCanBegin; - - private void TimerHandler(object src, ElapsedEventArgs args) - { - if (_captureStart == null || needToStop == null) - return; - var now = DateTime.Now; - if (now >= _captureStart || needToStop.WaitOne(0)) - { - TimeBeforeCapture = null; - _waitTimer.Stop(); - _captureCanBegin.Set(); - } - else - TimeBeforeCapture = _captureStart - now; - } - private void WorkerThreadHandler(object argument) { try { - TimeBeforeCapture = null; if (argument is EncoderArguments encoderArguments) { - if (encoderArguments.StartTime != null) - { - Status = EncoderStatus.Wait; - _captureStart = encoderArguments.StartTime.Value - TimeSpan.FromSeconds(1); - Debug.Assert(_captureCanBegin == null); - _captureCanBegin = new ManualResetEvent(false); - Debug.Assert(_waitTimer == null); - _waitTimer?.Dispose(); - _waitTimer = new System.Timers.Timer(250); - _waitTimer.Elapsed += TimerHandler; - _waitTimer.Start(); - if (_captureCanBegin.WaitOne()) - { - if (needToStop.WaitOne(0, false)) - return; - } - } - Status = EncoderStatus.Start; - using (MediaBuffer mediaBuffer = new MediaBuffer(encoderArguments.VideoSource, encoderArguments.AudioCodec == AudioCodec.None ? null : encoderArguments.AudioSource)) { using (MediaWriter mediaWriter = new MediaWriter( @@ -649,14 +590,6 @@ private void WorkerThreadHandler(object argument) if (needToStop.WaitOne(1, false)) break; } - if (encoderArguments.EndTime != null) - { - if (DateTime.Now >= encoderArguments.EndTime) - { - needToStop?.Set(); - break; - } - } } } } @@ -673,7 +606,6 @@ private void WorkerThreadHandler(object argument) AudioSamplesCount = 0; Url = ""; Status = EncoderStatus.Stop; - TimeBeforeCapture = null; } } diff --git a/ScreenRecorder/Encoder/EncoderStatus.cs b/ScreenRecorder/Encoder/EncoderStatus.cs index 6dc5012..7118e22 100644 --- a/ScreenRecorder/Encoder/EncoderStatus.cs +++ b/ScreenRecorder/Encoder/EncoderStatus.cs @@ -16,10 +16,6 @@ public enum EncoderStatus /// /// Encoder Stopped /// - Stop, - /// - /// Encoder waiting time after start - /// - Wait + Stop } } diff --git a/ScreenRecorder/Encoder/ScreenEncoder.cs b/ScreenRecorder/Encoder/ScreenEncoder.cs index 4ee9841..9524b36 100644 --- a/ScreenRecorder/Encoder/ScreenEncoder.cs +++ b/ScreenRecorder/Encoder/ScreenEncoder.cs @@ -21,21 +21,16 @@ public class ScreenEncoder : Encoder private AudioCaptureSource audioCaptureSource; private Utils.ThreadExecutionState? oldSleepState; - public bool StopByAutomatic { get; set; } - public ScreenEncoder() { this.EncoderStopped += ScreenEncoder_EncoderStopped; } - public void Start(string format, string url, VideoCodec videoCodec, int videoBitrate, AudioCodec audioCodec, int audioBitrate, string deviceName, - Rect region, bool drawCursor, bool recordMicrophone, DateTime? captureStart, DateTime? captureEnd) + public void Start(string format, string url, VideoCodec videoCodec, int videoBitrate, AudioCodec audioCodec, int audioBitrate, string deviceName, Rect region, bool drawCursor, bool recordMicrophone) { if (base.IsRunning) return; - StopByAutomatic = AppConfig.Instance.CaptureTimeControlled; - // to be on the safe side Debug.Assert(screenVideoSource == null); Debug.Assert(loopbackAudioSource == null); @@ -69,7 +64,7 @@ public void Start(string format, string url, VideoCodec videoCodec, int videoBit Rect validRegion = Rect.Intersect(region, new Rect(0, 0, monitorInfo.Width, monitorInfo.Height)); base.Start(format, url, screenVideoSource, videoCodec, videoBitrate, new VideoSize((int)validRegion.Width, (int)validRegion.Height), - audioSource, audioCodec, audioBitrate, captureStart, captureEnd); + audioSource, audioCodec, audioBitrate); } catch (Exception ex) { @@ -98,12 +93,7 @@ private void ScreenEncoder_EncoderStopped(object sender, EncoderStoppedEventArgs if (oldSleepState.HasValue) { Utils.SetThreadExecutionState(oldSleepState.Value); - oldSleepState = null; - } - // prevent closing of program for manual stop of time controlled capture - if (AppConfig.Instance.CaptureTimeControlled && StopByAutomatic && AppConfig.Instance.ExitProgram) - { - Utils.ExitProgram(AppConfig.Instance.ShutDown); + oldSleepState = null; ; } } } diff --git a/ScreenRecorder/Icons.xaml b/ScreenRecorder/Icons.xaml index 1ee76a8..9fad768 100644 --- a/ScreenRecorder/Icons.xaml +++ b/ScreenRecorder/Icons.xaml @@ -33,5 +33,4 @@ - \ No newline at end of file diff --git a/ScreenRecorder/MainWindow.HwndSourceHook.cs b/ScreenRecorder/MainWindow.HwndSourceHook.cs new file mode 100644 index 0000000..e15f83a --- /dev/null +++ b/ScreenRecorder/MainWindow.HwndSourceHook.cs @@ -0,0 +1,95 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Input; +using System.Windows.Interop; + +namespace ScreenRecorder +{ + public partial class MainWindow + { + [StructLayout(LayoutKind.Sequential)] + public struct WINDOWPOS + { + public IntPtr hwnd; + public IntPtr hwndInsertAfter; + public int x; + public int y; + public int cx; + public int cy; + public int flags; + } + + private IntPtr windowHandle = IntPtr.Zero; + + protected override void OnSourceInitialized(EventArgs e) + { + base.OnSourceInitialized(e); + + HwndSource source = (HwndSource)HwndSource.FromVisual((Window)this); + source.AddHook(new HwndSourceHook(WndProc)); + windowHandle = source.Handle; + + // 자기 자신은 캡쳐가 안 되도록 하기 위해 사용 + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowdisplayaffinity +#if !DEBUG + Utils.SetWindowDisplayedOnlyMonitor(source.Handle, true); +#endif + } + + private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + var message = System.Windows.Forms.Message.Create(hwnd, msg, wParam, lParam); + + switch (msg) + { + case 0x0046: + #region Magnetic Move + if (windowHandle != IntPtr.Zero) + { + WINDOWPOS windowPos = (WINDOWPOS)message.GetLParam(typeof(WINDOWPOS)); + + System.Drawing.Rectangle workingArea = (System.Windows.Forms.Screen.FromHandle(windowHandle)).WorkingArea; + + int dockMargin = 15; + //left + if (Math.Abs(windowPos.x - workingArea.Left) <= dockMargin) + { + windowPos.x = workingArea.Left; + } + + //top + if (Math.Abs(windowPos.y - workingArea.Top) <= dockMargin) + { + windowPos.y = workingArea.Top; + } + + //right + if (Math.Abs(windowPos.x + windowPos.cx - workingArea.Left - workingArea.Width) <= dockMargin) + { + windowPos.x = workingArea.Right - windowPos.cx; + } + + //bottom + if (Math.Abs(windowPos.y + windowPos.cy - workingArea.Top - workingArea.Height) <= dockMargin) + { + windowPos.y = (int)(workingArea.Bottom - windowPos.cy); + } + Marshal.StructureToPtr(windowPos, lParam, false); + } + #endregion + break; + } + + return IntPtr.Zero; + } + + #region Window Moving + private void Border_MouseDown(object sender, MouseButtonEventArgs e) + { + if (e.ChangedButton == MouseButton.Left) + DragMove(); + } + #endregion + } +} diff --git a/ScreenRecorder/MainWindow.xaml b/ScreenRecorder/MainWindow.xaml index 874236e..b47dafd 100644 --- a/ScreenRecorder/MainWindow.xaml +++ b/ScreenRecorder/MainWindow.xaml @@ -12,7 +12,7 @@ Icon="pack://application:,,,/icon.ico" SnapsToDevicePixels="True" Left="{Binding Source={x:Static local:AppConfig.Instance}, Path=WindowLeft, Mode=TwoWay}" Top="{Binding Source={x:Static local:AppConfig.Instance}, Path=WindowTop, Mode=TwoWay}" - WindowStyle="None" ResizeMode="CanMinimize" Background="Transparent" AllowsTransparency="False" Topmost="True" WindowStartupLocation="Manual" + WindowStyle="None" ResizeMode="NoResize" Background="Transparent" AllowsTransparency="False" Topmost="True" WindowStartupLocation="Manual" Title="" Height="72" MinWidth="240" SizeToContent="Width"> @@ -20,7 +20,6 @@ - - - - - @@ -90,9 +85,8 @@ -