Win32+WPF Resizable, Borderless window that has a system menu - c#

I have a (NoResize Borderless) window in WPF that I am trying to have sizable yet still have the system menu work.
I have manually done NC hittesting to enable resizing and the system menu. However, I can only get one to work at a time. I try to enable both using SetWindowLong(Ptr) but I cannot get any combination to enable the system menu and resizing.
I've tried enabling the WS_SYSMENU style which makes no difference.
PostMessage(callingWindow, WindowMessage.SystemCommand, new IntPtr(trackPMenu), IntPtr.Zero);
only works when the window is not resizable.
Also, setting the window to be an overlapped window (WS_OVERLAPPEDWINDOW) puts a frame around the window.

The MahApps OSS project has the ability to have a no resizable borderless window with a system menu. Have a look at there MetroWindow class.
I'm currently using a resizable borderless window with a system menu:
Code behind:
using MahApps.Metro.Controls;
public partial class MainWindow : MetroWindow
{
public MainWindow()
{
InitializeComponent();
}
}
XAML:
<controls:MetroWindow x:Class="XXXX.Views.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"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:XXXX.ViewModels"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
d:DataContext="{d:DesignInstance vm:MainViewModel}"
WindowStartupLocation="Manual"
SaveWindowPosition="True"
Title="{Binding Path=Title, Mode=OneWay}"
Style="{StaticResource MyCleanWindowStyleKey}">
</controls:MetroWindow>
With the following style:
<Style x:Key="MyCleanWindowStyleKey"
TargetType="{x:Type c:MetroWindow}">
<Setter Property="BorderThickness"
Value="2" />
<Setter Property="BorderBrush"
Value="Blue" />
<Setter Property="Background"
Value="Black" />
<Setter Property="Foreground"
Value="White" />
<Setter Property="TitleForeground"
Value="White" />
<Setter Property="TitlebarHeight"
Value="42" />
<Setter Property="WindowState"
Value="Normal" />
<Setter Property="ResizeMode"
Value="CanResizeWithGrip" />
<Setter Property="AllowsTransparency"
Value="False" />
<Setter Property="TitleCaps"
Value="False" />
<Setter Property="ShowWindowCommandsOnTop"
Value="False" />
<Setter Property="WindowTransitionsEnabled"
Value="False" />
</Style>

Related

How to easily allow users to update Styles used be elements in XAML (UWP)

This is for a Windows 10 UWP. I need to allow users to update values on Styles that are associated with elements used throughout the application (i.e allow users to change the font size of various textblocks, background color stackpanels etc.) .
I currently have all my Styles in a separately file.
My App.xaml is as below:
<Application
x:Class="MyTestApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Styles/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
My Styles.xaml (partial) is as below:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converters="using:MyTestApp.Views"
xmlns:x1="using:System">
<Style x:Key="HeaderTextBlocks" TargetType="TextBlock" BasedOn="{StaticResource TitleTextBlockStyle}">
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="10,4,0,0"/>
</Style>
<Style x:Key="RegularTextBlocks" TargetType="TextBlock" BasedOn="{StaticResource TitleTextBlockStyle}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Margin" Value="0,0,0,0"/>
</Style>
</ResourceDictionary>
I refer to these styles on controls throughout the application using like this:
<TextBlock Style="{StaticResource HeaderTextBlocks}" />
I have created a Settings page (settings.xaml) which has textboxes for the users to update various style settings.
But I am not sure how I could bind these to the settings on the various styles on the styles.xaml file so that the styles are updated and the controls referring to the styles are updated when the user changes the value.
<TextBox Header="Font Size of Header TextBlocks" Text="{x:Bind HeaderTextBlocks.FontSize ???, Mode=TwoWay}" />
<TextBox Header="Font Size of Regular TextBlocks" Text="{x:Bind RegularTextBlocks.FontSize???, Mode=TwoWay}" />
Could someone please point me in the right direction? I am trying to do this with minimal (or no code behind) as possible.
Unfortunately this kind of user-defined styling is not easily available in UWP. You can however implement a kind of styling solution using data binding.
First step is to create a class like CustomUISettings which implements INotifyPropertyChanged and has properties like HeaderFontSize, etc.
Now on app start create an instance of this class and add it as app resource:
Application.Current.Resources["CustomUISettings"] = new CustomUISettings();
Now you can bind to the properties in this class anywhere in your code:
<TextBox FontSize="{Binding HeaderFontSize, Source={StaticResource CustomUISettings}}" />
You must use the classic {Binding} markup extension, because {x:Bind} does not support Source setting.
To modify the UI settings you can just retrieve the instance anywhere and set the properties as you see fit:
var customUISettings = (CustomUISettings)Application.Current.Resources["CustomUISettings"];
customUISettings.HeaderFontSize = 50;
You must make sure that all properties in CustomUISettings class fire the PropertyChanged event. You can see how to implement INotifyPropertyChanged interface for example here.

