WPFではアプリのウィンドウにボタンとかのコン
トロールを複数表示させるには
その中に色々ボタンとかのコン
トロールを置いていくみたい
<Window>
<パネル系のコントロール>
<いろいろ>
</いろいろ>
<いろいろ>
</いろいろ>
</パネル系のコントロール>
</Window>
アプリを新規作成した時に最初から設置されているのがGridなので
Gridが代表格なのかも、その他でよく見かけるのがStackPanel
Canvas、TabControl、WrapPanelとか他にもあるみたい
癖がなくて使いやすそうな感じなのが
両方試してみた
このふたつは特に指定しないと置いた場所全体に広がる
Windowに置けばWindow全体に広がる
コン
トロールのドラッグ移動で必要なのが位置の取得と指定なんだけど
Gridの場合
Marginプロパティで場所指定する
左寄せと上寄せをしないと変な位置になるので
HorizontalAlignment="Left" VerticalAlignment="Top"を指定している
Marginの4つの数字は順番に左、上、右、下の値になる
左寄せと上寄せを指定するとMarginの右と下の値は無視される
マウスドラッグでコン
トロールを移動させる処理の流れ
マウスダウンイベントで
ドラッグ移動中フラグにする
最初のマウスの位置を記録しておく
マウスムーブイベントで
ドラッグ移動中フラグなら
動かした今の位置から最初の位置を引き算して移動距離を測る
移動距離と動かしているコン
トロールの今の位置を足し算したのが
移動させる位置なのでこれを指定する
マウスアップイベントで
ドラッグ移動中フラグを解除
Grid編
最初からあるGridにgrid1と言う名前を付けただけ
Class MainWindow
Private syokiX As Double
Private syokiY As Double
Private IsDrag As Boolean
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Dim r As New Rectangle
Dim b As New SolidColorBrush(Color.FromArgb(128, 255, 0, 0))
With r
.Width = 100
.Height = 100
.Fill = b
.Margin = New Thickness(10, 20, 0, 0)
.HorizontalAlignment = HorizontalAlignment.Left
.VerticalAlignment = VerticalAlignment.Top
End With
grid1.Children.Add(r)
AddHandler r.MouseDown, AddressOf Rectangle_MouseDown
AddHandler r.MouseMove, AddressOf Rectangle_MouseMove
AddHandler r.MouseUp, AddressOf Rectangle_MouseUp
End Sub
Private Sub Rectangle_MouseDown(sender As Rectangle, e As MouseButtonEventArgs)
syokiX = e.GetPosition(sender).X
syokiY = e.GetPosition(sender).Y
IsDrag = True
sender.CaptureMouse()
End Sub
Private Sub Rectangle_MouseMove(sender As Rectangle, e As MouseEventArgs)
If IsDrag Then
Dim p As Point = e.GetPosition(sender)
Dim t As New Thickness
t.Left = p.X - syokiX + sender.Margin.Left
t.Top = p.Y - syokiY + sender.Margin.Top
sender.Margin = t
End If
End Sub
Private Sub Rectangle_MouseUp(sender As Rectangle, e As MouseButtonEventArgs)
IsDrag = False
sender.ReleaseMouseCapture()
End Sub
End Class
Loadedイベントの時にRectangleを作成してgrid1に追加している。
位置の指定はMarginプロパティに
Thicknessっていう見慣れないのを指定している
Thicknessってのは構造体なのかな?4つの数値を入れることができる
位置の取得は
sender(動かしているコン
トロール).Margin.leftとかでそのまま取得できる
Class MainWindow
Private syokiX As Double
Private syokiY As Double
Private IsDrag As Boolean
Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Dim r As New Rectangle
Dim b As New SolidColorBrush(Color.FromArgb(128, 255, 0, 0))
With r
.Width = 100
.Height = 100
.Fill = b
.HorizontalAlignment = HorizontalAlignment.Left
.VerticalAlignment = VerticalAlignment.Top
End With
canvas1.Children.Add(r)
Canvas.SetLeft(r, 10)
Canvas.SetTop(r, 20)
AddHandler r.MouseDown, AddressOf Rectangle_MouseDown
AddHandler r.MouseMove, AddressOf Rectangle_MouseMove
AddHandler r.MouseUp, AddressOf Rectangle_MouseUp
End Sub
Private Sub Rectangle_MouseDown(sender As Rectangle, e As MouseButtonEventArgs)
syokiX = e.GetPosition(sender).X
syokiY = e.GetPosition(sender).Y
IsDrag = True
sender.CaptureMouse()
End Sub
Private Sub Rectangle_MouseMove(sender As Rectangle, e As MouseEventArgs)
If IsDrag Then
Dim p As Point = e.GetPosition(sender)
Canvas.SetLeft(sender, p.X - syokiX + Canvas.GetLeft(sender))
Canvas.SetTop(sender, p.Y - syokiY + Canvas.GetTop(sender))
End If
End Sub
Private Sub Rectangle_MouseUp(sender As Rectangle, e As MouseButtonEventArgs)
IsDrag = False
sender.ReleaseMouseCapture()
End Sub
End Class
位置の指定は
CanvasクラスのSetLeftとSetTopメソッドを使っている
動かしているコン
トロールの今の位置を取得するときは
GetLeftとGetTopメソッド、わかりやすい
実行した時の画面
見た目も動きも全く同じ
グリグリ動かした時のCPUの占有率も同じくらいで8%前後
動くのと動かないの
ここまでの方法で動かしたコントロールはRectangle
その時はイベントの時に使うメソッドの引数の型をRectangleからObjectに変更
Private Sub Rectangle_MouseDown(sender As Rectangle, e As MouseButtonEventArgs)
Private Sub Rectangle_MouseDown(sender As Object, e As MouseButtonEventArgs)
動かせたのはImage、TabControl、Ellipse
動かないのはButton、ComboBox
動かしたいのは画像なので画像表示に便利そうなImageが動けばいいや
っていうのがあってマウスでのドラッグ移動に便利なイベントを持っている
その名もDragDelta
引数の(e As DragDeltaEventArgs)からマウスの移動距離が取得できる
e.HorizontalChangeで横の移動距離
e.VerticalChangeで縦の移動距離
スゴイ
これだけで動く、実質2行
しかもグリグリ動かした時のCPU占有率が4%前後と低い!
だけど見た目が…
例えば
↓
なので枠の付かない
ImageコントロールにDragDeltaイベントがあればいいんだけどなあ
ThumbだとDragDeltaイベントが候補に出てくるけど
ThumbのBackgroundに半透明の画像を指定しても透過処理にならない
二つのThumbコン
トロールは半透明のブラシを使って
塗りつぶしているんだけど透過処理になってない
Imageコン
トロールはSourceに半透明の画像を指定するだけで
透過処理になっていたんだけどなあ
Backgroundではならないみたい
ImageコントロールにDragDeltaイベントを付ける方法が
ここまでとこの前の
画像ファイルドロップで表示した画像を
マウスドラッグで移動できる
それにしても半透明の透過処理を自動でしてくれる
WPFはスゴイ
このテストアプリの中身
デザイン画面
コピペして作ったから
コメントアウトでの説明がRectangleのままになっているw
例外処理してないから画像以外のファイルをドロップするとエラーになる
Imports System.IO
Class MainWindow
Private syokiX As Double
Private syokiY As Double
Private IsDrag As Boolean
Private Sub MainWindow_Drop(sender As Object, e As DragEventArgs) Handles Me.Drop
Dim filesPath() As String = e.Data.GetData(DataFormats.FileDrop)
Dim locate As New Point(0, 0)
For i As Integer = 0 To filesPath.Length - 1
Call AddImage(filesPath(i), locate)
locate.Offset(30, 30)
Next
End Sub
Private Function GetBitmapImage(filePath As String) As BitmapImage
Dim bmp As New BitmapImage
Using fs As New FileStream(filePath, FileMode.Open, FileAccess.Read)
With bmp
.BeginInit()
.StreamSource = fs
.CacheOption = BitmapCacheOption.OnLoad
.EndInit()
.Freeze()
End With
End Using
Return bmp
End Function
Private Sub AddImage(filesPath As String, locate As Point)
Dim bmp As BitmapImage = GetBitmapImage(filesPath)
Dim img As New Image
With img
.Source = bmp
.Width = bmp.PixelWidth
.Height = bmp.PixelHeight
End With
canvas1.Children.Add(img)
Canvas.SetLeft(img, locate.X)
Canvas.SetTop(img, locate.Y)
AddHandler img.MouseDown, AddressOf Image_MouseDown
AddHandler img.MouseMove, AddressOf Image_MouseMove
AddHandler img.MouseUp, AddressOf Image_MouseUp
End Sub
Private Sub Image_MouseDown(sender As Image, e As MouseButtonEventArgs)
syokiX = e.GetPosition(sender).X
syokiY = e.GetPosition(sender).Y
IsDrag = True
sender.CaptureMouse()
End Sub
Private Sub Image_MouseMove(sender As Image, e As MouseEventArgs)
If IsDrag Then
Dim p As Point = e.GetPosition(sender)
Canvas.SetLeft(sender, p.X - syokiX + Canvas.GetLeft(sender))
Canvas.SetTop(sender, p.Y - syokiY + Canvas.GetTop(sender))
End If
End Sub
Private Sub Image_MouseUp(sender As Image, e As MouseButtonEventArgs)
IsDrag = False
sender.ReleaseMouseCapture()
End Sub
End Class
予定しているテスト
- 表示画像すべてを画像ファイルとして保存
- ドラッグ移動時に指定ピクセルごとに移動
- 表示画像のレイヤー間の移動(入れ替え)ZOrder指定
- 指定した色を透明にする
- レイアウト
上の3つは必要な機能