Click button through only part of a transparent image in wpf program - c#

I am trying to implement the ability to click through only part of a transparent background. The background image is a solid gray and has 3 circles, a rectangle, and an oval shape. The image is transparent. Button 1 appears inside of the rectangle and button 2 appears inside of the oval. When the program runs both buttons are visible but currently not clickable because the image is in a grid and added after the buttons. I would like to make only the rectangle click through so button 1 can be clicked, but still keep the image ahead of button 2 so it is not clickable.
I've searched around quite a bit for a solution but have not found what I'm looking for. This example is a dumbed down version of what I'm currently working on - but the functionality is essentially the same. Any help would be appreciated.
Xaml:
<Window x:Class="TransparentClickThrough.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button x:Name="ButtonOne" Click="ButtonOne_Click" Content="Button1" Width="50" Height="25" ></Button>
<Button x:Name="ButtonTwo" Content="Button2" Width="50" Height="25" Margin="379,100,59,148" Click="ButtonTwo_Click"></Button>
<Image Source="/TransparentClickThrough;component/background.png" />
</Grid>
</Window>
Code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace TransparentClickThrough
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonOne_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("You clicked button 1!");
}
private void ButtonTwo_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("You clicked button 2!");
}
}
}
background - 3 circles, rectangle, and oval are all set to transparent
This is what the program looks like when running.

I was able to just add a Rectangle with transparent fill to the grid. Then I added an event "MouseDown" Interaction trigger to toggle the Visibility through a DataTrigger which in turn changed the background color.
Similar to this link link

Related

WPF MainWindow differs at runtime from it's expected outcome

I am relatively new to this platform, so forgive me for my lack of professionalism.
I encountered a problem while creating one of my first WPF applications.
I managed to include some buttons in MainWindow and run it, but I spotted some bugs, so I tried to start from the scratch.
I decided to run an empty window, but then i saw the previous "buggy" window at runtime. Since then, no matter what i change in MainWindow.xaml file i get the same old result.
I tried to chceck whether my program compiles, and for what I know it does.
Unfortunately I erased old xaml code responsible for "buggy" window, but I can recall it was something like this.
<Window x:Class="ProjektPO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ProjektPO"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="A" Content="B" Click="A_Click"/>
</Grid>
</StackPanel>
</Grid>
</Window>
And the .cs file (almost default)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ProjektPO
{
/// <summary>
/// Logika interakcji dla klasy MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void A_Click(object sender, RoutedEventArgs e)
{
}
}
}
Program compiles and dispalys old "buggy" Window.

How to make my WPF Textblock Ticker animation (Marquee) smoother? [duplicate]

This question already has answers here:
How to make the animation smoother through code in WPF?
(3 answers)
WPF: Animation is not smooth
(1 answer)
WPF Jitters with TranslateTransform and Canvas.SetLeft
(1 answer)
Why creating non storyboard animation is not smooth
(1 answer)
Closed 5 years ago.
The following text block ticker animation is not smooth at all. So need some guidance on how to make this double animation smoother for more user friendliness as I will be integrating RSS news feed in there after that.
XAML CODE:
<Window x:Class="Wpf_Marquee.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Wpf_Marquee"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Canvas Margin="50" Canvas.Left="150" Canvas.Top="100" ClipToBounds="True" Name="canMain" Background="Red" Height="100" Width="400" >
<TextBlock x:Name="marquee" Margin="0 50 0 0" FontSize="20pt" Foreground="Black" Background="Transparent" Canvas.Left="0" Canvas.Right="68">
Hello This is a Sample Marquee in Wpf. Please check the animation
</TextBlock>
<Button x:Name="btn1" Width="50" Height="50" Content="Marquee" Click="Button_Click" />
</Canvas>
Where as my .CS code is as follows
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
namespace Wpf_Marquee
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void Button_Click(object sender, RoutedEventArgs e)
{
DoubleAnimation doubleAnimation = new DoubleAnimation();
doubleAnimation.From = this.ActualWidth;
doubleAnimation.To = -marquee.ActualWidth;
doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(2060)); // provide an appropriate duration
marquee.BeginAnimation(Canvas.LeftProperty, doubleAnimation);
}
}
}
Thanks in advance for your help :)

Textblock/Textbox in XAML and C#

I am a complete "weekend warrior" to programming so go gentle on me, please...
I want to achieve a simple task, which I had no problem with in plain C# (TextBox.Text = "Something";)
I have a textbox and a textblock in XAML, and I want to populate them from C#, simple as that - run the web app and pull the predefined strings from the C# code. I have been searching for 2 days now and can't find a straight answer. I don't want any triggers (buttons), just filling e.g. textbox on load with a C# string. A simple code example on both XAML and C# side would be greatly appreciated!
Cheers,
Sasa
Not sure if I'm understanding your question...
<!--xaml-->
<TextBox x:Name="txtMyTextBox"/>
// C#
// Window constructor
public MyWindow()
{
InitializeComponent();
txtMyTextBox.Text = "Something";
}
One simple way to achieve what you try to achieve (if I understood correctly), is to add the UI elements to your window and set a Name for each of them. This way, you can access them in your code-behind as seen below.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
<TextBox Name="TextBox1" HorizontalAlignment="Left" Height="23" Margin="37,37,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
<TextBlock Name="TextBlock1" HorizontalAlignment="Left" Margin="48,100,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="103" Width="239"/>
</Grid>
</Window>
While there are certainly more "refined" ways to achieve the same, once you named your UI elements in xaml, you can access them just as other object instances in your code-behind.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
TextBox1.Text = "Hello TextBox1!";
TextBlock1.Text = "Hello TextBlock1!";
}
}
}

