I'm trying to create an application that looks like Visual Studio 2012. I have used WindowChrome to remove the window borders, and changed the border color in my xaml.
What I don't know how to do is paint the shadow of the window, here you can see an screenshot of what I'm saying:
As you can see there is a shadow and its color is also the border color
Do you know how to implement it using WPF?
Update (October '17)
It has been four years now and I was interested in tackling this again and thus I have been messing around with MahApps.Metro once again and derived my own library based on it. My ModernChrome library provides a custom window that looks like Visual Studio 2017:
Since you are most likely only interested in the part about the glowing border, you should either use MahApps.Metro itself or see how I created a class GlowWindowBehavior which attaches glow borders to my custom ModernWindow class. It is hevily dependant on some internals of MahApps.Metro and the two dependency properties GlowBrush and NonActiveGlowBrush.
If you only want to include the glowing borders to your custom applications just reference MahApps.Metro and copy over my GlowWindowBehavior.cs and create a custom window class and adapt the references accordingly. This is a matter of 15 minutes at most.
This question and my answer have been accessed very frequently so I hope you will find my newest proper solution useful :)
Original post (February '13)
I have been working on such a library to copy the Visual Studio 2012 user interface. A custom chrome isn't that difficult but what you should take care of is this glowing border which is hard to implement. You could just say set the background color of your window to transparent and set the padding of the main grid to about 30px. A border around the grid could be colored and associated with a colored shadow effect but this approach forces you to set AllowsTransparency to true which drastically reduces visual performance of your application and this is something you definitely do not want to do!
My current approach to create such a window which just has a colored shadow effect on a border and is transparent but has no content at all. Evertime the position of my main window changes I just update the position of the window which holds the border. So in the end I am handling two windows with messages to fake that the border would be part of the main window. This was necessary because the DWM library doesn't provide a way to have a colored drop shadow effect for windows and I think Visual Studio 2012 does that similiar like I tried.
And to extend this post with more information: Office 2013 does that differently. The border around a window is just 1px thick and colored, yet the shadow is drawn by DWM with a code like this one here. If you can live without having blue/purple/green borders and just usual ones this is the approach I would choose! Just don't set AllowsTransparency to true, otherwise you have lost.
And here is a screenshot of my window with strange color to highlight what it looks like:
Here are some hints on how to start
Please keep in mind that my code is quite long, such that I will only be able to show you the basic things to do and you should be able to at least start somehow. First of all I'm going to assume that we have designed our main window somehow (either manually or with the MahApps.Metro package I tried out yesterday - with some modifications to the sourcecode this is really good(1)) and we are currently working to implement the glowing shadow border, which I will call GlowWindow from now on. The easiest approach is to create a window with the following XAML code
<Window x:Class="MetroUI.Views.GlowWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="GlowWindow"
Title="" Width="300" Height="100" WindowStartupLocation="Manual"
AllowsTransparency="True" Background="Transparent" WindowStyle="None"
ShowInTaskbar="False" Foreground="#007acc" MaxWidth="5000" MaxHeight="5000">
<Border x:Name="OuterGlow" Margin="10" Background="Transparent"
BorderBrush="{Binding Foreground, ElementName=GlowWindow}"
BorderThickness="5">
<Border.Effect>
<BlurEffect KernelType="Gaussian" Radius="15" RenderingBias="Quality" />
</Border.Effect>
</Border>
</Window>
The resulting window should look like the following picture.
The next steps are quite difficult - when our main window spawns we want to make the GlowWindow visible but behind the main window and we have to update the position of the GlowWindow when the main window is being moved or resized. What I suggest to prevent visual glitches that can AND will occur is to hide the GlowWindow during every change of either location or size of the window. Once finished with such action just show it again.
I have some method which is called in different situations (it might be a lot but just to get sure)
private void UpdateGlowWindow(bool isActivated = false) {
if(this.DisableComposite || this.IsMaximized) {
this.glowWindow.Visibility = System.Windows.Visibility.Collapsed;
return;
}
try {
this.glowWindow.Left = this.Left - 10;
this.glowWindow.Top = this.Top - 10;
this.glowWindow.Width = this.Width + 20;
this.glowWindow.Height = this.Height + 20;
this.glowWindow.Visibility = System.Windows.Visibility.Visible;
if(!isActivated)
this.glowWindow.Activate();
} catch(Exception) {
}
}
This method is mainly called in my custom WndProc I have attached to the main window:
/// <summary>
/// An application-defined function that processes messages sent to a window. The WNDPROC type
/// defines a pointer to this callback function.
/// </summary>
/// <param name="hwnd">A handle to the window.</param>
/// <param name="uMsg">The message.</param>
/// <param name="wParam">Additional message information. The contents of this parameter depend on
/// the value of the uMsg parameter.</param>
/// <param name="lParam">Additional message information. The contents of this parameter depend on
/// the value of the uMsg parameter.</param>
/// <param name="handled">Reference to boolean value which indicates whether a message was handled.
/// </param>
/// <returns>The return value is the result of the message processing and depends on the message sent.
/// </returns>
private IntPtr WindowProc(IntPtr hwnd, int uMsg, IntPtr wParam, IntPtr lParam, ref bool handled) {
// BEGIN UNMANAGED WIN32
switch((WinRT.Message)uMsg) {
case WinRT.Message.WM_SIZE:
switch((WinRT.Size)wParam) {
case WinRT.Size.SIZE_MAXIMIZED:
this.Left = this.Top = 0;
if(!this.IsMaximized)
this.IsMaximized = true;
this.UpdateChrome();
break;
case WinRT.Size.SIZE_RESTORED:
if(this.IsMaximized)
this.IsMaximized = false;
this.UpdateChrome();
break;
}
break;
case WinRT.Message.WM_WINDOWPOSCHANGING:
WinRT.WINDOWPOS windowPosition = (WinRT.WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WinRT.WINDOWPOS));
Window handledWindow = (Window)HwndSource.FromHwnd(hwnd).RootVisual;
if(handledWindow == null)
return IntPtr.Zero;
bool hasChangedPosition = false;
if(this.IsMaximized == true && (this.Left != 0 || this.Top != 0)) {
windowPosition.x = windowPosition.y = 0;
windowPosition.cx = (int)SystemParameters.WorkArea.Width;
windowPosition.cy = (int)SystemParameters.WorkArea.Height;
hasChangedPosition = true;
this.UpdateChrome();
this.UpdateGlowWindow();
}
if(!hasChangedPosition)
return IntPtr.Zero;
Marshal.StructureToPtr(windowPosition, lParam, true);
handled = true;
break;
}
return IntPtr.Zero;
// END UNMANAGED WIN32
}
However there is still an issue left - once you resize your main window the GlowWindow will not be able to cover the whole window with its size. That is if you resize your main window to about MaxWidth of your screen, then the widt of the GlowWindow would be the same value + 20 as I have added a margin of 10 to it. Therefore the right edge would be interrupted right before the right edge of the main window which looks ugly. To prevent this I used a hook to make the GlowWindow a toolwindow:
this.Loaded += delegate {
WindowInteropHelper wndHelper = new WindowInteropHelper(this);
int exStyle = (int)WinRT.GetWindowLong(wndHelper.Handle, (int)WinRT.GetWindowLongFields.GWL_EXSTYLE);
exStyle |= (int)WinRT.ExtendedWindowStyles.WS_EX_TOOLWINDOW;
WinRT.SetWindowLong(wndHelper.Handle, (int)WinRT.GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);
};
And still we will have some issues - when you go with the mouse over the GlowWindow and left click it will be activated and get the focus which means it will overlap the main window which looks like this:
To prevent that just catch the Activated event of the border and bring the main window to the foreground.
How should YOU do this?
I suggest NOT to try this out - it took me about a month to achieve what I wanted and still it has some issues, such that I would go for an approach like Office 2013 does - colored border and usual shadow with the DWM API calls - nothing else and still it looks good.
(1) I have just edited some files to enable the border around the window which is disabled on Window 8 for me. Furthermore I have manipulated the Padding of the title bar such that it doesn't look that sqeezed inplace and lastly I have change the All-Caps property to mimic Visual Studio's way of rendering the title. So far the MahApps.Metro is a better way of drawing the main window as it even supports AeroSnap I couldn't implement with usual P/Invoke calls.
You can use this simple xaml code
<Window x:Class="VS2012.MainWindow"
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
Title="MainWindow"
Height="100" Width="200"
AllowsTransparency="True" WindowStyle="None" Background="Transparent">
<Border BorderBrush="DarkOrange" BorderThickness="1" Background="White" Margin="5">
<Border.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="5" Color="DarkOrange"/>
</Border.Effect>
</Border>
</Window>
This is called "Metro style" (Windows 8 style). I think that this Code Project article is interesting for you and it will help you.
You can try Elysium, which licensed under MIT license and included ApplicationBar and ToastNotification classes, or MetroToolKit, from codeplext, too.
This is a great tutorial about Elysium, I think that it helps you.
For shadow, just add a BitmapEffect to a Border from your Grid in XAML:
<Grid>
<Border BorderBrush="#FF006900" BorderThickness="3" Height="157" HorizontalAlignment="Left" Margin="12,12,0,0" Name="border1" VerticalAlignment="Top" Width="479" Background="#FFCEFFE1" CornerRadius="20, 20, 20, 20">
<Border.BitmapEffect>
<DropShadowBitmapEffect Color="Black" Direction="320" ShadowDepth="10" Opacity="0.5" Softness="5" />
</Border.BitmapEffect>
<TextBlock Height="179" Name="textBlock1" Text="Hello, this is a beautiful DropShadow WPF Window Example." FontSize="40" TextWrapping="Wrap" TextAlignment="Center" Foreground="#FF245829" />
</Border>
</Grid>
<Window x:Class="MyProject.MiniWindow"
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:MyProject"
mc:Ignorable="d"
WindowStyle="None"
Title="MiniWindow" Background="Transparent"
Height="200" Width="200"
>
<WindowChrome.WindowChrome>
<WindowChrome
CaptionHeight="0"
ResizeBorderThickness="4" />
</WindowChrome.WindowChrome>
<Grid Margin="0">
<Border BorderThickness="3">
<Border BorderThickness="1" Margin="0" BorderBrush="#ff007acc">
<Border.Effect>
<DropShadowEffect Color="#ff007acc" Direction="132" ShadowDepth="0" BlurRadius="8" />
</Border.Effect>
<Grid Background="#ff2d2d30">
</Grid>
</Border>
</Border>
</Grid>
I'm trying to obtain the same effect, my app is using .NET 4 and thus I cannot directly use WindowChrome (so, I'm using the Microsoft Windows Shell library to get the same).
In this thread it is correctly noted that using spy++ it can be seen that Visual Studio has four windows called VisualStudioGlowWindow to implement the glowing effect.
It has been already described in many places how the AllowsTransparency property to true can reduce the performances.
So, I tried to go the VS way and the result is not bad (at least, for me); no need to use blur or similar effect on the main window, I just had to fight a bit with some window states (focus/visible/hidden).
I've put all the needed stuff on github - hope this can help.
Related
In WinForms, Form had a ClientSize property (inherited from Control), which returns the size of its client area, i.e., the area inside the title bar and window borders.
I'm not seeing anything similar in WPF: there's no ClientSize, ClientWidth, ClientHeight, GetClientSize(), or anything else that I can think to guess the name of.
How do I go about getting the client size of a WPF Window?
One way you could do it is to take the top most child element, cast this.Content to its type, and call .RenderSize on it, which will give you its size.
<Window x:Class="XML_Reader.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="400" Width="600" WindowStyle="SingleBorderWindow">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
</Grid>
</Window>
((Grid)this.Content).RenderSize.Height
((Grid)this.Content).RenderSize.Width
edit:
as Trent said, ActualWidth and ActualHeight are also viable solutions. Basically easier methods of getting what I put above.
var h = ((Panel)Application.Current.MainWindow.Content).ActualHeight;
var w = ((Panel)Application.Current.MainWindow.Content).ActualWidth;
One way to do it is with the code below. XAML:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
<Canvas>
</Canvas>
</Window>
C#:
using System.Windows;
using System.IO;
using System.Xml;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
double dWidth = -1;
double dHeight = -1;
FrameworkElement pnlClient = this.Content as FrameworkElement;
if (pnlClient != null)
{
dWidth = pnlClient.ActualWidth;
dHeight = pnlClient.ActualHeight;
}
}
}
}
I used a Grid with VerticalAlignment=Top. As a result the Grid unfortunately didn't fill the parent Window anymore (which is its default behaviour, but the VerticalAligment property spoils it).
I solved it by putting an empty Border around the Grid. This border fills the complete content of the window, it has the same dimensions as the default border that a wpf window has anyways.
To get the Grid to fill the main window, I used the binding:
<Border BorderThickness="0" x:Name=Main>
<Grid VerticalAlignment="Top" Height="{Binding ElementName=Main, Path=ActualHeight}"> ...
</Grid>
</Border>
All the suggested solutions are based on the idea to use the size of Windows.Content to know what is the actual size available within the window, like this:
var h = ((Panel)Application.Current.MainWindow.Content).ActualHeight;
This of course only works if Window.Content is not null. Which is a problem if you want to set Window.Content from your code and you already then need to know exactly how much space is available.
The other problem is that the above code only provides the available space once a first layout cycle has completed (i.e. in the Window_Loaded event). But what do you do if you need to know the available space during the first layout cycle, for example because you draw to the window during Windows.OnRender() ?
The first control in the visual tree of any Window is always a Border, even if Window.Content is null. Interestingly, Border.RenderSize has already a value, even when RenderSize.ActualSize might still be zero. I guess the reason is that the size of the Border does not depend on Window.Content, but only on the size of the window (unless, of course, if Window.SizeToContent is used).
I recommend to place your code into the Window.SizeChanged event. Because each time the Window size changes, your content needs to change too. You cannot use the size provided in the event parameters, which gives you the size of the complete window, but you can get the the available size within the window like this:
var h = ((Border)GetVisualChild(0)).RenderSize.Height;
You can use that line of code also if you override Windows.OnRender().
A little bit of background first, I have an application that uses the Microsoft AddIn Framework (MAF) that gets a WPF UI from the plugins (You can follow this Microsoft example to create one). This is up and working fine until the plugin content is large enough that the main form needs to scroll. When this happens, it scrolls outside of the bounds that it should.
In the image, you'll notice that the Plugin Label Top goes over Main Label Top when you scroll down some and at the bottom you'll only see Plugin Label Bottom. My code for the main form is the following:
<Window x:Class="WpfAddinTest.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:WpfAddinTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Background="DarkGray">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="Main Label Top"/>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ContentControl Name="PluginHolder"/>
</ScrollViewer>
<Label Grid.Row="2" Content="Main Label Bottom"/>
</Grid>
</Window>
ContentControl is what houses the plugin UI, I don't understand why the plugin UI is going over it's parent controls. I've tried housing it in different types of controls, such as a DockPanel and Grid, everything acts the same way.
Is there a special way to get this to function correctly?
If more code is needed, I'm happy to post it, https://github.com/middas/WpfAddInTest is my complete sample project that demonstrates this.
EDIT: Loading up the form in WPF Inspector, all I can see is an AddInHost control, it doesn't show any of the individual controls inside the ContentControl. Does this have something to do with it?
EDIT 2: In trying anything I can think of, I was thinking that maybe it wasn't getting the right height when it placed the control in, so I had the plugin return the desired height and set the Height of the ContentPlaceholder manually based on what was returned; no luck. Here is what I tried:
I updated the AddIn contracts from GetInt() to GetHeight() and on the Plugin I have this method now:
public double GetHeight()
{
_Control.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
return _Control.DesiredSize.Height;
}
Then on the hosting form, I have this now:
public MainWindow()
{
_PluginPath = System.IO.Path.Combine(Environment.CurrentDirectory, "Pipeline");
_AddInPath = System.IO.Path.Combine(_PluginPath, "AddIns");
InitializeComponent();
var warnings = new List<string>(AddInStore.Update(_PluginPath));
_PluginToken = AddInStore.FindAddIns(typeof(IPlugin), _PluginPath, _AddInPath).FirstOrDefault();
_Plugin = _PluginToken.Activate<IPlugin>(AddInSecurityLevel.FullTrust);
var control = _Plugin.GetControl();
PluginHolder.Height = _Plugin.GetHeight();
PluginHolder.Content = control;
}
EDIT 3: Attempting to force the ZIndex doesn't seem to affect it either.
Panel.SetZIndex(control, -1);
I believe I've finally figured out the issue. I believe the problem is because the plugin UI is outside of the AppDomain, the ScrollViewer doesn't know how to clip the content properly. What I finally did that worked was create a callback to the main UI that the plugin can use to be given a height that it needs to fit in. If the plugin requires scrolling, the plugin can then handle it with it's own ScrollViewer.
Here is the updated Contract:
[AddInContract]
public interface IPluginContract : IContract
{
INativeHandleContract GetControl();
double GetHeight();
void SetHostCallback(IHostCallbackContract callback);
}
IHostCallbackContract:
public interface IHostCallbackContract : IContract
{
double GetHeight();
}
Now before the plugin returns the Control it can set the Height given by the main form:
public FrameworkElement GetControl()
{
if (_Callback != null)
{
_Control.SetHeight(_Callback.GetHeight());
}
return _Control;
}
I have updated my Git repo (https://github.com/middas/WpfAddInTest) with the entire working solution. The only issue with it now is that the scrolling isn't double buffered so it flickers. I'll have to live with that though since it doesn't appear there is a way to fix though due to WPF rendering via DirectX.
I have a window.xaml which has components with different kind of styling( border color red, opacity changed and so on). In one moment I want to create a screenshot and save to folder. But before that the window background should be transparent and someCanvas should be hidden.
How do I know when the styling method finished so I can take a screenshot?
public void SomeMethod()
{
ChangeWindowControlStyles();
//TODO: waint till 'ChangeWindowControlStyles' finished
TageScreenshotAndSave();
}
public void ChangeWindowControlStyles()
{
this.Background.Opacity = 0;
this.someCanvas.Visibility = Visibility.Collapsed;
//Some other stuff related to window content styling
}
public void TakeScreenshotAndSave()
{
//No multithreading happening here
//Just taking screenshot and saving to folder
}
EDIT
The window itself is transparent WindowStyle="None", that means it has no borders. In the start the window's Background.Opacity is set to 0.1 and all controls are visible (there are other controls than someCanvas that should always be visible).
Before screenshot is taken someCanvas is hidden and the Background.Opacity is set to 0.
Window.xaml
<Window
WindowStartupLocation="CenterScreen"
ResizeMode="NoResize"
WindowState="Maximized"
WindowStyle="None"
AllowsTransparency="True" >
<Window.Background>
<SolidColorBrush Opacity="0.1" Color="White"/>
</Window.Background>
<Grid Name="mainGrid" Background="Transparent" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0">
<!--Main canvas, function holder-->
<Canvas Name="canvasAlwaysVisible" Margin="0" Panel.ZIndex="5">
<!-- Controls that are always visible -->
</Canvas>
<Canvas x:Name="someCanvas" Margin="0" Background="Transparent" Visibility="Visibility">
<!-- Controls with styling -->
</Canvas>
</Grid>
</Window>
EDIT 2
Another thing to mention is that inside TakeScreenshotAndSave there is also System.IO operations like - get all folders in directory, creation new directory and so on. Maybe .NET sees that and it is ran asynchronously.
Looks like I found the solution. I don't know why it works, will need to investigate more. That TakeScreenshotAndSave method that I mentioned in code sample was somehow running on different thread. When wrap that method inside Application.Current.Dispatcher it worked!
public void SomeMethod()
{
ChangeWindowControlStyles();
var m_dispatcher = Application.Current.Dispatcher;
m_dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.ApplicationIdle,
new System.Threading.ThreadStart(delegate
{
TakeScreenshotAndSave(); //Now running on UI thread
}));
}
I'm in need of making a rectangle clickable, at which it will run a function that animates it and does some stuff. I've tried to browse Microsoft's API, but I don't find anything and I'm going crazy because of this. This will be the last time I touch XAML, but I really need to know how to get this to work.
<Grid Background=Transparent>
<Grid same same>
<Rectangle MouseLeftButtonDown="moveClick" x:Name="red"
Fill="Red" Height="125" Width="125" Stroke="Pink"
StrokeThickness="10" Margin="106,196,225,348"
/>
</Grid>
</Grid>
This is one of my rectangles and I have a function called moveClick in the .xaml.cs file that should be called. In that function there is some code firing up an animation that will target this rectangles. Since I have a lot of rectangles I want to animate I am changing the target depending on which one is pressed. Problem is, the MouseEvent isn't happening. I have googled for hours but Microsoft's help is useless. I don't know what to do.
I can't really post more code than this because then I'd have to rewrite it all over due to my PC I'm programming on has no internet connection. THis is my laptop and I'm going through my phone because my normal internet is down. My desktop has no wifi.
SO, can anybody who has had experience with Windows apps tell me what the reason could be? Is it because I'm in a grid? I saw somewhere that it has to have a transparent background. It is. I'm so clueless because there's nothing to go on because wherever I look, I find something irrelevant or dead ends.
EDIT: Just to clarify, the animation works. I temporarily set it to run by pressing a button used for something else. And it works. It just doesn't work when touching the Rectangles.
EDIT TWO: I'm just using the template, and just added stuff under the ContentPanel as they call it.
An alternative/lazy approach is this:
<Button Click="moveClick" BorderThickness="0" Background="Transparent">
<Rectangle x:Name="red"
Fill="Red" Height="125" Width="125" Stroke="Pink"
StrokeThickness="10" Margin="94,184,213,336"
/>
<Button>
In the click handler you can get the inner rectangle with the recursive function grabbed from this question: How to get children of a WPF container by type?
public static T GetChildOfType<T>(this DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) return null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
var result = (child as T) ?? GetChildOfType<T>(child);
if (result != null) return result;
}
return null;
}
The rectangle it self works fine here. MouseLeftButtonDown get invoked. It is more likely that the way you place it that matter. Can't guess without looking more XAML code.
Wild guess for workarounds, try with Tap event too and explicitly set IsHitTestVisible="True" :
......
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<Rectangle MouseLeftButtonDown="moveClick" x:Name="red"
Fill="Red" Height="125" Width="125" Stroke="Pink"
StrokeThickness="10" Margin="106,196,225,348"
Tap="red_Tap" IsHitTestVisible="True"
/>
</StackPanel>
</Grid>
......
Both event get invoked when I tap the rectangle with this setting. And when IsHitTestVisible set to false, both event doesn't get invoked, just as I expect.
My textbox is the only control on a window, which is a part of a bigger application. The textbox contains a certain amount of text, large enough to show vertical scrollbar. The scrollbar appears, but without a thumb:
I can still scroll the contents, either with mouse wheel or by clicking the arrow-buttons repeatedly.
When I create a new project with the same window and textbox the scrollbar works as it should. The same happens with a WrapPanel. Do you have ideas what could be spoiling my existing project and causing this issue? In generic.xaml I found some styles overriding the defaults for scrollbar and scrollviewer, but even totally clearing generic.xaml didn't help.
Thanks in advance!
EDIT: right, the code. It's XAML only (no c# backing code).
<Window x:Class="TextBoxTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" MaxHeight="200" MaxWidth="200">
<TextBox x:Name="textbox" MaxLines="2" MaxHeight="50" VerticalScrollBarVisibility="Auto" TextWrapping="WrapWithOverflow">
Useless text..... asdasdasda ssssssssssssss sssssss ssssaokdoka sdojwoandowm nxaofwha398ua ozmca3u0a3j3 a80a9fu 03 u0sf u0s9jf4s 0cuj wuf0j w40 fcjw cujwfj9 c9 u49 wsuc j9w3
3089w 9f8u4wfv 0sf ufw0u w0fuw0 fwu f0uw 09djcazp zopf h43 wofh FYHFWFH WOWY HWO H wohg fujg 4g fugj 4 g0 4
4w fw4 f3f g555u45y 55 some more some moresome more some moresome more some moresome more some moresome more some more.
</TextBox>
</Window>
The answer is astonishing!
Just after I'd started to suspect it might be a WPF bug, I found this forum thread.
Guy who asked the question says: "My application uses a directx renderer from a DLL that's written in C++". Mine does almost the same with the difference that my renderer is written in C# (MDX) and uses D3DImage interop.
Following steps mentioned in the thread above, I moved DirectX initialization from OnInitialize() to Loaded event callback of the main window and now scrollbars regained their expected appearance. It seems that GUI must be displayed first, before the renderer is initialized.
So I guess it's reasonable to talk about a bug in this case.
It seems like a style problem. Remove explicit style setter from the TextBox (check both XAML and code behind). If TextBox has no explicit style, search for implicit styles (defined via TargetType="TextBox" or TargetType="{x:Type TextBox}" and/or x:Key="{x:Type TextBox"}).
Try snooping your application and check ScrollViewer's visual tree. It may give you some insights where to look.
Hope this helps.
At a guess: your TextBox is inside a StackPanel. If you want more than a guess, you'll need to provide code.
You can solve the problem adding CreateFlags.FpuPreserve during the creation of your D3D Device
Example:
this.device = new Device(0, DeviceType.Hardware, this.handle,
CreateFlags.HardwareVertexProcessing |
CreateFlags.PureDevice |
CreateFlags.FpuPreserve, this.pparams);