OSDN Git Service

Show a balloon tip when captured
authorKazuhiro Fujieda <fujieda@users.osdn.me>
Wed, 21 Sep 2016 11:21:03 +0000 (20:21 +0900)
committerKazuhiro Fujieda <fujieda@users.osdn.me>
Sat, 24 Sep 2016 10:50:46 +0000 (19:50 +0900)
12 files changed:
BurageSnap/Capture.cs
BurageSnap/Config.cs
BurageSnap/Main.cs
BurageSnap/MainWindow.xaml
BurageSnap/MainWindowViewModel.cs
BurageSnap/NotifyIconWrapper.cs
BurageSnap/OptionContent.cs
BurageSnap/OptionView.xaml
BurageSnap/Properties/Resources.Designer.cs
BurageSnap/Properties/Resources.ja.resx
BurageSnap/Properties/Resources.resx
BurageSnap/Recorder.cs

index 0863ba7..07e708f 100644 (file)
@@ -24,8 +24,11 @@ namespace BurageSnap
 {
     public class CaptureError : Exception
     {
-        public CaptureError(string message) : base(message)
+        public string Summary { get; private set; }
+
+        public CaptureError(string summary, string message) : base(message)
         {
+            Summary = summary;
         }
     }
 
@@ -35,12 +38,13 @@ namespace BurageSnap
         private IntPtr _hWnd;
         private Rect _windowRect;
         private Rectangle _rectangle;
-        private string _title;
+
+        public string Title { get; private set; }
 
         public Bitmap CaptureGameScreen()
         {
             if (_hWnd == IntPtr.Zero || _rectangle.IsEmpty)
-                throw new CaptureError(Resources.Capture_Internal_error);
+                throw new CaptureError(Resources.Capture_Internal_error, Resources.Capture_Internal_error);
             using (var bmp = CaptureWindow(_hWnd, _windowRect))
                 return bmp.Clone(_rectangle, bmp.PixelFormat);
         }
@@ -50,7 +54,8 @@ namespace BurageSnap
             int index;
             _hWnd = FindWindow(titles, out index);
             if (_hWnd == IntPtr.Zero)
-                throw new CaptureError(Resources.Capture_Search_error);
+                throw new CaptureError(Resources.Capture_Search_error,
+                    Resources.Capture_Cant_find_window);
             var rect = new Rect();
             GetWindowRect(_hWnd, ref rect);
             using (var bmp = CaptureWindow(_hWnd, rect))
@@ -60,14 +65,15 @@ namespace BurageSnap
                 {
                     _windowRect = rect;
                     _rectangle = rectangle;
-                    _title = titles[index];
+                    Title = titles[index];
                 }
                 else
                 {
                     using (var file = File.Create("debug.png"))
                         bmp.Save(file, ImageFormat.Png);
-                    if (_rectangle.IsEmpty || !_windowRect.Equals(rect) || _title != titles[index])
-                        throw new CaptureError(Resources.Capture_Extract_error);
+                    if (_rectangle.IsEmpty || !_windowRect.Equals(rect) || Title != titles[index])
+                        throw new CaptureError(Resources.Capture_Extract_error,
+                            Resources.Capture_Cant_extract_game_screen);
                 }
                 return bmp.Clone(_rectangle, bmp.PixelFormat);
             }
index 20b008c..6edcd3a 100644 (file)
@@ -32,6 +32,7 @@ namespace BurageSnap
         public Point Location { get; set; } = new Point(double.MinValue, double.MinValue);
         public bool TopMost { get; set; }
         public bool ResideInSystemTray { get; set; }
+        public bool Notify { get; set; } = true;
         public WindowState WindowState { get; set; }
         public int Interval { get; set; } = 200;
         public int RingBuffer { get; set; } = 25;
index 7282023..d48189d 100644 (file)
@@ -38,7 +38,8 @@ namespace BurageSnap
             }
             catch (CaptureError e)
             {
-                CaptureResult = e.Message;
+                CaptureResult = e.Summary;
+                throw;
             }
         }
 
@@ -51,8 +52,9 @@ namespace BurageSnap
             }
             catch (CaptureError e)
             {
-                CaptureResult = e.Message;
+                CaptureResult = e.Summary;
                 Capturing = false;
+                throw;
             }
         }
 