xaml resource errors when view open in editor

I have a solution with multiple projects that has been building with no errors. Recently, I discovered that if I have a XAMview open in the editor, clean the solution then build it, I get a bunch of "Cannot find resource named 'Resource'. Resource names are case sensitive." errors. The 'Resource' that can't be found is referenced in a different view, not the view that I'm currently in. Any Static/Dynamic resources in the current view don't get the error. If I close the view and rebuild, the errors don't appear.
I've gone through and made sure all my namespace references are correct, the resource dictionary is in my app.xaml, all the keys are defined first in my styles, etc.
Any idea what could be causing this or how to solve it?
view with error:
<StackPanel>
<StackPanel Orientation="Horizontal">
<amp:AmpView DataContext="{Binding Path=Amp}" />
<autoCal:AutoCalView DataContext="{Binding Path=AutoCal}"
Margin="5 0 0 0" />
</StackPanel>
referenced view:
<Border Style="{StaticResource ContentBorderStyle}"
HorizontalAlignment="Left">
Resource:
<!-- Content container styles -->
<Style x:Key="ContentBorderStyle" TargetType="{x:Type Border}">
<Setter Property="Background" Value="{StaticResource ContentBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource ContentBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="3" />
<Setter Property="Margin" Value="0 0 0 5" />
<Setter Property="Padding" Value="3" />
</Style>
App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Src.Pl;component/Resources/Styles/StyleResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

How can I change the default style of WPF controls for a single assembly?