WPF could not get touch position from MouseDown event

I have a WPF project written before touch support was added to .NET (v 4.0), so only the mouse events were handled. I run into this problem when testing the project on a touch screen with fingers.
The problem is, the position (X, Y) is correctly retrieved in the first touch, but the (X, Y) values stay the same in subsequent touches, no matter where I touch, and even if I touch out of the Image, the MouseDown event is fired, which makes it more weird.
It can be reproduced with .NET 3.0/3.5/4.0, tested on Win7/Win8, both are 64 bits. And it seems it is MouseDown event that is misbehaving, MouseUp works fine.
Update:
This is a bug with long history and MS has not yet fixed it (even in 4.5), so you have to update the code if you encounter the same symptom - get the touch position from Touch event, not Mouse event. Luckily this bug is not subtle so it only takes a little while to be located and fixed.
Code to reproduce the issue:
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Height="60" Width="80" x:Name="Image" MouseDown="Image_MouseDown"
Source="/WpfApplication1;component/Images/Desert.jpg" />
</Grid>
</Window>
Code behind:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Image_MouseDown(object sender, MouseButtonEventArgs e)
{
Point p = e.GetPosition(Image);
MessageBox.Show(p.X.ToString() + " " + p.Y.ToString());
}
}
}
By default in WPF, if a Touch event is not handled by a control it will be promoted to a Mouse event. Touch events are routed events, so when the Mouse event will be triggered it will go up and down the visual tree (hence your event handler being executed even when you touch outside of the Image).
If the MouseDown event comes from a promoted touch event, you could probably get the correct position using the StylusDevice:
if (e.StylusDevice != null)
point = e.StylusDevice.GetPosition(sender as Image);
Or as an alternative, you could add a handler for the TouchDown event for the controls where you need the position:
<Image TouchDown="UIElement_OnTouchDown"/>
private void UIElement_OnTouchDown(object sender, TouchEventArgs e)
{
var touchPoint = e.GetTouchPoint(sender as Image);
// more processing using touchPoint.Position
}
If you run in .NET 4.5.0, you will not see this issue. It is introduced at 4.5.1. I am trying to see if I can get somebody at MS to pay attention and fix this without you and me hacking up our code.

Specific binding in C#/WPF

That's me again with my bindings :)
Here is the problem, I need to have on my GRID two controls connected with a LINE. So I can move with mouse one of the controls around GRID and LINE, that connect this two controls must replace immediately while moving.
Any ideas? I thought that calculate new X1,Y1,X2,Y2 of the LINE on every 1px move impossible and very speedless... So I think that there is the way to create BINDINGS for LINE's X1,Y1,X2,Y2, such as:
x1={Binding firstCtrl.Position.X+firstCtrl.Width/2}
But such binding is very hard (for me) even in XAML, but I need to create such binding dynamically in C# code.
Need your advice again, how to create such binding in C# or there is another way to realize my idea?
P.S."I don't need whole code for that, just description and, maybe, simple example of code."
Thanks a lot.
You could use a MultiValueConverter to gather the points of interest and return the X or Y point as needed.
Here is a good blog post discussing their use.
Try this:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="template1">
<Ellipse Width="30" Margin="-15 -15" Height="30" Fill="Black"/>
</ControlTemplate>
</ResourceDictionary>
</Window.Resources>
<Canvas Name="myCanvas">
<Thumb Name="myThumb" DragDelta="onDragDelta" Canvas.Left="0" Canvas.Top="30" Template="{StaticResource template1}"/>
<Thumb Name="myThumb2" DragDelta="onDragDelta" Canvas.Left="400" Canvas.Top="30" Template="{StaticResource template1}"/>
<Line X1="{Binding ElementName=myThumb,Path=(Canvas.Left)}" Y1="{Binding ElementName=myThumb,Path=(Canvas.Top)}" X2="{Binding ElementName=myThumb2,Path=(Canvas.Left)}" Y2="{Binding ElementName=myThumb2,Path=(Canvas.Top)}" Stroke="Black" />
</Canvas>
code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
void onDragDelta(object sender, DragDeltaEventArgs e)
{
var i = sender as UIElement;
if (i != null)
{
Canvas.SetLeft(i, Canvas.GetLeft(i) + e.HorizontalChange);
//Canvas.SetTop(myThumb, Canvas.GetTop(myThumb) + e.VerticalChange);
}
}
}
}
EDIT:
Explanation: this has two draggable circles (x-axis only) and a line connecting both. I've created a binding for the X-Num,Y-Num properties and bound them to the Canvas.Top/Left attached properties of the thumb objects (using ElementName Binding). This places both ends of the line in the 0,0 coords of each object. So I used a negative margin to put the circle's center in 0,0.
Hope that helps.

Categories