열리는 창들의 결을 통일한다 — 타이틀바와 강조 버튼
## 창 열둘 중 하나만 우리 옷을 입고 있었다 커스텀 크롬을 가진 것은 메인 셸과 MessageDialogView 둘뿐이었고, 나머지 열한 창(서식 이력·데이터소스 배선·글꼴 관리자·태그 선택·쿼리 편집기·마스크· 환자 선택·데이터소스 결과·레이어 필터·서식 등록·미리보기)은 <b>윈도우 기본 타이틀바</b>를 달고 떴다. 다크 테마에서 어두운 앱 위에 OS 바가 얹히고, 높이·글자·모서리·닫기 버튼 모양이 전부 달라 "다른 프로그램이 열렸다"로 보였다. 열한 창이 이미 전부 ThemedWindow 를 걸고 있었으므로, 그 옆에 템플릿을 가진 ThemedDialogWindow 를 만들고 각 창은 <b>스타일 이름 한 줄</b>만 바꿨다. 창마다 타이틀바 markup 을 복사했다면 다음에 또 갈라진다. ## WindowChrome 은 스타일로 줄 수 없었다 두 번 막혔고 둘 다 같은 뿌리다 — WindowChrome 은 Freezable 인데 창에 붙으면서 스스로 속성을 고친다. Setter.Value 에 두면 열한 창이 <b>한 인스턴스를 나눠 쓰다</b> 두 번째 창부터 "읽기 전용 상태라 속성을 설정할 수 없습니다"로 죽었다. x:Shared="False" 로도 안 됐다 — 공유되는 것은 리소스가 아니라 Setter 가 이미 붙든 값이다. 그래서 ctl:DialogChrome 첨부 속성이 창마다 새 인스턴스를 만들어 붙인다. 템플릿 안 닫기 버튼은 Click 핸들러를 가질 수 없으므로(템플릿에 코드비하인드가 없다) 표준 SystemCommands.CloseWindowCommand 를 쓰고 그 CommandBinding 도 여기서 단다. DialogResult 를 건드리지 않으므로 ShowDialog 는 false 를 돌려주고 호출부의 '취소' 경로가 그대로 탄다. 최대화 보정도 같이 건다. WindowStyle=None 인 창은 최대화하는 순간 작업표시줄을 덮는데 (메인 창에서 겪은 결함이다) 대화상자 열 개가 크기 조절 가능이라 타이틀바 더블클릭으로 그 상태에 들어갈 수 있다. ## 진단이 바로 그 부분에 눈이 없었다 --dialog-shots 는 window.Content 만 찍고 있었다. 그래서 이 결함을 <b>한 번도 보여 준 적이 없다</b> — MessageDialogView 만 타이틀바가 사진에 나왔는데, 그건 그 창의 바가 Content 안에 있어서였다. 창 전체를 찍도록 바꿨다(템플릿의 PART_Root). 고칠 대상이 사진에 안 나오는 진단은 있으나 마나였고, 실제로 이번에도 첫 캡처가 "고쳤는데 그대로"로 보여 한 번 헛짚게 만들었다. ## 강조 버튼 — 규칙은 이미 있었다 Primary 스타일을 열한 창 중 넷만 쓰고 있었다. 그런데 IsDefault="True" 는 대부분의 창이 이미 주 동작에 달아 두었다 — 규칙을 새로 만들 필요가 없었다. <b>기본 버튼 = 강조</b>로 맞춘다(서식 이력·서식 등록·마스크·레이어 필터·데이터소스 결과·환자 선택). 글꼴 관리자만 예외로 손으로 골랐다. IsDefault 가 없고 버튼이 셋인데, 강조는 <b>고른 것만</b> 바꾸는 '선택 조합에 적용'에 준다. '전체에 적용'은 문서 전체를 한 번에 바꾸므로 눈이 먼저 가는 자리에 두지 않았다 — 되돌리기가 있어도 되돌릴 생각을 하려면 먼저 알아채야 한다. 환자 선택의 '선택'에는 Primary 만 주고 IsDefault 는 건드리지 않았다 — 검색칸에서 Enter 는 '찾기'여야 한다. ## 판정 - 단위 시험 388 · edit-smoke 376건 전건 통과 - --dialog-shots 69장 전건 통과(창 전체 캡처로 바뀐 뒤에도) - --modal-check · --maxrect · --scale-budget 전건 통과 - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변 ## 남은 것 내용 여백은 아직 창마다 다르다 — 설명 문장이 창 위쪽 가장자리에 바짝 붙는 창이 여럿이다. 타이틀바가 생겨 덜 도드라지지만 통일된 것은 아니다. 별도로 잡을 것. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
020595f8d4
commit
12e5ec6452
@@ -0,0 +1,90 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
|
|
||||||
|
namespace SheetMe.Designer.Controls;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 대화상자 크롬을 켠다 — <c>ThemedDialogWindow</c> 스타일이 <b>스타일 세터로</b> 걸어 준다.
|
||||||
|
///
|
||||||
|
/// <b>왜 첨부 속성인가.</b> 창 12종에 같은 타이틀바를 주려면 <see cref="ControlTemplate"/> 이 필요한데,
|
||||||
|
/// 템플릿 안의 닫기 버튼은 <c>Click</c> 핸들러를 가질 수 없다(템플릿은 코드비하인드가 없다).
|
||||||
|
/// 그래서 표준 <see cref="SystemCommands.CloseWindowCommand"/> 를 쓰고, 그 명령을 받을
|
||||||
|
/// <see cref="CommandBinding"/> 을 여기서 창에 달아 준다. 창마다 코드를 넣지 않아도 된다.
|
||||||
|
///
|
||||||
|
/// <b>최대화 보정도 함께 건다.</b> <c>WindowStyle=None</c> 인 창은 최대화하는 순간
|
||||||
|
/// 작업표시줄을 덮는다(메인 창에서 실제로 겪은 결함이다). 대화상자 대부분이 크기 조절 가능이라
|
||||||
|
/// 타이틀바를 더블클릭하면 그 상태에 들어갈 수 있다 — 크롬을 켜는 이 자리에서 같이 막는다.
|
||||||
|
/// </summary>
|
||||||
|
public static class DialogChrome
|
||||||
|
{
|
||||||
|
#region Attached Properties
|
||||||
|
/// <summary>크롬 사용 여부 — 스타일이 True 로 세팅한다</summary>
|
||||||
|
public static readonly DependencyProperty EnabledProperty =
|
||||||
|
DependencyProperty.RegisterAttached(
|
||||||
|
"Enabled", typeof(bool), typeof(DialogChrome),
|
||||||
|
new PropertyMetadata(false, OnEnabledChanged));
|
||||||
|
|
||||||
|
public static void SetEnabled(DependencyObject element, bool value)
|
||||||
|
=> element.SetValue(EnabledProperty, value);
|
||||||
|
|
||||||
|
public static bool GetEnabled(DependencyObject element)
|
||||||
|
=> (bool)element.GetValue(EnabledProperty);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
private static void OnEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is not Window window || e.NewValue is not true)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 같은 창에 두 번 걸리지 않게 한다 — 스타일이 다시 적용되는 경로가 있다
|
||||||
|
foreach (CommandBinding existing in window.CommandBindings)
|
||||||
|
{
|
||||||
|
if (existing.Command == SystemCommands.CloseWindowCommand)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 크롬은 <b>창마다 새로</b> 만든다. WindowChrome 은 Freezable 이고 창에 붙으면서
|
||||||
|
// 스스로 속성을 고치므로, 한 인스턴스를 여러 창이 나눠 쓰면 두 번째 창부터
|
||||||
|
// "읽기 전용 상태라 속성을 설정할 수 없습니다"로 죽는다.
|
||||||
|
// 그래서 XAML 스타일 세터로는 줄 수 없다(세터 값은 한 번 평가돼 공유된다).
|
||||||
|
//
|
||||||
|
// CaptionHeight 36 = 타이틀바 높이와 같아야 그 띠를 잡고 창을 끌 수 있다.
|
||||||
|
// GlassFrameThickness 0,0,0,1 = DWM 그림자 유지.
|
||||||
|
// ResizeBorderThickness 6 은 ResizeMode 가 허용할 때만 실제로 동작한다.
|
||||||
|
System.Windows.Shell.WindowChrome.SetWindowChrome(window, new System.Windows.Shell.WindowChrome
|
||||||
|
{
|
||||||
|
CaptionHeight = 36,
|
||||||
|
ResizeBorderThickness = new Thickness(6),
|
||||||
|
GlassFrameThickness = new Thickness(0, 0, 0, 1),
|
||||||
|
CornerRadius = new CornerRadius(0),
|
||||||
|
UseAeroCaptionButtons = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
window.CommandBindings.Add(new CommandBinding(
|
||||||
|
SystemCommands.CloseWindowCommand,
|
||||||
|
(_, args) =>
|
||||||
|
{
|
||||||
|
// 창의 X 를 누른 것과 같아야 한다 — DialogResult 를 건드리지 않으므로
|
||||||
|
// ShowDialog 는 false 를 돌려주고, 호출부의 '취소' 경로가 그대로 탄다
|
||||||
|
SystemCommands.CloseWindow(window);
|
||||||
|
args.Handled = true;
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 크기 조절 가능한 창만 최대화될 수 있다 — 그때 작업표시줄을 덮지 않게 한다
|
||||||
|
if (window.ResizeMode is ResizeMode.CanResize or ResizeMode.CanResizeWithGrip)
|
||||||
|
{
|
||||||
|
if (window.IsInitialized)
|
||||||
|
{
|
||||||
|
Services.MaximizeToWorkArea.Attach(window);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window.SourceInitialized += (_, _) => Services.MaximizeToWorkArea.Attach(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -390,18 +390,26 @@ public static class DialogShots
|
|||||||
// 레이아웃·비동기 로딩(Loaded 핸들러)이 한 바퀴 돌게 한다
|
// 레이아웃·비동기 로딩(Loaded 핸들러)이 한 바퀴 돌게 한다
|
||||||
Pump();
|
Pump();
|
||||||
|
|
||||||
// 창 자체를 렌더한다 — Content 만 찍으면 Window.Background(B.AppBg)가 빠져 투명이 되고,
|
// <b>창 전체</b>를 찍는다 — Content 만 찍으면 타이틀바가 통째로 빠진다.
|
||||||
// PNG 에서 검정으로 저장돼 "다크처럼 보이는" 착시가 생긴다(라이트 결함이 가려진다).
|
//
|
||||||
|
// 전에는 Content 를 찍었다. 그래서 창 크롬을 통일하기 전까지 이 진단은
|
||||||
|
// "열한 창이 윈도우 기본 타이틀바를 달고 뜬다"는 사실을 <b>한 번도 보여 준 적이 없었다</b> —
|
||||||
|
// 고쳐야 할 바로 그 부분에 눈이 없었던 셈이다. 이제 커스텀 타이틀바는 창의 Template
|
||||||
|
// 안에 있으므로 Content 만 찍으면 여전히 안 보인다.
|
||||||
|
//
|
||||||
|
// 배경을 먼저 칠하는 것은 그대로 둔다 — 투명 픽셀이 PNG 에서 검정으로 저장되면
|
||||||
|
// 라이트 테마 결함이 "다크처럼 보이는" 착시에 가려진다.
|
||||||
var content = (FrameworkElement)window.Content;
|
var content = (FrameworkElement)window.Content;
|
||||||
var width = (int)Math.Ceiling(content.ActualWidth > 0 ? content.ActualWidth : window.Width);
|
var root = (FrameworkElement?)window.Template?.FindName("PART_Root", window) ?? content;
|
||||||
var height = (int)Math.Ceiling(content.ActualHeight > 0 ? content.ActualHeight : window.Height);
|
var width = (int)Math.Ceiling(window.ActualWidth > 0 ? window.ActualWidth : window.Width);
|
||||||
|
var height = (int)Math.Ceiling(window.ActualHeight > 0 ? window.ActualHeight : window.Height);
|
||||||
var bitmap = new RenderTargetBitmap(Math.Max(1, width), Math.Max(1, height), 96, 96, PixelFormats.Pbgra32);
|
var bitmap = new RenderTargetBitmap(Math.Max(1, width), Math.Max(1, height), 96, 96, PixelFormats.Pbgra32);
|
||||||
|
|
||||||
var drawing = new DrawingVisual();
|
var drawing = new DrawingVisual();
|
||||||
using (var context = drawing.RenderOpen())
|
using (var context = drawing.RenderOpen())
|
||||||
{
|
{
|
||||||
context.DrawRectangle(window.Background ?? Brushes.Transparent, null, new Rect(0, 0, width, height));
|
context.DrawRectangle(window.Background ?? Brushes.Transparent, null, new Rect(0, 0, width, height));
|
||||||
context.DrawRectangle(new VisualBrush(content) { Stretch = Stretch.None, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Top },
|
context.DrawRectangle(new VisualBrush(root) { Stretch = Stretch.None, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Top },
|
||||||
null, new Rect(0, 0, width, height));
|
null, new Rect(0, 0, width, height));
|
||||||
}
|
}
|
||||||
bitmap.Render(drawing);
|
bitmap.Render(drawing);
|
||||||
|
|||||||
@@ -1404,4 +1404,68 @@
|
|||||||
</Style.Triggers>
|
</Style.Triggers>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<!-- ============================================================
|
||||||
|
대화상자 크롬 — 앱 셸·알림창과 같은 타이틀바를 <b>모든</b> 창에 준다.
|
||||||
|
|
||||||
|
<b>왜 필요했나.</b> 커스텀 크롬을 가진 창은 메인 셸과 MessageDialogView 둘뿐이었고,
|
||||||
|
나머지 열한 창(서식 이력·데이터소스 배선·글꼴 관리자·태그 선택·쿼리 편집기·환자 선택 …)은
|
||||||
|
윈도우 <b>기본</b> 타이틀바를 달고 떴다. 다크 테마에서 어두운 앱 위에 OS 바가 얹히고,
|
||||||
|
모서리·높이·글자 크기·닫기 버튼 모양이 전부 달라 "다른 프로그램이 열렸다"로 보였다.
|
||||||
|
|
||||||
|
<b>왜 스타일 하나로 하나.</b> 열한 창은 이미 전부 ThemedWindow 를 걸고 있었다 —
|
||||||
|
템플릿을 여기 한 번 두면 각 창은 스타일 이름 한 줄만 바꾸면 된다.
|
||||||
|
창마다 타이틀바 markup 을 복사하면 다음에 또 갈라진다.
|
||||||
|
|
||||||
|
AllowsTransparency 는 켜지 않는다: 레이어드 윈도우가 되면 ClearType 이 꺼져
|
||||||
|
13px 한글이 뭉개지고 진단이 찍는 PNG 배경이 알파가 된다.
|
||||||
|
닫기 버튼의 명령 배선과 최대화 보정은 ctl:DialogChrome 이 붙여 준다.
|
||||||
|
============================================================ -->
|
||||||
|
<Style x:Key="ThemedDialogWindow" TargetType="Window" BasedOn="{StaticResource ThemedWindow}">
|
||||||
|
<Setter Property="WindowStyle" Value="None" />
|
||||||
|
<Setter Property="Background" Value="{DynamicResource B.Surface}" />
|
||||||
|
<!--
|
||||||
|
WindowChrome 은 여기서 못 준다. Freezable 인 데다 창에 붙는 순간 스스로 속성을 고치는데,
|
||||||
|
Style 의 Setter.Value 는 <b>한 번 평가돼 공유</b>되므로 두 번째 창부터
|
||||||
|
"읽기 전용 상태라 속성을 설정할 수 없습니다"로 죽는다(x:Shared="False" 로도 안 된다 —
|
||||||
|
공유되는 것은 리소스가 아니라 Setter 가 이미 붙든 값이다).
|
||||||
|
그래서 ctl:DialogChrome 이 <b>창마다 새 인스턴스</b>를 만들어 붙인다.
|
||||||
|
-->
|
||||||
|
<Setter Property="ctl:DialogChrome.Enabled" Value="True" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Window">
|
||||||
|
<!-- PART_Root — 진단(dialog-shots)이 창 전체를 찍을 때 잡는 이름.
|
||||||
|
이 이름이 없으면 Content 만 찍혀 타이틀바가 사진에서 빠진다. -->
|
||||||
|
<Border x:Name="PART_Root"
|
||||||
|
BorderBrush="{DynamicResource B.Line2}" BorderThickness="1"
|
||||||
|
Background="{DynamicResource B.Surface}">
|
||||||
|
<DockPanel>
|
||||||
|
<!-- 타이틀바 — 드래그는 WindowChrome 의 CaptionHeight 가 처리한다 -->
|
||||||
|
<Border DockPanel.Dock="Top" Height="36" Background="{DynamicResource B.Titlebar}"
|
||||||
|
BorderBrush="{DynamicResource B.Line}" BorderThickness="0,0,0,1">
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Text="{TemplateBinding Title}" Margin="14,0,52,0"
|
||||||
|
VerticalAlignment="Center" FontSize="12"
|
||||||
|
Foreground="{DynamicResource B.Muted}"
|
||||||
|
TextTrimming="CharacterEllipsis" />
|
||||||
|
<!-- IsHitTestVisibleInChrome 필수 — 빠지면 클릭이 창 드래그로 먹혀 닫을 수 없다 -->
|
||||||
|
<Button Style="{StaticResource CloseBtn}" Height="36"
|
||||||
|
HorizontalAlignment="Right" IsTabStop="False" ToolTip="닫기"
|
||||||
|
Command="{x:Static SystemCommands.CloseWindowCommand}"
|
||||||
|
shell:WindowChrome.IsHitTestVisibleInChrome="True">
|
||||||
|
<TextBlock Text="" FontFamily="Segoe MDL2 Assets" FontSize="10" />
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
<!-- AdornerDecorator 가 있어야 검증 오류 표시·툴팁 어도너가 정상 동작한다 -->
|
||||||
|
<AdornerDecorator>
|
||||||
|
<ContentPresenter />
|
||||||
|
</AdornerDecorator>
|
||||||
|
</DockPanel>
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Title="데이터소스 조회 결과" Width="980" Height="640"
|
Title="데이터소스 조회 결과" Width="980" Height="640"
|
||||||
MinWidth="760" MinHeight="440"
|
MinWidth="760" MinHeight="440"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<DockPanel Margin="12">
|
<DockPanel Margin="12">
|
||||||
|
|
||||||
<TextBlock x:Name="HeaderText" DockPanel.Dock="Top" Margin="0,0,0,8" TextWrapping="Wrap"
|
<TextBlock x:Name="HeaderText" DockPanel.Dock="Top" Margin="0,0,0,8" TextWrapping="Wrap"
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
|
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
|
||||||
<Button Content="SQL 복사" Padding="14,4" Click="OnCopySql"
|
<Button Content="SQL 복사" Padding="14,4" Click="OnCopySql"
|
||||||
ToolTip="치환을 마친 SQL 을 클립보드로 — 쿼리 편집기나 SQL 도구에 그대로 붙일 수 있습니다"/>
|
ToolTip="치환을 마친 SQL 을 클립보드로 — 쿼리 편집기나 SQL 도구에 그대로 붙일 수 있습니다"/>
|
||||||
<Button Content="닫기" Padding="18,4" Margin="8,0,0,0" IsCancel="True" IsDefault="True"/>
|
<Button Content="닫기" Padding="18,4" Margin="8,0,0,0" IsCancel="True" IsDefault="True" Style="{StaticResource Primary}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
Title="데이터 필드 배선" Width="560" Height="520"
|
Title="데이터 필드 배선" Width="560" Height="520"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<DockPanel Margin="14">
|
<DockPanel Margin="14">
|
||||||
<TextBlock DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" TextWrapping="Wrap" Margin="0,0,0,10"
|
<TextBlock DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" TextWrapping="Wrap" Margin="0,0,0,10"
|
||||||
Text="데이터소스(조회 결과)의 한 칸을 이 컨트롤에 꽂습니다. 형식이 어긋나면 런타임이 아무 경고 없이 값을 비워 두므로, 문법은 여기서 조립합니다."/>
|
Text="데이터소스(조회 결과)의 한 칸을 이 컨트롤에 꽂습니다. 형식이 어긋나면 런타임이 아무 경고 없이 값을 비워 두므로, 문법은 여기서 조립합니다."/>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
Title="폰트 일괄 변경" Width="620" Height="560" MinWidth="520" MinHeight="420"
|
Title="폰트 일괄 변경" Width="620" Height="560" MinWidth="520" MinHeight="420"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<DockPanel Margin="12">
|
<DockPanel Margin="12">
|
||||||
<TextBlock DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" TextWrapping="Wrap" Margin="0,0,0,8"
|
<TextBlock DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}" TextWrapping="Wrap" Margin="0,0,0,8"
|
||||||
Text="문서 전체의 (타입·글꼴·크기) 조합입니다. 변경할 조합을 선택(다중 가능)하고 새 글꼴을 지정하세요."/>
|
Text="문서 전체의 (타입·글꼴·크기) 조합입니다. 변경할 조합을 선택(다중 가능)하고 새 글꼴을 지정하세요."/>
|
||||||
@@ -23,7 +23,10 @@
|
|||||||
<DockPanel Margin="0,10,0,0">
|
<DockPanel Margin="0,10,0,0">
|
||||||
<Button DockPanel.Dock="Right" Content="닫기" Padding="16,4" Margin="8,0,0,0" IsCancel="True"/>
|
<Button DockPanel.Dock="Right" Content="닫기" Padding="16,4" Margin="8,0,0,0" IsCancel="True"/>
|
||||||
<Button DockPanel.Dock="Right" Content="전체에 적용" Padding="14,4" Margin="8,0,0,0" Click="OnApplyAll"/>
|
<Button DockPanel.Dock="Right" Content="전체에 적용" Padding="14,4" Margin="8,0,0,0" Click="OnApplyAll"/>
|
||||||
<Button DockPanel.Dock="Right" Content="선택 조합에 적용" Padding="14,4" Click="OnApplySelected"/>
|
<!-- 강조는 <b>고른 것만</b> 바꾸는 쪽이다. '전체에 적용'은 문서 전체를 한 번에 바꾸므로
|
||||||
|
눈이 먼저 가는 자리에 두지 않는다 — 되돌리기가 있어도 되돌릴 생각을 하려면 먼저 알아채야 한다. -->
|
||||||
|
<Button DockPanel.Dock="Right" Content="선택 조합에 적용" Padding="14,4" Click="OnApplySelected"
|
||||||
|
Style="{StaticResource Primary}"/>
|
||||||
<TextBlock x:Name="ResultText" VerticalAlignment="Center" Foreground="{DynamicResource B.Success}"/>
|
<TextBlock x:Name="ResultText" VerticalAlignment="Center" Foreground="{DynamicResource B.Success}"/>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
xmlns:ctl="clr-namespace:SheetMe.Designer.Controls"
|
xmlns:ctl="clr-namespace:SheetMe.Designer.Controls"
|
||||||
Title="타입으로 거르기" Width="380" Height="520"
|
Title="타입으로 거르기" Width="380" Height="520"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<ctl:IconNameToVisualConverter x:Key="IconName"/>
|
<ctl:IconNameToVisualConverter x:Key="IconName"/>
|
||||||
<ctl:TypeToIconConverter x:Key="TypeToIcon"/>
|
<ctl:TypeToIconConverter x:Key="TypeToIcon"/>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
|
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
|
||||||
<Button Content="전체 해제" Padding="12,4" Click="OnClearAll"/>
|
<Button Content="전체 해제" Padding="12,4" Click="OnClearAll"/>
|
||||||
<Button Content="확인" Padding="20,4" Margin="8,0,0,0" Click="OnConfirm" IsDefault="True"/>
|
<Button Content="확인" Padding="20,4" Margin="8,0,0,0" Click="OnConfirm" IsDefault="True" Style="{StaticResource Primary}"/>
|
||||||
<Button Content="취소" Padding="20,4" Margin="8,0,0,0" IsCancel="True"/>
|
<Button Content="취소" Padding="20,4" Margin="8,0,0,0" IsCancel="True"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
Title="마스크 편집" Width="620" Height="620"
|
Title="마스크 편집" Width="620" Height="620"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<DockPanel Margin="12">
|
<DockPanel Margin="12">
|
||||||
<!--
|
<!--
|
||||||
백슬래시를 글리프로 보여주지 않는다 — 한글 글꼴에서 원화 기호(₩)로 렌더되어 오해를 부른다.
|
백슬래시를 글리프로 보여주지 않는다 — 한글 글꼴에서 원화 기호(₩)로 렌더되어 오해를 부른다.
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
|
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
|
||||||
<Button Content="마스크 없음" Padding="12,4" Click="OnClear"/>
|
<Button Content="마스크 없음" Padding="12,4" Click="OnClear"/>
|
||||||
<Button Content="확인" Padding="20,4" Margin="8,0,0,0" Click="OnConfirm" IsDefault="True"/>
|
<Button Content="확인" Padding="20,4" Margin="8,0,0,0" Click="OnConfirm" IsDefault="True" Style="{StaticResource Primary}"/>
|
||||||
<Button Content="취소" Padding="20,4" Margin="8,0,0,0" IsCancel="True"/>
|
<Button Content="취소" Padding="20,4" Margin="8,0,0,0" IsCancel="True"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Title="환자 선택 — 미리보기" Width="1040" Height="620"
|
Title="환자 선택 — 미리보기" Width="1040" Height="620"
|
||||||
MinWidth="880" MinHeight="480"
|
MinWidth="880" MinHeight="480"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<DockPanel Margin="12">
|
<DockPanel Margin="12">
|
||||||
|
|
||||||
<!-- 검색 줄. 유형을 먼저 고른다 — 유형마다 일치 방식이 달라서(차트번호는 완전일치,
|
<!-- 검색 줄. 유형을 먼저 고른다 — 유형마다 일치 방식이 달라서(차트번호는 완전일치,
|
||||||
@@ -58,7 +58,8 @@
|
|||||||
<ComboBoxItem Content="처음"/>
|
<ComboBoxItem Content="처음"/>
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
<Button x:Name="SelectButton" Content="선택" Padding="20,4" Margin="10,0,0,0"
|
<Button x:Name="SelectButton" Content="선택" Padding="20,4" Margin="10,0,0,0"
|
||||||
Click="OnSelect" IsDefault="True" IsEnabled="False"/>
|
Click="OnSelect" IsDefault="True" IsEnabled="False"
|
||||||
|
Style="{StaticResource Primary}"/>
|
||||||
<Button Content="취소" Padding="18,4" Margin="8,0,0,0" IsCancel="True"/>
|
<Button Content="취소" Padding="18,4" Margin="8,0,0,0" IsCancel="True"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
Title="미리보기" Width="900" Height="1000"
|
Title="미리보기" Width="900" Height="1000"
|
||||||
WindowStartupLocation="CenterOwner" Background="{DynamicResource B.CanvasBg}"
|
WindowStartupLocation="CenterOwner" Background="{DynamicResource B.CanvasBg}"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<ToolBarTray DockPanel.Dock="Top">
|
<ToolBarTray DockPanel.Dock="Top">
|
||||||
<ToolBar>
|
<ToolBar>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
xmlns:ctl="clr-namespace:SheetMe.Designer.Controls"
|
xmlns:ctl="clr-namespace:SheetMe.Designer.Controls"
|
||||||
Title="쿼리 편집" Width="1180" Height="760" MinWidth="880" MinHeight="520"
|
Title="쿼리 편집" Width="1180" Height="760" MinWidth="880" MinHeight="520"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<Window.Resources>
|
<Window.Resources>
|
||||||
<!-- 처음 펼쳐 둘 그룹 판단 — 가장 많이 쓰는 '환자'와 이 서식의 컨트롤만 펴 둔다 -->
|
<!-- 처음 펼쳐 둘 그룹 판단 — 가장 많이 쓰는 '환자'와 이 서식의 컨트롤만 펴 둔다 -->
|
||||||
<ctl:QueryGroupExpandedConverter x:Key="GroupExpanded"/>
|
<ctl:QueryGroupExpandedConverter x:Key="GroupExpanded"/>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
Title="신규 서식 등록" Width="420" SizeToContent="Height"
|
Title="신규 서식 등록" Width="420" SizeToContent="Height"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False" ResizeMode="NoResize"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False" ResizeMode="NoResize"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<StackPanel Margin="16">
|
<StackPanel Margin="16">
|
||||||
<TextBlock Text="E_ShtMst 에 등록되지 않은 서식입니다. 신규 등록 후 저장합니다."
|
<TextBlock Text="E_ShtMst 에 등록되지 않은 서식입니다. 신규 등록 후 저장합니다."
|
||||||
TextWrapping="Wrap" Foreground="{DynamicResource B.Muted}" Margin="0,0,0,12"/>
|
TextWrapping="Wrap" Foreground="{DynamicResource B.Muted}" Margin="0,0,0,12"/>
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
TextWrapping="Wrap" Foreground="{DynamicResource B.Muted}" FontSize="11" Margin="0,10,0,0"/>
|
TextWrapping="Wrap" Foreground="{DynamicResource B.Muted}" FontSize="11" Margin="0,10,0,0"/>
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,14,0,0">
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,14,0,0">
|
||||||
<Button Content="등록 후 저장" Padding="14,5" Click="OnConfirm" IsDefault="True"/>
|
<Button Content="등록 후 저장" Padding="14,5" Click="OnConfirm" IsDefault="True" Style="{StaticResource Primary}"/>
|
||||||
<Button Content="취소" Padding="14,5" Margin="8,0,0,0" IsCancel="True"/>
|
<Button Content="취소" Padding="14,5" Margin="8,0,0,0" IsCancel="True"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
Title="서식 수정이력" Width="560" Height="520" MinWidth="480" MinHeight="380"
|
Title="서식 수정이력" Width="560" Height="520" MinWidth="480" MinHeight="380"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<DockPanel Margin="12">
|
<DockPanel Margin="12">
|
||||||
<TextBlock x:Name="HeaderText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}"
|
<TextBlock x:Name="HeaderText" DockPanel.Dock="Top" Foreground="{DynamicResource B.Muted}"
|
||||||
TextWrapping="Wrap" Margin="0,0,0,8"/>
|
TextWrapping="Wrap" Margin="0,0,0,8"/>
|
||||||
|
|
||||||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
|
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,10,0,0">
|
||||||
<TextBlock x:Name="CountText" VerticalAlignment="Center" Margin="0,0,12,0" Foreground="{DynamicResource B.Muted}"/>
|
<TextBlock x:Name="CountText" VerticalAlignment="Center" Margin="0,0,12,0" Foreground="{DynamicResource B.Muted}"/>
|
||||||
<Button Content="열람(새 탭)" Padding="16,4" Click="OnOpen" IsDefault="True"
|
<Button Content="열람(새 탭)" Padding="16,4" Click="OnOpen" IsDefault="True" Style="{StaticResource Primary}"
|
||||||
ToolTip="선택한 버전을 새 탭으로 엽니다 — 열람 후 'DB에 저장'하면 그 내용이 새 활성 버전이 됩니다(복원)"/>
|
ToolTip="선택한 버전을 새 탭으로 엽니다 — 열람 후 'DB에 저장'하면 그 내용이 새 활성 버전이 됩니다(복원)"/>
|
||||||
<Button Content="닫기" Padding="16,4" Margin="8,0,0,0" IsCancel="True"/>
|
<Button Content="닫기" Padding="16,4" Margin="8,0,0,0" IsCancel="True"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
xmlns:ctl="clr-namespace:SheetMe.Designer.Controls"
|
xmlns:ctl="clr-namespace:SheetMe.Designer.Controls"
|
||||||
Title="태그 선택" Width="1080" Height="700" MinWidth="900" MinHeight="560"
|
Title="태그 선택" Width="1080" Height="700" MinWidth="900" MinHeight="560"
|
||||||
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
WindowStartupLocation="CenterOwner" ShowInTaskbar="False"
|
||||||
Style="{StaticResource ThemedWindow}">
|
Style="{StaticResource ThemedDialogWindow}">
|
||||||
<!--
|
<!--
|
||||||
창 껍데기는 OS 크롬을 유지한다. 목업의 '오른쪽 위 X + 둥근 카드'는 WindowStyle=None 이 필요한데,
|
창 껍데기는 OS 크롬을 유지한다. 목업의 '오른쪽 위 X + 둥근 카드'는 WindowStyle=None 이 필요한데,
|
||||||
이 앱의 대화상자 10종이 전부 OS 크롬이라 이 창만 바꾸면 크롬 규약이 두 벌이 된다.
|
이 앱의 대화상자 10종이 전부 OS 크롬이라 이 창만 바꾸면 크롬 규약이 두 벌이 된다.
|
||||||
|
|||||||
Reference in New Issue
Block a user