@@ -69,7 +71,8 @@ namespace BurageSnap
             }
             catch (CaptureError e)
             {
-                CaptureResult = e.Message;
+                CaptureResult = e.Summary;
+                throw;
             }
             finally
             {
@@ -83,6 +86,14 @@ namespace BurageSnap
             Capturing = false;
         }
 
+        private string _windowTitle = "";
+
+        public string WindowTitle
+        {
+            get { return _windowTitle; }
+            set { SetProperty(ref _windowTitle, value); }
+        }
+
         private string _captureResult = "00:00:00.000";
 
         public string CaptureResult
@@ -99,8 +110,9 @@ namespace BurageSnap
             set { SetProperty(ref _capturing, value); }
         }
 
-        private void ReportCaptureResult(DateTime time)
+        private void ReportCaptureResult(string title, DateTime time)
         {
+            WindowTitle = title;
             CaptureResult = time.ToString("HH:mm:ss.fff");
         }
 
index 4469c06..0b53bd7 100644 (file)
@@ -27,6 +27,9 @@
                 <i:EventTrigger EventName="ExitSelected">
                     <i:InvokeCommandAction Command="{Binding NotifyIconExitCommand}"/>
                 </i:EventTrigger>
+                <prism:InteractionRequestTrigger SourceObject="{Binding ShowBaloonTipRequest, Mode=OneWay}">
+                    <local:ShowBaloonTipAction/>
+                </prism:InteractionRequestTrigger>
             </i:Interaction.Triggers>
         </local:NotifyIconWrapper>
         <Button x:Name="buttonCapture" Content="{Binding CaptureButtonText}" HorizontalAlignment="Left" Margin="8,8,0,0" VerticalAlignment="Top" Width="77" Height="51" FontSize="12" Command="{Binding CaptureCommand}"/>
index f2e661c..21a3743 100644 (file)
@@ -36,6 +36,9 @@ namespace BurageSnap
         public ICommand NotifyIconOpenCommand { get; private set; }
         public ICommand NotifyIconExitCommand { get; private set; }
 
+        public InteractionRequest<INotification> ShowBaloonTipRequest { get; } =
+            new InteractionRequest<INotification>();
+
         public bool BurstMode
         {
             get { return Main.Config.Continuous; }
@@ -181,19 +184,30 @@ namespace BurageSnap
 
         private void Capture()
         {
-            if (!BurstMode)
-            {
-                Main.OneShot();
-                return;
-            }
-            if (!Main.Capturing)
+            try
             {
-                Main.StartCapture();
+                if (!BurstMode)
+                {
+                    Main.OneShot();
+                    Notify(Resources.MainWindow_Captured);
+                    return;
+                }
+                if (!Main.Capturing)
+                {
+                    Main.StartCapture();
+                    Notify(Resources.MainWindow_Capture_started);
+                }
+                else
+                {
+                    Main.StopCapture();
+                    Notify(Resources.MainWindow_Capture_ended);
+                    ConfirmSaveBuffer();
+                }
             }
-            else
+            catch (CaptureError e)
             {
-                Main.StopCapture();
-                ConfirmSaveBuffer();
+                if (Main.Config.Notify)
+                    ShowBaloonTipRequest.Raise(new Notification {Title = Resources.MainWindow_Error, Content = e.Message});
             }
         }
 
@@ -208,5 +222,24 @@ namespace BurageSnap
                     Main.DiscardBuffer();
             });
         }
+
+        private void Notify(string message)
+        {
+            if (!Main.Config.Notify)
+                return;
+            var title = Main.WindowTitle;
+            if (title == "")
+            {
+                ShowBaloonTipRequest.Raise(new Notification
+                {
+                    Title = Resources.MainWindow_Error,
+                    Content = Main.CaptureResult
+                });
+                return;
+            }
+            if (title.Length > 22)
+                title = title.Substring(0, 22) + "...";
+            ShowBaloonTipRequest.Raise(new Notification {Title = message, Content = title});
+        }
     }
 }
