Convert to a flat transparent form

I’m trying to flatten the transparent form of the class.
But I can’t figure out what argument “control” is passing, and the editor is giving me an error about “control”

@michaelvollrath Perhaps Sir There is something you should know, asking for your help

import Rhino
import Eto
import Eto.Forms as ef
import Eto.Drawing as ed
Eto_w = 300
Eto_h = 300
class SampleTransparentEtoForm(Eto.Forms.Form):
    def __init__(self):
        super().__init__()
        self.WindowStyle = Eto.Forms.WindowStyle.NONE
        self.Styles.Add[Eto.Forms.Panel]("transparent", self.TransparentFormStyler)
        self.Style = "transparent"
        self.AutoSize = False
        self.Resizable = True
        self.TopMost = True
        self.ShowActivated = False
        self.Size = Eto.Drawing.Size(Eto_w, Eto_w)
        self.Padding = Eto.Drawing.Padding(0)
        self.MovableByWindowBackground = True
        self.Location = ed.PointF(300,300)

        self.bu = ef.Button()

        self.layout_bi = ef.DynamicLayout()
        self.layout_bi.AddRow(self.bu)

        self.layout = Eto.Forms.PixelLayout()
        self.layout.BackgroundColor = ed.Color(0,0,0,0.009)
        self.layout.Add(self.layout_bi,12,12)
        self.Content = self.layout

    def TransparentFormStyler(self, control):
        self.BackgroundColor = Eto.Drawing.Colors.Transparent
        window = control.ControlObject
        if hasattr(window, "AllowsTransparency"):
            window.AllowsTransparency = True
        if hasattr(window, "Background"):
            brush = window.Background.Clone()
            brush.Opacity = 0.5  # win
            window.Background = brush
        else:
            color = window.BackgroundColor
            window.BackgroundColor = color.FromRgba(0, 0, 0, 25)  # mac

def EstablishForm():
    form = SampleTransparentEtoForm()
    form.Owner = Rhino.UI.RhinoEtoApp.MainWindow
    form.Show()

if __name__ == "__main__":
    EstablishForm()

    def TransparentFormStyler(form,control):
        form.BackgroundColor = Eto.Drawing.Colors.Transparent
        window = control.ControlObject
        if hasattr(window, "AllowsTransparency"):
            window.AllowsTransparency = True
        if hasattr(window, "Background"):
            brush = window.Background.Clone()
            brush.Opacity = 0.6
            window.Background = brush
        else:
            color = window.BackgroundColor
            window.BackgroundColor = color.FromRgba(0, 0, 0, 25)

    form = ef.Form()

    form.Width = Eto_w
    form.Height = Eto_h
    form.Topmost = True
    form.Style(TransparentFormStyler(form,control))
    form.Style = "transparent"

    form.Show()

Report an error:

Traceback (most recent call last):
  File "file:///D:/py/Rhino/Eto/%E7%B1%BB%E7%9A%84%E9%80%8F%E6%98%8E%EF%BC%8C%E7%BB%98%E5%88%B6%E6%88%90%E9%9D%9E%E7%B1%BB%E7%9A%84%E9%80%8F%E6%98%8E.py", line 71, in <module>
NameError: name 'control' is not defined

I’m not exactly sure what you are trying to achieve, could you please explain more?

I see a small control on an overall background.

Are you trying to achieve transparency for the smaller control as well?

I’ve never found a need to do that? If you want to have a “transparent” or “clipped” button you should create an Eto.Forms.Drawable control and then inside the Drawable init and OnPaint you can define your button rectangles/shapes/paths/etc. and then draw/fill them in the OnPaint method.

You override the OnMouseEnter, OnMouseLeave, OnMouseDown, OnMouseUp events in the Drawable to handle the “button interactions” with the mouse.

You can also use use Graphics.SetClip and ResetClip to have images fall within the bounds of a a graphics path such as drawing a typical square image inside of a circle shaped path or oval or whatever…

Here you can see a rectangular headshot image clipped inside an ellipse path:
image

Inside OnPaint:

        def OnPaint(self, e):
            e.Graphics.SetClip(self._ellipse_path)  # Set the rounded path to clip the icon
            e.Graphics.DrawImage(self.icon_image, self._i_rect)  # Draw Icon
            e.Graphics.ResetClip()  # Reset the clipping

I’m trying to draw transparent forms without using classes, forgive my level of expressiveness.

if __name__ == "__main__":
    def TransparentFormStyler(form,control):
        form.BackgroundColor = Eto.Drawing.Colors.Transparent
        window = control.ControlObject
        if hasattr(window, "AllowsTransparency"):
            window.AllowsTransparency = True
        if hasattr(window, "Background"):
            brush = window.Background.Clone()
            brush.Opacity = 0.6
            window.Background = brush
        else:
            color = window.BackgroundColor
            window.BackgroundColor = color.FromRgba(0, 0, 0, 25)

    form = ef.Form()

    form.Width = Eto_w
    form.Height = Eto_h
    form.Topmost = True
    form.Style(TransparentFormStyler(form,control))
    form.Style = "transparent"

    form.Show()