I've written a WPF plugin for some off-the-shelf product, and in this plugin I've used a theme/style to change the minimal width of all buttons like so:
<Style TargetType="Button">
<Setter Property="MinWidth" Value="80" />
</Style>
In the newest version of said off-the-shelf product they migrated from winforms to WPF themselves. Now when my plugin is loaded the style that previously just affected my plugged-in forms now affects all buttons in the application. This renders most UI's unusable.
I know I can use dictionary key based resources to make this style specific to my buttons, but this means I have to change each and every button in my plugin by hand, as well as not forget to set the style of each button in the future (and other elements this problem applies to). There are other options to make the style specific to a set of buttons, as seen in Is it possible to set a style in XAML that selectively affects controls? But I'm looking for a way to let my style affect only those of my plugin (so a bit more coarse than talked about in the referenced question). This plugin consists of multiple windows/views (tied together with Caliburn.Micro).
Is there a way to easily scope a style to for instance an assembly or namespace? I'd really like to define my resources just once. Currently it's defined at the Application.Resources level, if there's one more appropriate I'd like to hear that too.
With a ResourceDictionary, we can set default style wich will be applied without define style in Xaml.
DictionayNew.xaml :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Media="clr-namespace:System.Windows.Media;assembly=PresentationCore"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<!-- default button -->
<Style TargetType="{x:Type Button}">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="MinWidth" Value="80" />
</Style>
<!-- new button style -->
<Style x:Key="ActionButton" TargetType="{x:Type Button}">
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="MinWidth" Value="75" />
<Setter Property="Height" Value="23" />
</Style>
<!-- new button style based on previous style -->
<Style x:Key="BigActionButton"
BasedOn="{StaticResource ActionButton}"
TargetType="{x:Type Button}">
<Setter Property="MinWidth" Value="150" />
<Setter Property="Height" Value="30" />
</Style>
</ResourceDictionary>
In your Xaml, use the dictionary :
<Window x:Class="CheckDoublonImageBing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="DictionaryNew.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
</Grid>
</Window>
Then, use Button as usual or with new style
<Button Content="Refresh" />
<Button Content="Delete selected" Style="{DynamicResource ActionButton}" />
With no style defined, button will have default style defined in the dictionary.
EDIT :
You can set merged dictionary by code like this :
ResourceDictionary myResourceDictionary = new ResourceDictionary();
myResourceDictionary.Source = new Uri("DictionayNew.xaml", UriKind.Relative);
Application.Current.Resources.MergedDictionaries.Add(myResourceDictionary);
You need to specify a Key for your Style and apply the Style to all your Buttons.
<Style TargetType="Button" x:Key="MyButtonStyle">
<Setter Property="MinWidth" Value="80" />
</Style>
<Button Style="{StaticResource MyButtonStyle}"/>
Without a Key the Style is used for all Buttons in the application (as you have already noticed).

Is there any settings in wpf to align buttons in fixed distance

App contain more than 30 buttons but there alignments are incorrect
my question is:
Is there any property for arranging all 30 button in fixed length and height?
If you want share same setting between all 30 buttons you should use Styles:
<Style TargetType="Button">
<Setter Property="Width" Value="20" />
</Style>
After you'll have all buttons with width 20. This is happening due to a concept called implicit styles. Any time you are specifying style without Key it will automatically apply it to all TargetTypes without explicitly defined style.
Have you tried using a Style to declare your Button dimensions? Try adding this into your Resources section:
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Height" Value="24" />
<Setter Property="Width" Value="150" />
</Style>
</Window.Resources>
This will affect all Buttons within scope of the Style, but you could change it to this...:
<Style x:Key="SizedButton" TargetType="{x:Type Button}">
<Setter Property="Height" Value="24" />
<Setter Property="Width" Value="150" />
</Style>
... and then explicitly assign the Style to each Button:
<Button Content="Something" Style="{StaticResource SizedButton}" />

Copy control button in run time

Hi all. I create an application with some (WPF) forms. I have a button on one form. I want to, at run time, copy this button onto a second form without having to create it again.
For example: I have 'X' button on form 1. At run time, I create a copy of this button on form 2 with all of the same property values as the original button on form 1.
The button:
<Button Content="Open Window" Click="ButtonClicked" Height="25"
HorizontalAlignment="Left" Margin="379,264,0,0" Name="button1"
VerticalAlignment="Top" Width="100" />
Any chance I can avoid having to reproduce this code?
You can define your own style for button in App.xaml:
<Application x:Class="WpfButton.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style x:Key="myBtnStyle" TargetType="Button" >
<Setter Property="Content" Value="Open Window" />
<Setter Property="Height" Value="25" />
<Setter Property="Width" Value="100" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Margin" Value="379,264,0,0" />
<Setter Property="VerticalAlignment" Value="Top" />
<EventSetter Event="Click" Handler="myBtn_Click" />
</Style>
</Application.Resources>
</Application>
Code behind:
public partial class App : Application
{
public void myBtn_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
// ...
}
}
And when you want to assign created earlier style to the button, you should use StaticResource and name of your style:
<Button Style="{StaticResource myBtnStyle}" />
If you want to create an exact clone, then you will need to serialize the component and inject an ExpressionConverter into the serialization process. This will create a 'deep' clone. See here.

Categories