teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

見直しキャンペーン中

2023/07/17 13:47

投稿

TN8001
TN8001

スコア10114

answer CHANGED
@@ -1,171 +1,171 @@
1
- > PhotoShopの機能を模倣していくこと
2
-
3
- 入門者にはあまりに壮大な目標に感じますが、まあどこまでやるかによりますね。
4
-
5
- PhotoShopは持っていませんが、ツールバーにある[TEXT]ボタンを選択して画面をクリックするとそこに枠が出る(ドラッグで範囲指定?)みたいなやつですね?
6
- フォントや色を変更できて、欲を言えばマウスで移動やリサイズができる。と
7
-
8
-
9
- 凝ったUIの作りこみはロジック以上に難しいことが多いです(私はあまり手を出さないようにしています^^;
10
- とはいえ出発点としてミニマムかつ、そこそこ遊べるような参考コードを書いてみました。
11
-
12
- [仕様]
13
- 画像エリアをダブルクリックでその場所にTextBoxを生成
14
- TextBoxの右クリックメニューに削除(コピー等はTextBoxのコピーではなく、テキストのコピー)
15
- テキストの編集はその場で可能(複数行に対応)
16
- ほかのプロパティはPropertyGridで編集(クリックしたTextBoxをPropertyGridに割り当てるため、選択が少し重いです)
17
- - 移動はCanvasLeft CanvasTop
18
- - サイズはWidth Height(NaNで自動調整)
19
- - フォントはFontなんちゃら
20
- - 色はForeground
21
-
22
-
23
-
24
- NuGetから`Extended.Wpf.Toolkit`をインストールしてください(PropertyGridだけ使います)
25
-
26
- ```xaml
27
- <Window
28
- x:Class="Questions233943.MainWindow"
29
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
30
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
31
- xmlns:local="clr-namespace:Questions233943"
32
- xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
33
- Width="800"
34
- Height="450">
35
- <Window.Resources>
36
- <ContextMenu x:Key="TextBoxContextMenu">
37
- <MenuItem Command="ApplicationCommands.Copy" />
38
- <MenuItem Command="ApplicationCommands.Cut" />
39
- <MenuItem Command="ApplicationCommands.Paste" />
40
- <MenuItem Click="DelMenuItem_Click" Header="削除" />
41
- </ContextMenu>
42
-
43
- <Style x:Key="TextBoxStyle" TargetType="{x:Type local:TextBoxEx}">
44
- <Setter Property="AcceptsReturn" Value="True" />
45
- <Setter Property="AcceptsTab" Value="True" />
46
- <Setter Property="Background" Value="{x:Null}" />
47
- <Setter Property="BorderBrush" Value="{x:Null}" />
48
- <Setter Property="ContextMenu" Value="{StaticResource TextBoxContextMenu}" />
49
- <Setter Property="FontSize" Value="16px" />
50
- <Setter Property="FontWeight" Value="bold" />
51
- <Setter Property="Foreground" Value="Red" />
52
- <Setter Property="Text" Value="テキスト" />
53
- <Setter Property="TextWrapping" Value="Wrap" />
54
- <Setter Property="Template">
55
- <Setter.Value>
56
- <ControlTemplate TargetType="{x:Type TextBox}">
57
- <Border
58
- x:Name="border"
59
- Background="{TemplateBinding Background}"
60
- BorderBrush="{TemplateBinding BorderBrush}"
61
- BorderThickness="{TemplateBinding BorderThickness}"
62
- SnapsToDevicePixels="True">
63
- <ScrollViewer
64
- x:Name="PART_ContentHost"
65
- Focusable="false"
66
- HorizontalScrollBarVisibility="Hidden"
67
- VerticalScrollBarVisibility="Hidden" />
68
- </Border>
69
- <ControlTemplate.Triggers>
70
- <Trigger Property="IsMouseOver" Value="true">
71
- <Setter TargetName="border" Property="BorderBrush" Value="#FF7EB4EA" />
72
- </Trigger>
73
- <Trigger Property="IsFocused" Value="true">
74
- <Setter TargetName="border" Property="BorderBrush" Value="#FF7EB4EA" />
75
- </Trigger>
76
- </ControlTemplate.Triggers>
77
- </ControlTemplate>
78
- </Setter.Value>
79
- </Setter>
80
- </Style>
81
- </Window.Resources>
82
- <Grid>
83
- <Grid.ColumnDefinitions>
84
- <ColumnDefinition Width="2*" />
85
- <ColumnDefinition Width="5" />
86
- <ColumnDefinition />
87
- </Grid.ColumnDefinitions>
88
- <Canvas x:Name="canvas" MouseLeftButtonDown="Canvas_MouseLeftButtonDown">
89
- <Image Source="Resources\whippet.jpg" />
90
- </Canvas>
91
- <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
92
- <xctk:PropertyGrid x:Name="propertyGrid" Grid.Column="2" />
93
- </Grid>
94
- </Window>
95
- ```
96
-
97
- ```C#
98
- using System.Windows;
99
- using System.Windows.Controls;
100
- using System.Windows.Input;
101
-
102
- namespace Questions233943
103
- {
104
- // PropertyGridでいじれるようにCanvas.Left Canvas.Topをラップ
105
- public class TextBoxEx : TextBox
106
- {
107
- public static readonly DependencyProperty CanvasLeftProperty
108
- = DependencyProperty.Register(nameof(CanvasLeft), typeof(double), typeof(TextBoxEx),
109
- new FrameworkPropertyMetadata(0d, new PropertyChangedCallback(OnCanvasLeftChanged)));
110
- public double CanvasLeft { get => (double)GetValue(CanvasLeftProperty); set => SetValue(CanvasLeftProperty, value); }
111
- private static void OnCanvasLeftChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
112
- {
113
- if(obj is TextBoxEx ctrl) Canvas.SetLeft(ctrl, ctrl.CanvasLeft);
114
- }
115
-
116
- public static readonly DependencyProperty CanvasTopProperty
117
- = DependencyProperty.Register(nameof(CanvasTop), typeof(double), typeof(TextBoxEx),
118
- new FrameworkPropertyMetadata(0d, new PropertyChangedCallback(OnCanvasTopChanged)));
119
- public double CanvasTop { get => (double)GetValue(CanvasTopProperty); set => SetValue(CanvasTopProperty, value); }
120
- private static void OnCanvasTopChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
121
- {
122
- if(obj is TextBoxEx ctrl) Canvas.SetTop(ctrl, ctrl.CanvasTop);
123
- }
124
- }
125
-
126
- public partial class MainWindow : Window
127
- {
128
- public MainWindow() => InitializeComponent();
129
-
130
- private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
131
- {
132
- if(e.ClickCount == 2)
133
- {
134
- var textBox = new TextBoxEx
135
- {
136
- Style = FindResource("TextBoxStyle") as Style,
137
- CanvasLeft = e.GetPosition(canvas).X,
138
- CanvasTop = e.GetPosition(canvas).Y
139
- };
140
- textBox.GotFocus += TextBox_GotFocus;
141
- canvas.Children.Add(textBox);
142
- }
143
- }
144
-
145
- private void TextBox_GotFocus(object sender, RoutedEventArgs e)
146
- => propertyGrid.SelectedObject = sender;
147
-
148
- private void DelMenuItem_Click(object sender, RoutedEventArgs e)
149
- {
150
- if(sender is MenuItem menuItem)
151
- {
152
- if(menuItem.Parent is ContextMenu contextMenu)
153
- {
154
- if(contextMenu.PlacementTarget is TextBoxEx textBox)
155
- {
156
- propertyGrid.SelectedObject = null;
157
- textBox.GotFocus -= TextBox_GotFocus;
158
- canvas.Children.Remove(textBox);
159
- }
160
- }
161
- }
162
- }
163
- }
164
- }
165
- ```
166
-
167
- ---
168
-
169
- マウスでサイズ変更・移動をちゃんとやるなら、この辺を参考に頑張ってください。
170
- * 大変古いが公式の [ResizingAdorner のサンプル | Microsoft Docs](https://docs.microsoft.com/ja-jp/previous-versions/dotnet/netframework-3.5/ms771714(v=vs.90)?redirectedfrom=MSDN)(ざっとやってみたが移動とテキストの編集を、どう両立させるかがむずかしい)
1
+ > PhotoShopの機能を模倣していくこと
2
+
3
+ 入門者にはあまりに壮大な目標に感じますが、まあどこまでやるかによりますね。
4
+
5
+ PhotoShopは持っていませんが、ツールバーにある[TEXT]ボタンを選択して画面をクリックするとそこに枠が出る(ドラッグで範囲指定?)みたいなやつですね?
6
+ フォントや色を変更できて、欲を言えばマウスで移動やリサイズができる。と
7
+
8
+
9
+ 凝ったUIの作りこみはロジック以上に難しいことが多いです(私はあまり手を出さないようにしています^^;
10
+ とはいえ出発点としてミニマムかつ、そこそこ遊べるような参考コードを書いてみました。
11
+
12
+ [仕様]
13
+ 画像エリアをダブルクリックでその場所に`TextBox`を生成
14
+ `TextBox`の右クリックメニューに削除(コピー等は`TextBox`のコピーではなく、テキストのコピー)
15
+ テキストの編集はその場で可能(複数行に対応)
16
+ ほかのプロパティは`PropertyGrid`で編集(クリックした`TextBox``PropertyGrid`に割り当てるため、選択が少し重いです)
17
+ - 移動は`CanvasLeft`・`CanvasTop`
18
+ - サイズは`Width`・`Height``NaN`で自動調整)
19
+ - フォントはFontなんちゃら
20
+ - 色は`Foreground`
21
+
22
+
23
+
24
+ NuGetから`Extended.Wpf.Toolkit`をインストールしてください(`PropertyGrid`だけ使います)
25
+
26
+ ```xml
27
+ <Window
28
+ x:Class="Questions233943.MainWindow"
29
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
30
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
31
+ xmlns:local="clr-namespace:Questions233943"
32
+ xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
33
+ Width="800"
34
+ Height="450">
35
+ <Window.Resources>
36
+ <ContextMenu x:Key="TextBoxContextMenu">
37
+ <MenuItem Command="ApplicationCommands.Copy" />
38
+ <MenuItem Command="ApplicationCommands.Cut" />
39
+ <MenuItem Command="ApplicationCommands.Paste" />
40
+ <MenuItem Click="DelMenuItem_Click" Header="削除" />
41
+ </ContextMenu>
42
+
43
+ <Style x:Key="TextBoxStyle" TargetType="{x:Type local:TextBoxEx}">
44
+ <Setter Property="AcceptsReturn" Value="True" />
45
+ <Setter Property="AcceptsTab" Value="True" />
46
+ <Setter Property="Background" Value="{x:Null}" />
47
+ <Setter Property="BorderBrush" Value="{x:Null}" />
48
+ <Setter Property="ContextMenu" Value="{StaticResource TextBoxContextMenu}" />
49
+ <Setter Property="FontSize" Value="16px" />
50
+ <Setter Property="FontWeight" Value="bold" />
51
+ <Setter Property="Foreground" Value="Red" />
52
+ <Setter Property="Text" Value="テキスト" />
53
+ <Setter Property="TextWrapping" Value="Wrap" />
54
+ <Setter Property="Template">
55
+ <Setter.Value>
56
+ <ControlTemplate TargetType="{x:Type TextBox}">
57
+ <Border
58
+ x:Name="border"
59
+ Background="{TemplateBinding Background}"
60
+ BorderBrush="{TemplateBinding BorderBrush}"
61
+ BorderThickness="{TemplateBinding BorderThickness}"
62
+ SnapsToDevicePixels="True">
63
+ <ScrollViewer
64
+ x:Name="PART_ContentHost"
65
+ Focusable="false"
66
+ HorizontalScrollBarVisibility="Hidden"
67
+ VerticalScrollBarVisibility="Hidden" />
68
+ </Border>
69
+ <ControlTemplate.Triggers>
70
+ <Trigger Property="IsMouseOver" Value="true">
71
+ <Setter TargetName="border" Property="BorderBrush" Value="#FF7EB4EA" />
72
+ </Trigger>
73
+ <Trigger Property="IsFocused" Value="true">
74
+ <Setter TargetName="border" Property="BorderBrush" Value="#FF7EB4EA" />
75
+ </Trigger>
76
+ </ControlTemplate.Triggers>
77
+ </ControlTemplate>
78
+ </Setter.Value>
79
+ </Setter>
80
+ </Style>
81
+ </Window.Resources>
82
+ <Grid>
83
+ <Grid.ColumnDefinitions>
84
+ <ColumnDefinition Width="2*" />
85
+ <ColumnDefinition Width="5" />
86
+ <ColumnDefinition />
87
+ </Grid.ColumnDefinitions>
88
+ <Canvas x:Name="canvas" MouseLeftButtonDown="Canvas_MouseLeftButtonDown">
89
+ <Image Source="Resources\whippet.jpg" />
90
+ </Canvas>
91
+ <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
92
+ <xctk:PropertyGrid x:Name="propertyGrid" Grid.Column="2" />
93
+ </Grid>
94
+ </Window>
95
+ ```
96
+
97
+ ```cs
98
+ using System.Windows;
99
+ using System.Windows.Controls;
100
+ using System.Windows.Input;
101
+
102
+ namespace Questions233943
103
+ {
104
+ // PropertyGridでいじれるようにCanvas.Left Canvas.Topをラップ
105
+ public class TextBoxEx : TextBox
106
+ {
107
+ public static readonly DependencyProperty CanvasLeftProperty
108
+ = DependencyProperty.Register(nameof(CanvasLeft), typeof(double), typeof(TextBoxEx),
109
+ new FrameworkPropertyMetadata(0d, new PropertyChangedCallback(OnCanvasLeftChanged)));
110
+ public double CanvasLeft { get => (double)GetValue(CanvasLeftProperty); set => SetValue(CanvasLeftProperty, value); }
111
+ private static void OnCanvasLeftChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
112
+ {
113
+ if(obj is TextBoxEx ctrl) Canvas.SetLeft(ctrl, ctrl.CanvasLeft);
114
+ }
115
+
116
+ public static readonly DependencyProperty CanvasTopProperty
117
+ = DependencyProperty.Register(nameof(CanvasTop), typeof(double), typeof(TextBoxEx),
118
+ new FrameworkPropertyMetadata(0d, new PropertyChangedCallback(OnCanvasTopChanged)));
119
+ public double CanvasTop { get => (double)GetValue(CanvasTopProperty); set => SetValue(CanvasTopProperty, value); }
120
+ private static void OnCanvasTopChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
121
+ {
122
+ if(obj is TextBoxEx ctrl) Canvas.SetTop(ctrl, ctrl.CanvasTop);
123
+ }
124
+ }
125
+
126
+ public partial class MainWindow : Window
127
+ {
128
+ public MainWindow() => InitializeComponent();
129
+
130
+ private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
131
+ {
132
+ if(e.ClickCount == 2)
133
+ {
134
+ var textBox = new TextBoxEx
135
+ {
136
+ Style = FindResource("TextBoxStyle") as Style,
137
+ CanvasLeft = e.GetPosition(canvas).X,
138
+ CanvasTop = e.GetPosition(canvas).Y
139
+ };
140
+ textBox.GotFocus += TextBox_GotFocus;
141
+ canvas.Children.Add(textBox);
142
+ }
143
+ }
144
+
145
+ private void TextBox_GotFocus(object sender, RoutedEventArgs e)
146
+ => propertyGrid.SelectedObject = sender;
147
+
148
+ private void DelMenuItem_Click(object sender, RoutedEventArgs e)
149
+ {
150
+ if(sender is MenuItem menuItem)
151
+ {
152
+ if(menuItem.Parent is ContextMenu contextMenu)
153
+ {
154
+ if(contextMenu.PlacementTarget is TextBoxEx textBox)
155
+ {
156
+ propertyGrid.SelectedObject = null;
157
+ textBox.GotFocus -= TextBox_GotFocus;
158
+ canvas.Children.Remove(textBox);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+ ```
166
+
167
+ ---
168
+
169
+ マウスでサイズ変更・移動をちゃんとやるなら、この辺を参考に頑張ってください。
170
+ * 大変古いが公式の [ResizingAdorner のサンプル | Microsoft Docs](https://docs.microsoft.com/ja-jp/previous-versions/dotnet/netframework-3.5/ms771714(v=vs.90)?redirectedfrom=MSDN)(ざっとやってみたが移動とテキストの編集を、どう両立させるかがむずかしい)
171
171
  * 「WPF ラバーバンド」あたりで検索