Author Topic: Flyout Button - Proof of Concept with wierd issue  (Read 546 times)

0 Members and 1 Guest are viewing this topic.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16778
  • Superior Stupidity at its best
Flyout Button - Proof of Concept with wierd issue
« on: April 17, 2020, 08:50:11 PM »
I am working on a proof of concept for a flyout button that will expand when clicked or perhaps hovered. It's only rudimentary but I'm gaining confidence that it could possibly be done.

Anyway, there is a problem that I can't isolate and it is driving me crazy. When it is shown in a horizontal orientation, the first time it is created, it always shows at 100,100 and the size is incorrect.

I've stepped through the code and verified the size and location values are what they should be, but when Shown is fired, the location is always 100,100 and the size is always wrong the first time. The second time, it shows where it is supposed to be and at the correct size.

Maybe someone can tell me where I am going wrong.

Code - C#: [Select]
  1. namespace FlyoutMenu
  2. {
  3.     public partial class FlyoutMenu : Form
  4.     {
  5.         private FlyoutDirection _orientation = FlyoutDirection.Down;
  6.         private Point _location;
  7.         private Size _size;
  8.         public FlyoutMenu()
  9.         {
  10.             base.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
  11.             InitializeComponent(); //from the form generator in VS
  12.             base.ControlAdded += FlyoutMenu_ControlAdded;
  13.             base.FormClosing += FlyoutMenu_FormClosing;
  14.             base.Shown += FlyoutMenu_Shown;
  15.         }
  16.         void FlyoutMenu_Shown(object sender, EventArgs e)
  17.         {
  18.             //force the form to the size and location it should be despite setting it previously
  19.             //why doesn't the value stay what it should be?
  20.             base.Size = _size;
  21.             int X = (_orientation == FlyoutDirection.Right) ? _location.X : _location.X - base.Width + base.Controls[0].Width;
  22.             int Y = (_orientation == FlyoutDirection.Down) ? _location.Y : _location.Y - base.Height + base.Controls[0].Height;
  23.             base.Location = new Point(X, Y);
  24.         }
  25.         void FlyoutMenu_FormClosing(object sender, FormClosingEventArgs e)
  26.         {
  27.             e.Cancel = true;
  28.             this.Hide();
  29.         }
  30.         void FlyoutMenu_ControlAdded(object sender, ControlEventArgs e)
  31.         {
  32.             //allow only certain controls … there is a better way, but this just works
  33.             if (e.Control.GetType().Equals(typeof(FlyoutButton)))
  34.             {
  35.             }
  36.             else if (e.Control.GetType().Equals(typeof(FlyoutLabel)))
  37.             {
  38.             }
  39.             else if (e.Control.GetType().Equals(typeof(FlyoutSeparator)))
  40.             {
  41.             }
  42.             else
  43.             {
  44.                 e.Control.Dispose();
  45.             }
  46.         }
  47.         //set the orientation and size of the control
  48.         private void setOrientation()
  49.         {
  50.             this.Width = 16;
  51.             this.Height = 16;
  52.             int wid = 0;
  53.             int hgt = 0;
  54.             int MaxHgt = 0;
  55.             int MaxWdt = 0;
  56.             int minWid = 16;
  57.             int minHgt = 16;
  58.             foreach (Control con in base.Controls)
  59.             {
  60.                 if (_orientation == FlyoutDirection.Left)
  61.                 {
  62.                     con.Left = -wid;
  63.                     con.Top = 0;
  64.                 }
  65.                 else if (_orientation == FlyoutDirection.Right)
  66.                 {
  67.                     con.Left = wid;
  68.                     con.Top = 0;
  69.                 }
  70.                 else if (_orientation == FlyoutDirection.Up)
  71.                 {
  72.                     con.Left = 0;
  73.                     con.Top = -hgt;
  74.                 }
  75.                 else if (_orientation == FlyoutDirection.Down)
  76.                 {
  77.                     con.Left = 0;
  78.                     con.Top = hgt;
  79.                 }                        
  80.                 wid += con.Width + con.Padding.Horizontal;
  81.                 hgt += con.Height + con.Padding.Vertical;
  82.                 MaxHgt = Math.Max(MaxHgt, con.Height + con.Padding.Vertical);
  83.                 MaxWdt = Math.Max(MaxWdt, con.Width + con.Padding.Horizontal);            
  84.             }
  85.             if (base.Controls.Count > 0)
  86.             {
  87.                 int leftmin = Math.Abs(Math.Min(base.Controls[0].Left, base.Controls[base.Controls.Count - 1].Left));
  88.                 int topmin = Math.Abs(Math.Min(base.Controls[0].Top, base.Controls[base.Controls.Count - 1].Top));
  89.                 foreach (Control con in base.Controls)
  90.                 {
  91.                     con.Left += leftmin;
  92.                     con.Top += topmin;
  93.                 }
  94.             }
  95.             if ((_orientation == FlyoutDirection.Left)||(_orientation == FlyoutDirection.Right))
  96.             {
  97.                 base.Width = Math.Max(wid, minWid);
  98.                 base.Height = Math.Max(MaxHgt, minHgt);
  99.             }
  100.             else
  101.             {
  102.                 base.Width = Math.Max(MaxWdt, minWid);
  103.                 base.Height = Math.Max(hgt, minHgt);
  104.             }
  105.             _location = base.Location;
  106.             _size = base.Size;
  107.         }
  108.  
  109.         public FlyoutDirection Orientation
  110.         {
  111.             get { return _orientation; }
  112.             set
  113.             {
  114.                 _orientation = value;
  115.                 setOrientation();
  116.             }
  117.         }
  118.         public enum FlyoutDirection
  119.         {
  120.             Down,
  121.             Right,
  122.             Up,
  123.             Left
  124.         }
  125.     }
  126.     //these will ultimately be the controls for the flyout
  127.     public class FlyoutButton: Button
  128.     {
  129.         public FlyoutButton(){}
  130.     }
  131.     public class FlyoutLabel : Label
  132.     {
  133.         public FlyoutLabel(){}
  134.     }
  135.     public class FlyoutSeparator : ToolStripSeparator
  136.     {
  137.         public FlyoutSeparator(){}
  138.     }
  139. }
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Lonnie

  • Newt
  • Posts: 42