Hmm well… This should give you a transparent form by just calling definitions…

import Eto
import Rhino

def CreateMyForm():
    form = Eto.Forms.Form()     
    form.WindowStyle = Eto.Forms.WindowStyle.None
    
    form.Styles.Add[Eto.Forms.Panel]("transparent", MyFormStyler)
    form.Style = "transparent"
    
    form.AutoSize = False
    form.Resizable = True
    # form.TopMost = True
    form.ShowActivated = False
    form.Size = Eto.Drawing.Size(300,300)
    form.Padding = Eto.Drawing.Padding(80)
    form.MovableByWindowBackground = True
    form.Location = Eto.Drawing.Point(200,200)

    return form

def MyFormStyler(control):
    form.BackgroundColor = Eto.Drawing.Colors.Transparent
    window = control.ControlObject
    if hasattr(window, "AllowsTransparency"):
        window.AllowsTransparency = True
    if hasattr(window, "Background"):
        brush = window.Background.Clone()
        brush.Opacity = 0.1
        window.Background = brush
    else:
        color = window.BackgroundColor
        window.BackgroundColor = color.FromRgba(0,0,0,25)

def OnButtonClick(sender, e):
    form.Close()


if __name__=="__main__":
    form = CreateMyForm()
    form.Owner = Rhino.UI.RhinoEtoApp.MainWindow
    form.Show()

But there’s a lot of advantages to setting it up as a class more directly.
Eto.Forms.Form is already a class so by creating form = we are creating an instance of that class.

Is there an issue you are having when trying to set up your form as a class directly?

#! python2

import Rhino
import scriptcontext
import System

import Eto

class SampleTransparentEtoForm(Eto.Forms.Form):
    def __init__(self):
        
        self.WindowStyle = Eto.Forms.WindowStyle.None
        
        self.Styles.Add[Eto.Forms.Panel]("transparent", self.MyFormStyler)
        self.Style = "transparent"
        
        self.AutoSize = False
        self.Resizable = True
        self.TopMost = True
        self.ShowActivated = False
        self.Size = Eto.Drawing.Size(300,300)
        self.Padding = Eto.Drawing.Padding(80)
        self.MovableByWindowBackground = True
        self.Location = Eto.Drawing.Point(100,100)
        
        
        self.Button = Eto.Forms.Button(Text = "Close")
        self.Button.Click += self.OnButtonClick
        
        self.layout = Eto.Forms.DynamicLayout()
        self.layout.AddRow(self.Button)
        
        self.Content = self.layout
    
    def MyFormStyler(self, control):
        self.BackgroundColor = Eto.Drawing.Colors.Transparent
        window = control.ControlObject
        if hasattr(window, "AllowsTransparency"):
            window.AllowsTransparency = True
        if hasattr(window, "Background"):
            brush = window.Background.Clone()
            brush.Opacity = 0.1
            window.Background = brush
        else:
            color = window.BackgroundColor
            window.BackgroundColor = color.FromRgba(0,0,0,25)

    def OnButtonClick(self, sender, e):
        self.Close()

def DoSomething():
    
    form = SampleTransparentEtoForm()
    form.Owner = Rhino.UI.RhinoEtoApp.MainWindow
    form.Show()

if __name__=="__main__":
    DoSomething()
1 Like

Well, thanks for your explanation, because when i learned eto, I learned in the official example of eto, which did not show the use of classes, and then I got used to it. In normal times, I would not use classes to encapsulate ETO and directly write flat.
Thank you for your explanation of the benefits of using classes to write eto

1 Like

Cool, glad it helped you! I also started my Eto journey with avoiding classes as long as I could but it’s really nice being able to organize functions withing a larger class, set class attributes for use throughout that classes definitions, etc. and I caved in eventually :laughing:

1 Like

Hey, do you know any tools that can convert bits py2 to py3?
I remember seeing this tool on git, but I forget where it is, it seems to be in the rhino py repository

I don’t but please do let me know if you find one!

Usually there are too main things py3 wants over py2 scripts floating around on these forums…

super().__init__(self) in the init of a class:

    class PreviewDisplayConduit(Rhino.Display.DisplayConduit):
        def __init__(self):
            super(Display.PreviewDisplayConduit, self).__init__()

and it wants lines like this (py2):

self.Button = Eto.Forms.Button(Text = "Close")

to read like this (py3):

self.Button = Eto.Forms.Button()
self.Button.Text = "Close"

Which, honestly to me looks like it’s doing the same thing… but I don’t know enough about python nuances to tell you why py3 doesn’t like the way the argument is passed to the constructor of the py2 version…

I like the way py3 is written, it looks very comfortable.

I am looking for it. I found it in a rhino repository some time ago, but I forgot to save the URL path at that time. It seems that there are many rhino libraries, so I need to look for it

Look at this, Sir.

1 Like

Awesome, super helpful, thanks for sharing!

How is it used? Is it effective