Click here to Skip to main content
15,867,568 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I use the following solution to minimize my app window:
XAML
<Window x:Name="GanjAsemanMainWindow" x:Class="Ganj_Aseman.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"
        mc:Ignorable="d"
        StateChanged="GanjAsemanMainWindow_StateChanged" AllowsTransparency="True" Background="Transparent" FontSize="13" Height="535" RenderTransformOrigin="0.5,0.5" ResizeMode="CanResizeWithGrip" Title="MainWindow" Width="764" WindowStyle="None">
    <Window.RenderTransform>
        <TransformGroup>
            <RotateTransform/>
            <ScaleTransform/>
        </TransformGroup>
    </Window.RenderTransform>
    <Grid>
        <Rectangle x:Name="TitleRectangle" Fill="#727A7A7A" Stroke="WhiteSmoke" StrokeThickness="0.5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" RadiusX="10" RadiusY="10" RenderTransformOrigin="0.504,-0.3">
            <Rectangle.Effect>
                <BlurEffect Radius="2"/>
            </Rectangle.Effect>
        </Rectangle>
        <Rectangle x:Name="MainRectangle" Fill="#d4fed8" RadiusY="5" RadiusX="5" Stroke="Gray" Margin="7,50,7,7" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
        <Image x:Name="CloseIconImage" PreviewMouseLeftButtonDown="CloseIconImage_PreviewMouseLeftButtonDown" GotFocus="CloseIconImage_GotFocus" Focusable="True" FocusVisualStyle="{x:Null}" Cursor="Hand" HorizontalAlignment="Right" Height="47" VerticalAlignment="Top" Source="{Binding}" Width="52" Margin="0,2,11,0"/>
        <Image x:Name="MinimizeIconImage" GotFocus="MinimizeIconImage_GotFocus" Focusable="True" FocusVisualStyle="{x:Null}" Cursor="Hand" Height="47"  VerticalAlignment="Top" Source="{Binding}" Margin="0,2,67,0" HorizontalAlignment="Right" Width="52">
            <Image.Triggers>
                <EventTrigger RoutedEvent="PreviewMouseLeftButtonDown">
                    <BeginStoryboard>
                        <Storyboard Storyboard.TargetName="GanjAsemanMainWindow" Completed="MinimizeWindow_Completed">
                            <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[0].Angle" Duration="0:0:2" To="360"/>
                            <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[1].ScaleX" Duration="0:0:2" To="0"/>
                            <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[1].ScaleY" Duration="0:0:2" To="0"/>
                            <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2.5" To="0"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Image.Triggers>
        </Image>
    </Grid>
</Window>

C#
private void MinimizeWindow_Completed(object sender, EventArgs e)
{
    WindowState = WindowState.Minimized;
}

Result:
Click on this link to see the result
What I want:

• Restoring the window and its controls to their original dimensions (by clicking on the app icon in the Taskbar)
• Do the opposite of what is shown in the result above if possible
• XAML code should be used as much as possible
I use the following tools:
.NET Framework 4.5
WPF

Thank you for your time.
Best regards,
Reza Jaferi

What I have tried:

C#
private void GanjAsemanMainWindow_StateChanged(object sender, EventArgs e)
{
    switch (WindowState)
    {
        case WindowState.Normal:
            //I tried some codes here.
            break;
    }
}
Posted
Updated 28-Aug-22 15:42pm
v3
Comments
Reza jafery 26-Aug-22 12:36pm    
Is there any suggestion?
[no name] 26-Aug-22 14:36pm    
Pointless screen gymnastics. Develop something that doesn't get annoying after the second time.
Reza jafery 26-Aug-22 15:15pm    
Thank you for your reply, but I'd like my app to be visually distinct.
Reza jafery 26-Aug-22 15:37pm    
"screen gymnastics" It was an interesting sentence. 😆😆😆😆😆 :D:D
Reza jafery 28-Aug-22 21:43pm    
Is it necessary to unsubscribe from "SourceInitialized += New EventHandler(OnSourceInitialized)" to avoid memory leaks?

1 solution