Re: Flyout Button - Proof of Concept with wierd issue
« Reply #1 on: May 22, 2020, 01:47:58 PM »
From my pea picker understanding of that stuff I think you can delete the menu files created by the cuix and it should recreate for you properly. It's free advice so take it for what it's worth. I'd have not posted this but you weren't getting any other ideas.

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16778
  • Superior Stupidity at its best
Re: Flyout Button - Proof of Concept with wierd issue
« Reply #2 on: May 22, 2020, 02:16:30 PM »
Yeah, lots of views but unfortunately no advice. It happens. Could be any number of reasons. I'll not judge.

Just so I'm clear, this isn't part of the cui it is going to be on a user palette.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

Atook

  • Swamp Rat
  • Posts: 959
Re: Flyout Button - Proof of Concept with wierd issue
« Reply #3 on: May 22, 2020, 06:43:02 PM »
Just so I'm clear, this isn't part of the cui it is going to be on a user palette.

This looks like a great project. I'm curious why it's based on a form and not a UserControl?

I know AutoCAD does weird stuff with forms, 2021 seems to forget where a my forms are closed and always show them starting in the top left corner of my left monitor (might be 100,100?)

Maybe try basing it off a UserControl and see if that helps?

Keith™

  • Villiage Idiot
  • Seagull
  • Posts: 16778
  • Superior Stupidity at its best
Re: Flyout Button - Proof of Concept with wierd issue
« Reply #4 on: May 23, 2020, 11:34:17 AM »
Just so I'm clear, this isn't part of the cui it is going to be on a user palette.

This looks like a great project. I'm curious why it's based on a form and not a UserControl?

I know AutoCAD does weird stuff with forms, 2021 seems to forget where a my forms are closed and always show them starting in the top left corner of my left monitor (might be 100,100?)

Maybe try basing it off a UserControl and see if that helps?

Subclassing form is a hack to allow the control to be modeless and extend beyond the rectangle of the parent. Initially I looked at subclassing contextmenu but that proved to be significantly more backend work because there isn't a simple way to control the orientation of buttons. I'd have to override internal functions that aren't designed to be overridden .. not that I couldn't clone the entire class and write EVERYTHING from scratch, but that would involve a ton of code that might simply not be necessary.

Anyway, the flyout wouldn't be useful for a bunch of buttons, maybe 5 or 6 tops depending upon their size and location on the screen, but being able to control the flyout direction (up,down,left,right) seems like a very useful function especially where its not desirable to cover GUI elements.

It's still on my wishlist but not a priority right now.
Proud provider of opinion and arrogance since November 22, 2003 at 09:35:31 am
CadJockey Militia Field Marshal

CADbloke

  • Bull Frog
  • Posts: 314
  • Crash Test Dummy
Re: Flyout Button - Proof of Concept with wierd issue
« Reply #5 on: May 24, 2020, 05:12:20 AM »
It’s WPF but have a look at https://mahapps.com/api/MahApps.Metro.Controls/Flyout/ and also chase up what sorts of issues users may have had in the past. Mahapps is on Github so the code is readily accessible.
I use it for tvCAD & other WPF apps.