1
0
Fork 0

feat: 배치 결합 모드 + IExplorerCommand DLL 카스케이드

#10 다중 이미지 → 단일 PDF/TIFF/GIF 결합
- ConversionEngine: BatchMode { Independent, CombineToSingle } enum 추가
- ConvertManyAsync에 batchMode 파라미터, CombineToSingle 시 N:1 라우팅
- CombineAsync: MagickImageCollection으로 모든 입력 디코드 후
  단일 다중-페이지 파일로 출력 (PDF/TIFF/GIF만 지원)
- 결합 가능 검증: ImageMagick 디코드 가능 입력 + 결합 가능 출력
- 정적 헬퍼 CanCombine(outputExt), CanCombineInput(sourcePath)

UI
- MainWindow.xaml에 '단일 파일로 결합' CheckBox 추가
  (출력이 결합 가능 + 큐 ≥2 + 모든 입력 결합 가능일 때 활성화)
- 큐 변경/형식 변경 시 토글 상태 + 안내 텍스트 자동 갱신
- MainWindow.xaml.cs UpdateCombineState / OnCombineToggleChanged

#9 IExplorerCommand DLL 카스케이드 (MSIX 메인 메뉴)
- dllmain.cpp 전면 재작성:
  RootCascadeCommand (CLSID F1A2B3C4-...-2B3C4D5E6F70)
  + 11개 동적 SubVerbCommand
  + SubCommandEnumerator (IEnumExplorerCommand)
  + ECF_HASSUBCOMMANDS 플래그
- 서브메뉴 항목: JPEG/PNG/WebP/PDF/TXT/DOCX/AVIF/GIF/TIFF/BMP/변환…
- 기존 Quick/Dialog 핸들러는 backward compat용으로 유지
- 빌드: x64 Release Everything2Everything.Shell.dll (207KB)

Package.appxmanifest
- com:Class에 RootCascadeCommand CLSID 등록
- 모든 desktop5:ItemType verb를 Quick+Dialog 두 개에서 단일 Convert로 통합
  (29개 ItemType × 2 verbs → 29 × 1 verb)

quick CLI는 기본 .jpg 호환 유지, dialog는 메인 창에서 형식 선택

빌드: dotnet 0 errors, MSBuild C++ 0 errors
This commit is contained in:
Yun Chan 2026-05-07 15:46:38 +09:00
parent 9b7e5f0d0c
commit 2633a928c1
7 changed files with 452 additions and 68 deletions

View file

@ -93,7 +93,7 @@ public partial class App : Application
{
var options = ConvertOptions.Quick();
var reporter = new Progress<ConvertProgress>(p => progress.Report(p));
var results = await Engine.ConvertManyAsync(files, ".jpg", options, reporter);
var results = await Engine.ConvertManyAsync(files, outputExtension, options, reporter);
foreach (var r in results)
{

View file

@ -102,6 +102,15 @@
<TextBlock x:Name="OutputFormatHint" Margin="0,6,0,0"
Style="{StaticResource FsCaptionStyle}"
Text="모든 입력에서 변환 가능한 형식이 표시됩니다"/>
<CheckBox x:Name="CombineToSingleCheck"
Margin="0,12,0,0"
Content="단일 파일로 결합 (큐 전체 → 한 파일)"
IsEnabled="False"
Checked="OnCombineToggleChanged"
Unchecked="OnCombineToggleChanged"/>
<TextBlock x:Name="CombineHint" Margin="0,4,0,0"
Style="{StaticResource FsCaptionStyle}"
Text="PDF/TIFF/GIF 출력에 한해 큐의 이미지들을 한 파일로 결합합니다"/>
</StackPanel>
<!-- Encoding Quality -->

View file

@ -533,7 +533,10 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
{
var sources = snapshot.Select(s => s.SourcePath).ToList();
var outputExt = SelectedOutputExtension ?? ".jpg";
var results = await engine.ConvertManyAsync(sources, outputExt, options, reporter, _cts.Token);
var batchMode = (CombineToSingleCheck?.IsChecked == true)
? BatchMode.CombineToSingle
: BatchMode.Independent;
var results = await engine.ConvertManyAsync(sources, outputExt, options, reporter, batchMode, _cts.Token);
foreach (var (item, result) in snapshot.Zip(results))
{
@ -839,6 +842,7 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
UpdateOutputFormatBadge(keepExt);
UpdateQualityPanelForFormat(keepExt);
UpdateOutputDestHint(keepExt);
UpdateCombineState(keepExt);
if (OutputFormatHint is not null)
{
@ -848,6 +852,35 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
}
}
private void UpdateCombineState(string? extension)
{
if (CombineToSingleCheck is null || CombineHint is null) return;
var ext = extension ?? string.Empty;
var combinableOutput = ConversionEngine.CanCombine(ext);
var allInputsCombinable = _activeQueue.Count > 0
&& _activeQueue.All(q => ConversionEngine.CanCombineInput(q.SourcePath));
var enabled = combinableOutput && allInputsCombinable && _activeQueue.Count >= 2;
CombineToSingleCheck.IsEnabled = enabled;
if (!enabled && CombineToSingleCheck.IsChecked == true)
CombineToSingleCheck.IsChecked = false;
CombineHint.Text = (combinableOutput, _activeQueue.Count) switch
{
(false, _) => "PDF/TIFF/GIF 출력일 때만 단일 파일 결합이 가능합니다",
(true, 0) => "PDF/TIFF/GIF 출력에 한해 큐의 이미지들을 한 파일로 결합합니다",
(true, 1) => "결합하려면 큐에 2개 이상의 이미지가 필요합니다",
(true, _) when !allInputsCombinable => "결합은 이미지 입력만 지원합니다 (PDF/DOCX 등 제외)",
_ => $"체크 시 큐의 {_activeQueue.Count}개 이미지를 단일 {ext.TrimStart('.').ToUpperInvariant()}로 결합",
};
}
private void OnCombineToggleChanged(object sender, RoutedEventArgs e)
{
UpdateCombineState(SelectedOutputExtension);
}
private void OnOutputFormatChanged(object sender, SelectionChangedEventArgs e)
{
if (_suppressFormatChanged) return;