\ No newline at end of file
index 3b0ab9e..15e65d5 100644 (file)
@@ -18,6 +18,8 @@ using System.Drawing;
 using System.Reflection;
 using System.Windows;
 using System.Windows.Forms;
+using System.Windows.Interactivity;
+using Prism.Interactivity.InteractionRequest;
 using Application = System.Windows.Application;
 
 namespace BurageSnap
@@ -98,9 +100,25 @@ namespace BurageSnap
             RaiseEvent(args);
         }
 
+        public void ShowBaloonTip(string tipTitle, string tipText)
+        {
+            _notifyIcon.ShowBalloonTip(1000, tipTitle, tipText, ToolTipIcon.Info);
+        }
+
         public void Dispose()
         {
             _notifyIcon.Dispose();
         }
     }
+
+    public class ShowBaloonTipAction : TriggerAction<NotifyIconWrapper>
+    {
+        protected override void Invoke(object parameter)
+        {
+            var notification = (parameter as InteractionRequestedEventArgs)?.Context as Notification;
+            if (notification == null)
+                return;
+            AssociatedObject.ShowBaloonTip(notification.Title, (string)notification.Content);
+        }
+    }
 }
\ No newline at end of file
index e898371..1506d95 100644 (file)
@@ -21,6 +21,7 @@ namespace BurageSnap
     {
         public bool TopMost { get; set; }
         public bool ResideInSystemTray { get; set; }
+        public bool Notify { get; set; }
         public int Interval { get; set; }
         public int RingBuffer { get; set; }
         public ObservableCollection<string> WindowTitles { get; set; }
index a1ff61a..7acb89d 100644 (file)
@@ -29,9 +29,9 @@
     <UserControl.DataContext>
         <local:OptionViewModel/>
     </UserControl.DataContext>
-    <Grid Width="510" Height="295">
-        <Button x:Name="buttonOk" Content="Ok" HorizontalAlignment="Left" Margin="345,255,0,0" VerticalAlignment="Top" Width="75" Command="{Binding OkCommand}" IsDefault="True"/>
-        <Button x:Name="buttonCancel" Content="{x:Static proprties:Resources.OptionView_Cancel}" HorizontalAlignment="Left" Margin="425,255,0,0" VerticalAlignment="Top" Width="75" Command="{Binding CancelCommand}" IsCancel="True"/>
+    <Grid Width="510" Height="320">
+        <Button x:Name="buttonOk" Content="Ok" HorizontalAlignment="Left" Margin="345,280,0,0" VerticalAlignment="Top" Width="75" Command="{Binding OkCommand}" IsDefault="True"/>
+        <Button x:Name="buttonCancel" Content="{x:Static proprties:Resources.OptionView_Cancel}" HorizontalAlignment="Left" Margin="425,280,0,0" VerticalAlignment="Top" Width="75" Command="{Binding CancelCommand}" IsCancel="True"/>
         <DockPanel HorizontalAlignment="Stretch" VerticalAlignment="Top">
             <StackPanel Margin="20 15 10 10" HorizontalAlignment="Left" VerticalAlignment="Top" DockPanel.Dock="Right">
                 <Grid HorizontalAlignment="Left" Margin="0 0 0 15" VerticalAlignment="Top">
@@ -67,6 +67,7 @@
                     <Grid.RowDefinitions>
                         <RowDefinition/>
                         <RowDefinition/>
+                        <RowDefinition/>
                     </Grid.RowDefinitions>
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition Width="Auto"/>
@@ -74,7 +75,8 @@
                     </Grid.ColumnDefinitions>
                     <Label x:Name="labelWindow" Content="{x:Static proprties:Resources.OptionView_Window}" Margin="0 0 5 0"/>
                     <CheckBox x:Name="checkBoxTopMost" Content="{x:Static proprties:Resources.OptionView_Top_most}" Grid.Row="0" Grid.Column="1" Margin="0 0 0 5" IsChecked="{Binding Options.TopMost}"/>
-                    <CheckBox x:Name="checkBoxHideOnMinimize" Content="{x:Static proprties:Resources.OptionView_Reside_in_system_tray}" Grid.Row="1" Grid.Column="1" IsChecked="{Binding Options.ResideInSystemTray}"/>
+                    <CheckBox x:Name="checkBoxHideOnMinimize" Content="{x:Static proprties:Resources.OptionView_Reside_in_system_tray}" Grid.Row="1" Grid.Column="1" Margin="0 0 0 5" IsChecked="{Binding Options.ResideInSystemTray}"/>
+                    <CheckBox x:Name="checkBoxNotify" Content="{x:Static proprties:Resources.OptionView_Notify}" Grid.Row="2" Grid.Column="1" IsChecked="{Binding Options.Notify}"/>
                 </Grid>
                 <Grid HorizontalAlignment="Left"  VerticalAlignment="Top" Margin="0 0 0 0">
                     <Grid.RowDefinitions>
                 </DockPanel>
                 <CheckBox x:Name="checkBoxDailyFolder" Content="{x:Static proprties:Resources.OptionView_Create_daily_folders}" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 0 0 5" IsChecked="{Binding Options.DailyFolder}"/>
                 <Label x:Name="labelTargetWindows" Content="{x:Static proprties:Resources.OptionView_Target_windows}" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0 0 0 3"/>
-                <ListBox x:Name="listBox" ItemsSource="{Binding Options.WindowTitles}" HorizontalAlignment="Stretch" VerticalAlignment="Top" Height="110" BorderThickness="1" Margin="0 0 0 2">
+                <ListBox x:Name="listBox" ItemsSource="{Binding Options.WindowTitles}" HorizontalAlignment="Stretch" VerticalAlignment="Top" Height="122" BorderThickness="1" Margin="0 0 0 2">
                     <i:Interaction.Triggers>
                         <i:EventTrigger EventName="SelectionChanged">
                             <prism:InvokeCommandAction Command="{Binding SelectedCommand}" TriggerParameterPath="AddedItems"/>
index fb51ff9..b244ff9 100644 (file)
@@ -61,6 +61,24 @@ namespace BurageSnap.Properties {
         }
         
         /// <summary>
+        ///   Can&apos;t extract a game screen. に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Capture_Cant_extract_game_screen {
+            get {
+                return ResourceManager.GetString("Capture_Cant_extract_game_screen", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Can&apos;t find a window. に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Capture_Cant_find_window {
+            get {
+                return ResourceManager.GetString("Capture_Cant_find_window", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Extract error に類似しているローカライズされた文字列を検索します。
         /// </summary>
         public static string Capture_Extract_error {
@@ -163,6 +181,33 @@ namespace BurageSnap.Properties {
         }
         
         /// <summary>
+        ///   Capture ended に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string MainWindow_Capture_ended {
+            get {
+                return ResourceManager.GetString("MainWindow_Capture_ended", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Capture started に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string MainWindow_Capture_started {
+            get {
+                return ResourceManager.GetString("MainWindow_Capture_started", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Captured に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string MainWindow_Captured {
+            get {
+                return ResourceManager.GetString("MainWindow_Captured", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Burst に類似しているローカライズされた文字列を検索します。
         /// </summary>
         public static string MainWindow_Continuous {
@@ -172,6 +217,15 @@ namespace BurageSnap.Properties {
         }
         
         /// <summary>
+        ///   Error に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string MainWindow_Error {
+            get {
+                return ResourceManager.GetString("MainWindow_Error", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   Last snap に類似しているローカライズされた文字列を検索します。
         /// </summary>
         public static string MainWindow_Last_snap {
@@ -296,7 +350,7 @@ namespace BurageSnap.Properties {
                 return ResourceManager.GetString("OptionView_Interval", resourceCulture);
             }
         }
-        
+
         /// <summary>
         ///   Option に類似しているローカライズされた文字列を検索します。
         /// </summary>
@@ -305,6 +359,15 @@ namespace BurageSnap.Properties {
                 return ResourceManager.GetString("OptionView_Option", resourceCulture);
             }
         }
+
+        /// <summary>
+        ///   Notify に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string OptionView_Notify {
+            get {
+                return ResourceManager.GetString("OptionView_Notify", resourceCulture);
+            }
+        }
         
         /// <summary>
         ///   Pick window に類似しているローカライズされた文字列を検索します。
@@ -370,6 +433,15 @@ namespace BurageSnap.Properties {
         }
         
         /// <summary>
+        ///   Can&apos;t output a image file に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Recorder_Cant_output_image_file {
+            get {
+                return ResourceManager.GetString("Recorder_Cant_output_image_file", resourceCulture);
+            }
+        }
+        
+        /// <summary>
         ///   I/O error に類似しているローカライズされた文字列を検索します。
         /// </summary>
         public static string Recorder_IO_error {
index 6888e26..d08b49f 100644 (file)
   <data name="Capture_Search_error" xml:space="preserve">
     <value>検索エラー</value>
   </data>
+  <data name="Capture_Cant_extract_game_screen" xml:space="preserve">
+    <value>ゲーム画面を抽出できません。</value>
+  </data>
+  <data name="Capture_Cant_find_window" xml:space="preserve">
+    <value>ウィンドウが見つかりません。</value>
+  </data>
+  <data name="Recorder_Cant_output_image_file" xml:space="preserve">
+    <value>画像ファイルを出力できません。</value>
+  </data>
+  <data name="MainWindow_Captured" xml:space="preserve">
+    <value>撮影しました</value>
+  </data>
+  <data name="MainWindow_Capture_ended" xml:space="preserve">
+    <value>撮影を終了しました</value>
+  </data>
+  <data name="MainWindow_Capture_started" xml:space="preserve">
+    <value>撮影を開始しました</value>
+  </data>
+  <data name="MainWindow_Error" xml:space="preserve">
+    <value>エラー</value>
+  </data>
+  <data name="OptionView_Notify" xml:space="preserve">
+    <value>通知する</value>
+  </data>
 </root>
\ No newline at end of file
index 9ebf7eb..39caa46 100644 (file)
   <data name="Capture_Internal_error" xml:space="preserve">
     <value>Internal error</value>
   </data>
+  <data name="Capture_Cant_extract_game_screen" xml:space="preserve">
+    <value>Can't extract a game screen.</value>
+  </data>
+  <data name="Capture_Cant_find_window" xml:space="preserve">
+    <value>Can't find a window.</value>
+  </data>
+  <data name="Recorder_Cant_output_image_file" xml:space="preserve">
+    <value>Can't output a image file</value>
+  </data>
+  <data name="MainWindow_Captured" xml:space="preserve">
+    <value>Captured</value>
+  </data>
+  <data name="MainWindow_Capture_ended" xml:space="preserve">
+    <value>Capture ended</value>
+  </data>
+  <data name="MainWindow_Capture_started" xml:space="preserve">
+    <value>Capture started</value>
+  </data>
+  <data name="MainWindow_Error" xml:space="preserve">
+    <value>Error</value>
+  </data>
+  <data name="OptionView_Notify" xml:space="preserve">
+    <value>Notify</value>
+  </data>
 </root>
\ No newline at end of file
index c2f3a3b..3511171 100644 (file)
@@ -34,7 +34,7 @@ namespace BurageSnap
         private uint _timerId;
         private TimeProc _timeProc;
         private readonly object _lockObj = new object();
-        public Action<DateTime> ReportCaptureResult { private get; set; }
+        public Action<string, DateTime> ReportCaptureResult { private get; set; }
 
         public Recorder(Config config)
         {
@@ -111,7 +111,7 @@ namespace BurageSnap
                 ? _screenCapture.CaptureGameScreen(_config.TitleHistory)
                 : _screenCapture.CaptureGameScreen();
             var now = DateTime.Now;
-            ReportCaptureResult(now);
+            ReportCaptureResult(_screenCapture.Title, now);
             return new Frame {Time = now, Bitmap = bmp};
         }
 
@@ -124,7 +124,7 @@ namespace BurageSnap
             }
             catch (IOException)
             {
-                throw new CaptureError(Resources.Recorder_IO_error);
+                throw new CaptureError(Resources.Recorder_IO_error, Resources.Recorder_Cant_output_image_file);
             }
             finally
             {
@@ -170,7 +170,7 @@ namespace BurageSnap
             }
             catch (IOException)
             {
-                throw new CaptureError(Resources.Recorder_IO_error);
+                throw new CaptureError(Resources.Recorder_IO_error, Resources.Recorder_Cant_output_image_file);
             }
             finally
             {