質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

3757閲覧

C# WPFで、画像の形をしたコントロールを作成したい

Lyricania0220

総合スコア11

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

1グッド

0クリップ

投稿2020/03/09 12:40

前提・実現したいこと

イメージ説明

上画像のような形をしたコントロールを作成したいです。
画像は透過pngで、透過部をクリックしてもクリックイベントを発生しないようにしたいです。

自作コントロールにて強引に作成してみましたが、可能ならばボタンスタイルやテンプレートで作成したいと考えております。

該当のソースコード

下記のコードはImageを継承したコントロールにクリックイベントを追加して無理やり作成したものです。

C#

1using System.Drawing; 2using System.Drawing.Imaging; 3using System.Windows; 4using System.Windows.Input; 5using System.Windows.Media.Imaging; 6 7namespace ImageButtonTest 8{ 9 public class ImageButton : System.Windows.Controls.Image 10 { 11 /// <summary> 12 /// 設定された画像の透明領域(アルファ値ゼロ)以外がクリックされたときに発生します。 13 /// </summary> 14 public event MouseButtonEventHandler Click; 15 16 /// <summary> 17 /// マウスボタンを押し上げたときに発生します。 18 /// </summary> 19 /// <param name="e">イベントデータ</param> 20 protected override void OnMouseUp(MouseButtonEventArgs e) 21 { 22 var imageSource = Source as BitmapSource; 23 if (imageSource == null)return; 24 25 var clickEventFlag = false; 26 27 if (Click != null) 28 { 29 // クリック位置を取得する 30 var point = (e.GetPosition(this)); 31 32 // ボタンサイズを考慮し、画像上での座標を求める 33 point = new System.Windows.Point(point.X * ((double)imageSource.PixelWidth / ActualWidth), 34 point.Y * ((double)imageSource.PixelHeight / ActualHeight)); 35 36 // クリックした座標の色を取得する 37 var color = GetColorForPoint(imageSource, point); 38 39 if (color.A != 0) 40 { 41 // クリック箇所のアルファ値がゼロでないときは透過部でないと判断する 42 clickEventFlag = true; 43 } 44 } 45 46 if (clickEventFlag == true) 47 { 48 // マウスクリックイベントを発生させるので、現在のイベントのハンドルはキャンセルしておく 49 e.Handled = true; 50 Click(this, e); 51 } 52 else 53 { 54 // 通常のマウスアップイベントを発生させる 55 base.OnMouseUp(e); 56 } 57 } 58 59 /// <summary> 60 /// ビットマップソースに設定された画像の指定の色を取得します。 61 /// </summary> 62 /// <param name="bitmapSourc">色を取得したいビットマップソース</param> 63 /// <param name="point">座標</param> 64 /// <returns></returns> 65 private System.Windows.Media.Color GetColorForPoint(BitmapSource bitmapSourc, System.Windows.Point point) 66 { 67 // まずはビットマップソースをビットマップ画像に変換する 68 var bitmap = ConvertBitmapSourceToBitmap(bitmapSourc); 69 70 // 指定座標の色を取得する(この時点では「System.Drawing.Color」型) 71 var color = bitmap.GetPixel((int)point.X, (int)point.Y); 72 73 // 取得した色を「System.Windows.Media.Color」型に変換して戻す 74 return System.Windows.Media.Color.FromArgb(color.A, color.R, color.G, color.B); 75 } 76 77 /// <summary> 78 /// ビットマップソースをビットマップ画像に変換します。 79 /// </summary> 80 /// <param name="bitmapSource"></param> 81 /// <returns></returns> 82 private Bitmap ConvertBitmapSourceToBitmap(BitmapSource bitmapSource) 83 { 84 var bitmap = new Bitmap(bitmapSource.PixelWidth, 85 bitmapSource.PixelHeight, 86 System.Drawing.Imaging.PixelFormat.Format32bppPArgb); 87 BitmapData bitmapData = null; 88 89 var rect = new Rectangle(System.Drawing.Point.Empty, bitmap.Size); 90 try 91 { 92 bitmapData = bitmap.LockBits(rect, 93 ImageLockMode.WriteOnly, 94 System.Drawing.Imaging.PixelFormat.Format32bppPArgb); 95 96 bitmapSource.CopyPixels(Int32Rect.Empty, 97 bitmapData.Scan0, 98 bitmapData.Height * bitmapData.Stride, 99 bitmapData.Stride); 100 } 101 catch 102 { 103 bitmap.Dispose(); 104 bitmap = null; 105 throw; 106 } 107 108 bitmap.UnlockBits(bitmapData); 109 110 return bitmap; 111 } 112 } 113} 114

開発環境

Visual Studio 2017
.NET Framework 4.8

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

画像のクリックスルーは、それなりに面倒そうですね。
WPF: Detect Image click only on non-transparent portion - Stack Overflow

リンクのOpaqueClickableImageを使ったもの

xml

1<Window 2 x:Class="Questions246137.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="clr-namespace:Questions246137" 6 Width="800" 7 Height="450"> 8 <Grid> 9 <Button Click="Button_Click"> 10 <Button.Template> 11 <ControlTemplate TargetType="{x:Type Button}"> 12 <ContentPresenter Content="{TemplateBinding Content}" /> 13 </ControlTemplate> 14 </Button.Template> 15 <local:OpaqueClickableImage Source="star.png" Stretch="None" /> 16 </Button> 17 </Grid> 18</Window>

マウスオーバーやクリックの変化はありません。


簡単な図形ならMicrosoft Blend for Visual Studioで、作ってしまうのはどうでしょう?

雑にBlendで作ったもの(DLLが入ってしまうのが難点)

xml

1<Window 2 x:Class="Questions246137.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing" 6 Width="800" 7 Height="450"> 8 <Window.Resources> 9 <Style x:Key="ButtonStyle1" TargetType="{x:Type Button}"> 10 <Setter Property="Template"> 11 <Setter.Value> 12 <ControlTemplate TargetType="{x:Type Button}"> 13 <Grid> 14 <ed:RegularPolygon 15 Width="150" 16 Height="150" 17 Fill="Yellow" 18 InnerRadius="0.66" 19 PointCount="6" 20 Stretch="Fill" 21 Stroke="Black" 22 StrokeThickness="8" /> 23 <ed:RegularPolygon 24 x:Name="shadow" 25 Width="150" 26 Height="150" 27 Fill="Black" 28 InnerRadius="0.66" 29 Opacity="0" 30 PointCount="6" /> 31 </Grid> 32 <ControlTemplate.Triggers> 33 <Trigger Property="IsMouseOver" Value="true"> 34 <Setter TargetName="shadow" Property="Opacity" Value="0.1" /> 35 </Trigger> 36 <Trigger Property="IsPressed" Value="true"> 37 <Setter TargetName="shadow" Property="Opacity" Value="0.2" /> 38 </Trigger> 39 </ControlTemplate.Triggers> 40 </ControlTemplate> 41 </Setter.Value> 42 </Setter> 43 </Style> 44 </Window.Resources> 45 <Grid> 46 <Button Style="{DynamicResource ButtonStyle1}" Click="Button_Click" /> 47 </Grid> 48</Window>

凝ったものはMicrosoft Expression Design 4がまだダウンロードできますので、画像からPathに変換するのもいいかもしれません。

投稿2020/03/09 15:09

編集2023/07/21 08:44
TN8001

総合スコア9220

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lyricania0220

2020/03/10 12:10

回答ありがとうございます。 スタイルやテンプレートだけで実現するのは無理そうなのですね… 提示した画像以外にも透過画像ボタンとして使用したいものがありますので、「OpaqueClickableImage」を使用する方法で行こうと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問