I found the solution by getting the initial value of ScaleX and ScaleY.
This is the perfect solution. By "perfect," I mean that this solution works properly even if the user clicks on the application icon in the taskbar.
IntPtr should be used in this specific case instead of the StateChanged event to handle the Minimize event.
XAML
<Window x:Name="GanjAsemanMainWindow" x:Class="Ganj_Aseman.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"
        mc:Ignorable="d"
        AllowsTransparency="True" Background="Transparent" FontSize="13" Height="535" RenderTransformOrigin="0.5,0.5" ResizeMode="CanResizeWithGrip" Title="MainWindow" Width="764" WindowStyle="None">
    <Window.RenderTransform>
        <TransformGroup>
            <RotateTransform/>
            <ScaleTransform/>
        </TransformGroup>
    </Window.RenderTransform>
    <Window.Resources>
        <Storyboard x:Key="MinimizeMainWindow" Storyboard.TargetName="GanjAsemanMainWindow" Completed="MinimizeMainWindow_Completed">
            <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[0].Angle" Duration="0:0:2" To="360"/>
            <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[1].ScaleX" Duration="0:0:2" To="0"/>
            <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[1].ScaleY" Duration="0:0:2" To="0"/>
            <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2.5" To="0"/>
        </Storyboard>
        <Storyboard x:Key="NormalizeMainWindow" Storyboard.TargetName="GanjAsemanMainWindow" Completed="NormalizeMainWindow_Completed">
            <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[0].Angle" Duration="0:0:2" To="0"/>
            <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[1].ScaleX" Duration="0:0:2" To="1"/>
            <DoubleAnimation Storyboard.TargetProperty="RenderTransform.Children[1].ScaleY" Duration="0:0:2" To="1"/>
            <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2.5" To="100"/>
        </Storyboard>
    </Window.Resources>
    <Grid>
        <Rectangle x:Name="TitleRectangle" Fill="#727A7A7A" Stroke="WhiteSmoke" StrokeThickness="0.5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,0" RadiusX="10" RadiusY="10" RenderTransformOrigin="0.5,0.5">
            <Rectangle.Effect>
                <BlurEffect Radius="2"/>
            </Rectangle.Effect>
        </Rectangle>
        <Rectangle x:Name="MainRectangle" Fill="#d4fed8" RadiusY="5" RadiusX="5" Stroke="Gray" Margin="7,50,7,7" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
        <Image x:Name="CloseIconImage" PreviewMouseLeftButtonDown="CloseIconImage_PreviewMouseLeftButtonDown" Focusable="True" FocusVisualStyle="{x:Null}" Cursor="Hand" HorizontalAlignment="Right" Height="47" VerticalAlignment="Top" Source="Images/CloseIcon.png" Width="52" Margin="0,2,11,0"/>
        <Image x:Name="MinimizeIconImage" Focusable="True" FocusVisualStyle="{x:Null}" Cursor="Hand" Height="47" VerticalAlignment="Top" Source="Images/MinimizeIcon.png" Margin="0,2,67,0" HorizontalAlignment="Right" Width="52">
            <Image.Triggers>
                <EventTrigger RoutedEvent="PreviewMouseLeftButtonDown">
                    <BeginStoryboard Storyboard="{StaticResource MinimizeMainWindow}">
                    </BeginStoryboard>
                </EventTrigger>
            </Image.Triggers>
        </Image>
    </Grid>
</Window>

C#
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media.Animation;

namespace Ganj_Aseman
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //We define this variable to prevent the user from re-minimizing the window via the application icon on the taskbar during window normalization (not when it is normalized)
        bool Normalization = true;
        private void OnSourceInitialized(object sender, EventArgs e)
        {
            HwndSource Source = (HwndSource)PresentationSource.FromVisual(this);
            Source.AddHook(new HwndSourceHook(Minimize));
            Source.AddHook(new HwndSourceHook(Normalize));
        }

        public MainWindow()
        {
            InitializeComponent();
            SourceInitialized += new EventHandler(OnSourceInitialized);
        }

        private IntPtr Minimize(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // 0x0112 == WM_SYSCOMMAND, 'Window' command message.
            // 0xF020 == SC_MINIMIZE, command to minimize the window.
            if (msg == 0x0112 && ((int)wParam & 0xFFF0) == 0xF020)
            {
                handled = true;
                if (WindowState == WindowState.Normal && Normalization == true)
                {
                    (Resources["MinimizeMainWindow"] as Storyboard).Begin();
                }
            }
            return IntPtr.Zero;
        }

        private IntPtr Normalize(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // 0x0112 == WM_SYSCOMMAND, 'Window' command message.
            // 0xF120 == SC_RESTORE, command to normalize the window.
            if (msg == 0x0112 && ((int)wParam & 0xFFF0) == 0xF120 && WindowState == WindowState.Minimized)
            {
                (Resources["NormalizeMainWindow"] as Storyboard).Begin();
            }
            return IntPtr.Zero;
        }

        private void MinimizeMainWindow_Completed(object sender, EventArgs e)
        {
            WindowState = WindowState.Minimized;
            Normalization = false;
        }

        private void NormalizeMainWindow_Completed(object sender, EventArgs e)
        {
            WindowState = WindowState.Normal;
            Normalization = true;
        }

        private void CloseIconImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Close();
        }
    }
}

Tested in:
• .NET Framework 4.5
• WPF

Thank you for your time.
Best regards,
Reza Jaferi
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900