Drop Shadow On A Borderless Form (Powershell GUI)

521 views Asked by At

How can draw a shadow on a borderless form, when $Form.FormBorderStyle = 'None'? I found several solutions, but they are for C#. I think there is a similar option for Powershell, but I still can not find it. Thanks for answers.

2

There are 2 answers

0
Кирилл Зацепин On BEST ANSWER

Based on new knowledge, I myself write the answer to my question.

$Shadow = @'

using System;
using System.Windows;
using System.Windows.Forms;

namespace Program
{
    public partial class Shadow: Form
    {
        protected override CreateParams CreateParams
        {
            get
            {
                var сp = base.CreateParams;
                сp.ClassStyle |= 0x00020000;
                return сp;
            }
        }    
    }
}
'@

Add-Type -TypeDefinition $Shadow -Language CSharp -ReferencedAssemblies System, System.Windows, System.Windows.Forms

# Next, instead of your object $Form = New-Object System.Windows.Forms.Form, you need to write this:
$Form = New-Object Program.Shadow

I never found a solution on a clean PowerShell.

1
codewario On

PowerShell is .NET, as is C#. Most of the same .NET libraries will work in PowerShell as they would in C#, with some quirky edge cases with due to how the script execution differs from a compiled .NET program. If you find examples from C#, you can usually create the same objects and call the same methods you see in the C# examples. This is the preferred method in most cases, to translate the C# calls into PowerShell syntax.

However, PowerShell goes a step further than this and also allows you to compile and execute ad-hoc C# code. For example:

$assemblies=(
    "System"
)

$source=@"
using System;
namespace Helloworld
{
    public static class Hello{
        public static void Main(){
            Console.WriteLine("Hello, world!");
        }
    }
}
"@

Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $source -Language CSharp
[HelloWorld.Hello]::Main()

What the code above does is compile a short hello-world style class and makes its members available to the PowerShell session once Add-Type completes. While this technique generally should be avoided in favor of calling the .NET members directly from PowerShell, there are some cases (such as in the case of using P/Invoke to access the Win32 API) where this becomes useful, and is your only real option.

There is also a third option as well. Instead of ad-hoc compiling C# code like above, you can also build a proper .NET DLL as well, and use Add-Type to load it in. This is much safer, though less convenient, than compiling C# on every execution:

# Assume we have Library.dll already built
# and it consists of the same code as the `$source` in the block above
Add-Type -Path C:\path\to\Library.dll
[HelloWorld.Hello]::Main()