런처 클립보드 이미지 미리보기 창을 추가하고 개발 문서 이력 기록 규칙을 반영\n\n- Phase L2-3로 클립보드 이미지 전용 미리보기 창 ClipboardImagePreviewWindow를 신규 추가\n- 원본 해상도 이미지 표시, Ctrl+휠 및 + / - / 0 / F / Esc 단축키 기반 줌 조작 지원\n- PNG, JPEG, BMP 저장과 클립보드 복사 기능을 미리보기 창에서 바로 수행 가능하도록 구현\n- LauncherWindow에서 # 클립보드 이미지 항목 선택 후 Shift+Enter로 미리보기 창을 여는 흐름 추가\n- 단축키 도움말에 클립보드 이미지 미리보기 동작을 반영\n- 런처 CenterOnScreen을 마우스가 위치한 모니터 기준으로 보정해 다중 디스플레이 표시 위치를 개선\n- AGENTS.md에 README.md, docs/DEVELOPMENT.md 이력 선반영 및 업데이트 날짜/시간 기록 규칙을 추가\n- README.md, docs/DEVELOPMENT.md, docs/LAUNCHER_ROADMAP.md에 v0.7.3 이력과 2026-04-04 10:05 (KST) 업데이트 시각 반영\n- dotnet build 경고 0 / 오류 0, dotnet test 436 통과 확인
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
This commit is contained in:
214
src/AxCopilot/Views/ClipboardImagePreviewWindow.xaml
Normal file
214
src/AxCopilot/Views/ClipboardImagePreviewWindow.xaml
Normal file
@@ -0,0 +1,214 @@
|
||||
<Window x:Class="AxCopilot.Views.ClipboardImagePreviewWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="클립보드 이미지 미리보기"
|
||||
Width="1080"
|
||||
Height="760"
|
||||
MinWidth="760"
|
||||
MinHeight="560"
|
||||
WindowStyle="None"
|
||||
AllowsTransparency="True"
|
||||
ResizeMode="CanResizeWithGrip"
|
||||
Background="Transparent"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
KeyDown="Window_KeyDown">
|
||||
<Grid Margin="14">
|
||||
<Border CornerRadius="18"
|
||||
Background="{DynamicResource LauncherBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="1">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="24" ShadowDepth="4" Opacity="0.22" Color="Black"/>
|
||||
</Border.Effect>
|
||||
</Border>
|
||||
|
||||
<Border Background="{DynamicResource LauncherBackground}"
|
||||
CornerRadius="18"
|
||||
ClipToBounds="True">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="56"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="44"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border Grid.Row="0"
|
||||
CornerRadius="18,18,0,0"
|
||||
Background="{DynamicResource ItemBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="0,0,0,1"
|
||||
MouseLeftButtonDown="TitleBar_MouseLeftButtonDown">
|
||||
<Grid Margin="18,0,12,0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
||||
<Border Background="{DynamicResource AccentColor}"
|
||||
CornerRadius="8"
|
||||
Padding="7,4"
|
||||
Margin="0,0,10,0">
|
||||
<TextBlock Text=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="14"
|
||||
Foreground="White"/>
|
||||
</Border>
|
||||
<StackPanel>
|
||||
<TextBlock x:Name="TitleText"
|
||||
Text="클립보드 이미지 미리보기"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource PrimaryText}"/>
|
||||
<TextBlock x:Name="MetaText"
|
||||
Text="원본 이미지"
|
||||
Margin="0,2,0,0"
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource SecondaryText}"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Orientation="Horizontal"
|
||||
VerticalAlignment="Center">
|
||||
<Border Width="34"
|
||||
Height="34"
|
||||
Margin="0,0,6,0"
|
||||
Background="Transparent"
|
||||
CornerRadius="9"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonUp="BtnResetZoom_MouseLeftButtonUp">
|
||||
<TextBlock Text="100%"
|
||||
FontSize="10.5"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<Border Width="34"
|
||||
Height="34"
|
||||
Background="Transparent"
|
||||
CornerRadius="9"
|
||||
Cursor="Hand"
|
||||
MouseLeftButtonUp="BtnClose_MouseLeftButtonUp">
|
||||
<TextBlock Text=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="10"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="1"
|
||||
Background="{DynamicResource ItemBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Padding="16,12">
|
||||
<WrapPanel VerticalAlignment="Center" ItemHeight="36">
|
||||
<Button x:Name="BtnCopyImage"
|
||||
Content="클립보드 복사"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="108"
|
||||
Click="BtnCopyImage_Click"/>
|
||||
<Button x:Name="BtnSavePng"
|
||||
Content="PNG 저장"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="96"
|
||||
Click="BtnSavePng_Click"/>
|
||||
<Button x:Name="BtnSaveJpeg"
|
||||
Content="JPEG 저장"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="96"
|
||||
Click="BtnSaveJpeg_Click"/>
|
||||
<Button x:Name="BtnSaveBmp"
|
||||
Content="BMP 저장"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="96"
|
||||
Click="BtnSaveBmp_Click"/>
|
||||
<Button x:Name="BtnZoomIn"
|
||||
Content="확대"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="72"
|
||||
Click="BtnZoomIn_Click"/>
|
||||
<Button x:Name="BtnZoomOut"
|
||||
Content="축소"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="72"
|
||||
Click="BtnZoomOut_Click"/>
|
||||
<Button x:Name="BtnFit"
|
||||
Content="창에 맞춤"
|
||||
Margin="0,0,8,8"
|
||||
Padding="12,6"
|
||||
MinWidth="96"
|
||||
Click="BtnFit_Click"/>
|
||||
</WrapPanel>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="2"
|
||||
Background="{DynamicResource LauncherBackground}">
|
||||
<Grid Margin="14">
|
||||
<Border CornerRadius="16"
|
||||
Background="{DynamicResource ItemBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="1">
|
||||
<ScrollViewer x:Name="ImageScrollViewer"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
PreviewMouseWheel="ImageScrollViewer_PreviewMouseWheel"
|
||||
SizeChanged="ImageScrollViewer_SizeChanged">
|
||||
<Grid x:Name="ImageHost"
|
||||
Background="{DynamicResource LauncherBackground}"
|
||||
Width="{Binding ElementName=ImageScrollViewer, Path=ViewportWidth}"
|
||||
Height="{Binding ElementName=ImageScrollViewer, Path=ViewportHeight}">
|
||||
<Image x:Name="PreviewImage"
|
||||
Stretch="None"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
RenderOptions.BitmapScalingMode="HighQuality">
|
||||
<Image.RenderTransform>
|
||||
<ScaleTransform x:Name="ImageScaleTransform"
|
||||
ScaleX="1"
|
||||
ScaleY="1"/>
|
||||
</Image.RenderTransform>
|
||||
</Image>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="3"
|
||||
Background="{DynamicResource ItemBackground}"
|
||||
BorderBrush="{DynamicResource BorderColor}"
|
||||
BorderThickness="0,1,0,0"
|
||||
Padding="16,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="StatusText"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="11.5"
|
||||
Foreground="{DynamicResource SecondaryText}"/>
|
||||
<TextBlock Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
Text="Ctrl+휠 확대/축소 · + / - · 0 원본 · F 맞춤 · Esc 닫기"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
||||
226
src/AxCopilot/Views/ClipboardImagePreviewWindow.xaml.cs
Normal file
226
src/AxCopilot/Views/ClipboardImagePreviewWindow.xaml.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace AxCopilot.Views;
|
||||
|
||||
/// <summary>클립보드 이미지 전용 미리보기 창. 원본 해상도 기준 줌과 저장을 지원합니다.</summary>
|
||||
public partial class ClipboardImagePreviewWindow : Window
|
||||
{
|
||||
private const double MinZoom = 0.1;
|
||||
private const double MaxZoom = 8.0;
|
||||
private const double ZoomStep = 0.1;
|
||||
|
||||
private readonly BitmapSource _image;
|
||||
private readonly string? _sourcePath;
|
||||
private double _zoom = 1.0;
|
||||
private bool _fitToViewport = true;
|
||||
|
||||
public ClipboardImagePreviewWindow(BitmapSource image, string? sourcePath = null)
|
||||
{
|
||||
_image = image ?? throw new ArgumentNullException(nameof(image));
|
||||
_sourcePath = sourcePath;
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
PreviewImage.Source = _image;
|
||||
TitleText.Text = string.IsNullOrWhiteSpace(sourcePath)
|
||||
? "클립보드 이미지 미리보기"
|
||||
: Path.GetFileName(sourcePath);
|
||||
MetaText.Text = $"{_image.PixelWidth:N0} × {_image.PixelHeight:N0}px";
|
||||
|
||||
Loaded += (_, _) =>
|
||||
{
|
||||
ApplyFitToViewport();
|
||||
UpdateStatusText();
|
||||
};
|
||||
}
|
||||
|
||||
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (e.ClickCount == 2)
|
||||
{
|
||||
WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
||||
return;
|
||||
}
|
||||
|
||||
try { DragMove(); } catch { }
|
||||
}
|
||||
|
||||
private void Window_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.Escape:
|
||||
Close();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.Add:
|
||||
case Key.OemPlus:
|
||||
IncreaseZoom();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.Subtract:
|
||||
case Key.OemMinus:
|
||||
DecreaseZoom();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.D0:
|
||||
case Key.NumPad0:
|
||||
ResetZoom();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.F:
|
||||
ApplyFitToViewport();
|
||||
e.Handled = true;
|
||||
return;
|
||||
case Key.C when Keyboard.Modifiers == ModifierKeys.Control:
|
||||
CopyImageToClipboard();
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void ImageScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
if ((Keyboard.Modifiers & ModifierKeys.Control) == 0)
|
||||
return;
|
||||
|
||||
if (e.Delta > 0)
|
||||
IncreaseZoom();
|
||||
else if (e.Delta < 0)
|
||||
DecreaseZoom();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void ImageScrollViewer_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (_fitToViewport)
|
||||
ApplyFitToViewport();
|
||||
}
|
||||
|
||||
private void BtnClose_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => Close();
|
||||
private void BtnResetZoom_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) => ResetZoom();
|
||||
private void BtnZoomIn_Click(object sender, RoutedEventArgs e) => IncreaseZoom();
|
||||
private void BtnZoomOut_Click(object sender, RoutedEventArgs e) => DecreaseZoom();
|
||||
private void BtnFit_Click(object sender, RoutedEventArgs e) => ApplyFitToViewport();
|
||||
private void BtnCopyImage_Click(object sender, RoutedEventArgs e) => CopyImageToClipboard();
|
||||
private void BtnSavePng_Click(object sender, RoutedEventArgs e) => SaveImage("png");
|
||||
private void BtnSaveJpeg_Click(object sender, RoutedEventArgs e) => SaveImage("jpg");
|
||||
private void BtnSaveBmp_Click(object sender, RoutedEventArgs e) => SaveImage("bmp");
|
||||
|
||||
private void IncreaseZoom() => SetZoom(_zoom + ZoomStep, false);
|
||||
private void DecreaseZoom() => SetZoom(_zoom - ZoomStep, false);
|
||||
private void ResetZoom() => SetZoom(1.0, false);
|
||||
|
||||
private void ApplyFitToViewport()
|
||||
{
|
||||
if (ImageScrollViewer.ViewportWidth <= 0 || ImageScrollViewer.ViewportHeight <= 0)
|
||||
return;
|
||||
|
||||
var availableWidth = Math.Max(1, ImageScrollViewer.ViewportWidth - 32);
|
||||
var availableHeight = Math.Max(1, ImageScrollViewer.ViewportHeight - 32);
|
||||
|
||||
var scaleX = availableWidth / _image.PixelWidth;
|
||||
var scaleY = availableHeight / _image.PixelHeight;
|
||||
var fitScale = Math.Min(scaleX, scaleY);
|
||||
|
||||
if (double.IsNaN(fitScale) || double.IsInfinity(fitScale) || fitScale <= 0)
|
||||
fitScale = 1.0;
|
||||
|
||||
SetZoom(Math.Min(1.0, fitScale), true);
|
||||
}
|
||||
|
||||
private void SetZoom(double zoom, bool fitToViewport)
|
||||
{
|
||||
_fitToViewport = fitToViewport;
|
||||
_zoom = Math.Max(MinZoom, Math.Min(MaxZoom, zoom));
|
||||
ImageScaleTransform.ScaleX = _zoom;
|
||||
ImageScaleTransform.ScaleY = _zoom;
|
||||
UpdateStatusText();
|
||||
}
|
||||
|
||||
private void UpdateStatusText()
|
||||
{
|
||||
var mode = _fitToViewport ? "창 맞춤" : "수동 줌";
|
||||
var source = string.IsNullOrWhiteSpace(_sourcePath) ? "원본 경로 없음" : _sourcePath;
|
||||
StatusText.Text = $"{_image.PixelWidth:N0} × {_image.PixelHeight:N0}px · 확대 {Math.Round(_zoom * 100)}% · {mode} · {source}";
|
||||
}
|
||||
|
||||
private void CopyImageToClipboard()
|
||||
{
|
||||
try
|
||||
{
|
||||
var app = Application.Current as App;
|
||||
app?.ClipboardHistoryService?.SuppressNextCapture();
|
||||
Clipboard.SetImage(_image);
|
||||
CustomMessageBox.Show("이미지를 클립보드에 복사했습니다.", "AX Commander", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Services.LogService.Warn($"클립보드 이미지 복사 실패: {ex.Message}");
|
||||
CustomMessageBox.Show($"이미지 복사에 실패했습니다.\n{ex.Message}", "AX Commander", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveImage(string format)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dialog = new SaveFileDialog
|
||||
{
|
||||
FileName = BuildDefaultFileName(format),
|
||||
Filter = format switch
|
||||
{
|
||||
"png" => "PNG 이미지|*.png",
|
||||
"jpg" => "JPEG 이미지|*.jpg;*.jpeg",
|
||||
"bmp" => "BMP 이미지|*.bmp",
|
||||
_ => "이미지 파일|*.*",
|
||||
},
|
||||
AddExtension = true,
|
||||
OverwritePrompt = true,
|
||||
};
|
||||
|
||||
if (dialog.ShowDialog(this) != true)
|
||||
return;
|
||||
|
||||
BitmapEncoder encoder = format switch
|
||||
{
|
||||
"jpg" => new JpegBitmapEncoder { QualityLevel = 95 },
|
||||
"bmp" => new BmpBitmapEncoder(),
|
||||
_ => new PngBitmapEncoder(),
|
||||
};
|
||||
|
||||
encoder.Frames.Add(BitmapFrame.Create(_image));
|
||||
using var stream = new FileStream(dialog.FileName, FileMode.Create, FileAccess.Write);
|
||||
encoder.Save(stream);
|
||||
|
||||
CustomMessageBox.Show($"이미지를 저장했습니다.\n{dialog.FileName}", "AX Commander", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Services.LogService.Warn($"클립보드 이미지 저장 실패: {ex.Message}");
|
||||
CustomMessageBox.Show($"이미지 저장에 실패했습니다.\n{ex.Message}", "AX Commander", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private string BuildDefaultFileName(string format)
|
||||
{
|
||||
var sourceName = !string.IsNullOrWhiteSpace(_sourcePath)
|
||||
? Path.GetFileNameWithoutExtension(_sourcePath)
|
||||
: $"clipboard-image-{DateTime.Now:yyyyMMdd-HHmmss}";
|
||||
|
||||
var extension = format switch
|
||||
{
|
||||
"jpg" => ".jpg",
|
||||
"bmp" => ".bmp",
|
||||
_ => ".png",
|
||||
};
|
||||
|
||||
return sourceName + extension;
|
||||
}
|
||||
}
|
||||
29
src/AxCopilot/Views/LauncherWindow.Keyboard.cs
Normal file
29
src/AxCopilot/Views/LauncherWindow.Keyboard.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace AxCopilot.Views;
|
||||
|
||||
public partial class LauncherWindow
|
||||
{
|
||||
private bool TryOpenClipboardImagePreview()
|
||||
{
|
||||
if (_vm.SelectedItem?.Data is not Services.ClipboardEntry clipEntry || clipEntry.IsText)
|
||||
return false;
|
||||
|
||||
var originalImage = Services.ClipboardHistoryService.LoadOriginalImage(clipEntry.OriginalImagePath);
|
||||
BitmapSource? imageToPreview = originalImage ?? clipEntry.Image;
|
||||
if (imageToPreview == null)
|
||||
return false;
|
||||
|
||||
Hide();
|
||||
|
||||
var preview = new ClipboardImagePreviewWindow(imageToPreview, clipEntry.OriginalImagePath)
|
||||
{
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen,
|
||||
};
|
||||
preview.Resources.MergedDictionaries.Add(Resources);
|
||||
preview.Show();
|
||||
preview.Activate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ using System.Windows.Media.Animation;
|
||||
using Microsoft.Win32;
|
||||
using AxCopilot.Models;
|
||||
using AxCopilot.ViewModels;
|
||||
using FormsCursor = System.Windows.Forms.Cursor;
|
||||
using FormsScreen = System.Windows.Forms.Screen;
|
||||
|
||||
namespace AxCopilot.Views;
|
||||
|
||||
@@ -676,16 +678,20 @@ public partial class LauncherWindow : Window
|
||||
|
||||
private void CenterOnScreen()
|
||||
{
|
||||
var screen = SystemParameters.WorkArea;
|
||||
var monitor = FormsScreen.FromPoint(FormsCursor.Position);
|
||||
var transform = PresentationSource.FromVisual(this)?.CompositionTarget?.TransformFromDevice ?? Matrix.Identity;
|
||||
var topLeft = transform.Transform(new Point(monitor.WorkingArea.Left, monitor.WorkingArea.Top));
|
||||
var bottomRight = transform.Transform(new Point(monitor.WorkingArea.Right, monitor.WorkingArea.Bottom));
|
||||
var screen = new Rect(topLeft, bottomRight);
|
||||
// ActualHeight/ActualWidth는 첫 Show() 전 레이아웃 패스 이전에 0일 수 있음 → 기본값으로 보호
|
||||
var w = ActualWidth > 0 ? ActualWidth : 640;
|
||||
var h = ActualHeight > 0 ? ActualHeight : 80;
|
||||
Left = (screen.Width - w) / 2 + screen.Left;
|
||||
Left = screen.Left + (screen.Width - w) / 2;
|
||||
Top = _vm.WindowPosition switch
|
||||
{
|
||||
"center" => (screen.Height - h) / 2 + screen.Top,
|
||||
"bottom" => screen.Height * 0.75 + screen.Top,
|
||||
_ => screen.Height * 0.2 + screen.Top, // "center-top" (기본)
|
||||
"center" => screen.Top + (screen.Height - h) / 2,
|
||||
"bottom" => screen.Top + screen.Height * 0.75,
|
||||
_ => screen.Top + screen.Height * 0.2, // "center-top" (기본)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -863,6 +869,12 @@ public partial class LauncherWindow : Window
|
||||
|
||||
if (shift)
|
||||
{
|
||||
if (TryOpenClipboardImagePreview())
|
||||
{
|
||||
e.Handled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// 퍼지 파일 검색 결과: Shift+Enter → 파일이 있는 폴더 열기
|
||||
if (_vm.SelectedItem?.Data is AxCopilot.Services.IndexEntry shiftEntry)
|
||||
{
|
||||
@@ -1297,7 +1309,7 @@ public partial class LauncherWindow : Window
|
||||
"Ctrl+Shift+E 탐색기에서 열기",
|
||||
"Ctrl+Enter 관리자 실행",
|
||||
"Alt+Enter 속성 보기",
|
||||
"Shift+Enter 대형 텍스트",
|
||||
"Shift+Enter 대형 텍스트 / 클립보드 이미지 미리보기",
|
||||
};
|
||||
|
||||
CustomMessageBox.Show(
|
||||
|
||||
@@ -83,7 +83,7 @@ public partial class ShortcutHelpWindow : Window
|
||||
new ShortcutRow("Ctrl+K", "이 단축키 참조 창 열기", "\uE8FD", "#4B5EFC"),
|
||||
new ShortcutRow("Ctrl+,", "설정 창 열기", "\uE713", "#4B5EFC"),
|
||||
new ShortcutRow("F5", "파일 인덱스 즉시 재구축", "\uE72C", "#107C10"),
|
||||
new ShortcutRow("Shift+Enter", "Large Type / 병합 실행 / 캡처 모드: 지연 캡처(3/5/10초) 타이머", "\uE8A7", "#7B68EE"),
|
||||
new ShortcutRow("Shift+Enter", "클립보드 이미지 미리보기 / Large Type / 병합 실행 / 캡처 모드 지연 타이머", "\uE8A7", "#7B68EE"),
|
||||
};
|
||||
|
||||
// ── 입력 예약어 ───────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user