{
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;
}
}
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);
}
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))
{
_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);
}
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;
}
catch (CaptureError e)
{
- CaptureResult = e.Message;
+ CaptureResult = e.Summary;
+ throw;
}
}
}
catch (CaptureError e)
{
- CaptureResult = e.Message;
+ CaptureResult = e.Summary;
Capturing = false;
+ throw;
}
}
}
catch (CaptureError e)
{
- CaptureResult = e.Message;
+ CaptureResult = e.Summary;
+ throw;
}
finally
{
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
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");
}
<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}"/>
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; }
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});
}
}
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
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
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
{
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; }
<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">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
+ <RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
</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"/>
}
/// <summary>
+ /// Can'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'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 {
}
/// <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 {
}
/// <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 {
return ResourceManager.GetString("OptionView_Interval", resourceCulture);
}
}
-
+
/// <summary>
/// Option に類似しているローカライズされた文字列を検索します。
/// </summary>
return ResourceManager.GetString("OptionView_Option", resourceCulture);
}
}
+
+ /// <summary>
+ /// Notify に類似しているローカライズされた文字列を検索します。
+ /// </summary>
+ public static string OptionView_Notify {
+ get {
+ return ResourceManager.GetString("OptionView_Notify", resourceCulture);
+ }
+ }
/// <summary>
/// Pick window に類似しているローカライズされた文字列を検索します。
}
/// <summary>
+ /// Can'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 {
<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
<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
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)
{
? _screenCapture.CaptureGameScreen(_config.TitleHistory)
: _screenCapture.CaptureGameScreen();
var now = DateTime.Now;
- ReportCaptureResult(now);
+ ReportCaptureResult(_screenCapture.Title, now);
return new Frame {Time = now, Bitmap = bmp};
}
}
catch (IOException)
{
- throw new CaptureError(Resources.Recorder_IO_error);
+ throw new CaptureError(Resources.Recorder_IO_error, Resources.Recorder_Cant_output_image_file);
}
finally
{
}
catch (IOException)
{
- throw new CaptureError(Resources.Recorder_IO_error);
+ throw new CaptureError(Resources.Recorder_IO_error, Resources.Recorder_Cant_output_image_file);
}
finally
{