How make it?

Post Reply
User avatar
Silvio.Falconi
Posts: 4956
Joined: Thu Oct 18, 2012 7:17 pm

How make it?

Post by Silvio.Falconi »

I saw on another application this
Image

the button open a menu popup and on the menu there are two slider controls , Can make it on Fwh ?
I use : FiveWin for Harbour August 2020 (Revision) - Harbour 3.2.0dev (r1712141320) - Bcc7.30 - xMate ver. 1.15.3 - PellesC
User avatar
ukoenig
Posts: 3981
Joined: Wed Dec 19, 2007 6:40 pm
Location: Germany
Contact:

Re: How make it?

Post by ukoenig »

Silvio,

You can connect a dialog to the button on action.
Dialog-top = button-bottom, dialog-left = button-left.
There You can include what ever You want.
If needed You can paint a colored border around the dialog.
The logic can be used on any other object.
In xBrowse it is connected to a cell.

Image

connecting the dialog to the button ( main function )

// --------------
...
...
DEFINE DIALOG oDlg1 FROM 0, 0 TO 180, 200 OF oDlg PIXEL TRUEPIXEL FONT oFont ;
STYLE WS_POPUP
...
@ 20, 30 BTNBMP oBtn1 2007 ;
SIZE 30, 30 OF oDlg NOBORDER ;
ACTION MYDLG( oDlg, oBtn1, oFont )
...
ACTIVATE DIALOG oDlg CENTERED

RETURN NIL

// --------------

FUNCTION MYDLG( oDlg, oBtn, oFont )
LOCAL oDlg1, oBtn2, oSlider1, nSlidPos1 := 1, oSlider2, nSlidPos2 := 2
LOCAL oRect1 := oDlg:GetRect()
LOCAL nTop1 := oRect1:nTop
LOCAL nLeft1 := oRect1:nLeft
LOCAL nTop2 := oBtn:nTop() + oBtn:nHeight() + 25 // 25 = dlg-title
LOCAL nLeft2 := oBtn:nLeft()

DEFINE DIALOG oDlg1 FROM 0, 0 TO 180, 200 OF oDlg PIXEL TRUEPIXEL FONT oFont ;
STYLE WS_POPUP

@ 20, 20 SLIDER oSlider1 VAR nSlidPos1 OF oDlg1 ;
HORIZONTAL ;
RANGE 0, 10 ;
COLORS CLR_RED, CLR_HGRAY, CLR_CYAN ;
MARKS 10 ;
SIZE 160, 35 PIXEL UPDATE
oSlider1:SetFont( oFont )

@ 80, 20 SLIDER oSlider2 VAR nSlidPos2 OF oDlg1 ;
HORIZONTAL ;
RANGE 0, 10 ;
COLORS CLR_RED, CLR_HGRAY, CLR_CYAN ;
MARKS 10 ;
SIZE 160, 35 PIXEL UPDATE
oSlider2:SetFont( oFont )

ACTIVATE DIALOG oDlg1 ;
ON INIT oDlg1:Move( nTop1 + nTop2, nLeft1 + nLeft2, , , .t. )

RETURN NIL

best regards
Uwe :D
Since 1995 ( the first release of FW 1.9 )
i work with FW.
If you have any questions about special functions, maybe i can help.
User avatar
Silvio.Falconi
Posts: 4956
Joined: Thu Oct 18, 2012 7:17 pm

Re: How make it?

Post by Silvio.Falconi »

Uwe,
If I wanted a dialog I already knew how to do it
I think I asked for a particular thing
If you look closely you will see that the button opens a POPUP MENU control
and therefore not a dialog
other times you've already answered with other things that I don't even think about asking!!!!
I use : FiveWin for Harbour August 2020 (Revision) - Harbour 3.2.0dev (r1712141320) - Bcc7.30 - xMate ver. 1.15.3 - PellesC
User avatar
ukoenig
Posts: 3981
Joined: Wed Dec 19, 2007 6:40 pm
Location: Germany
Contact:

Re: How make it?

Post by ukoenig »

Silvio,
the button open a menu popup and on the menu there are two slider controls
in case something is not possible I'm looking for a alternative solution
that comes close to the needed result.
other times you've already answered with other things that I don't even think about asking!!!!
Trying to find a solution It is not a answer to something else.
But never mind I can save my time.

regards
Uwe
Since 1995 ( the first release of FW 1.9 )
i work with FW.
If you have any questions about special functions, maybe i can help.
User avatar
Silvio.Falconi
Posts: 4956
Joined: Thu Oct 18, 2012 7:17 pm

Re: How make it?

Post by Silvio.Falconi »

please,

Code: Select all

#include "Fivewin.ch"
#include "Slider.ch"

Function Test()

Local aget[10]
Local oDlgTest
Local oFont
Local oBtn1

DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-12 BOLD


DEFINE DIALOG oDlgTest FROM 0, 0 TO 180, 200  PIXEL TRUEPIXEL FONT oFont


@ 20, 30 BUTTON oBtn1 PROMPT "%" ;
SIZE 30, 30  PIXEL OF oDlgTest



oBtn1:bRClicked := {|nRow,nCol| MyPercentuale2(oBtn1,aget,oDlgTest,oFont,nRow,nCol) }




ACTIVATE DIALOG oDlgTest CENTERED

RETURN NIL

//-------------------------------------------------------------------------//


Function MyPercentuale2(oBtn,aget,oDlg,oFont,nRow,nCol)

 Local oMyoMenu
 Local aItem[4]
 Local nSconto_Percentuale := 0.00
 Local nSconto_Giorni:= 0

 bAction1 :=Sliders(aItem[1])
 bAction3 :=Sliders(aItem[3])

      MENU  oMyoMenu POPUP
         MENUITEM aItem[1] PromPt "Slider 1" // BLOCK bAction1
         MENUITEM aItem[2] PromPt "Sconto giorni :" + Ltrim(str(nSconto_Giorni))
         MENUITEM aItem[3] PromPt "Slider 3"  BLOCK bAction3
         MENUITEM aItem[4] PromPt "Sconto percentuale :"+ Ltrim(str(nSconto_Percentuale))
       ENDMENU


  ACTIVATE POPUP oMyoMenu OF oDlg AT  oBtn:nTop+nRow, oBtn:nLeft+nCol

   RETURN (NIL)




Function Sliders(aItem)
   Local oSlider1
   Local nSlidPos1 := 1

    @ 60, 20 SLIDER oSlider1 VAR nSlidPos1 OF aItem ;
                 HORIZONTAL ;
                 RANGE 0, 10 ;
                 COLORS CLR_RED, CLR_HGRAY, CLR_CYAN ;
                 MARKS 10 ;
                 SIZE 160, 35 PIXEL UPDATE
 return nil










 


I'm searching if I can make a codeblock type bInit to run a function to insert the slider into menuitem of menupopup

I found some question on Internet
https://stackoverflow.com/questions/398 ... -3-xcode-8
https://www.codeproject.com/Articles/26 ... lider-Menu

I found a source someone can converte it to fwh (https://www.codeproject.com/Articles/26 ... lider-Menu)

Code: Select all

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Markup;
using System.IO;
using System.Reflection;
using System.Windows.Media;
using System.Diagnostics;
using System.Windows.Controls.Primitives;

namespace SliderMenu
{
    public partial class SliderMenuItem : MenuItem
    {
        private const double ThumbHeight = 11.0d;
        private Slider m_Slider;
        private SortedDictionary<double, double> m_TickValueMap;

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Instance Constructor.
        /// </summary>
        public SliderMenuItem()
        {
            m_TickValueMap = new SortedDictionary<double, double>();
            InitializeComponent();
        }

        #region Attached Property Steps

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Xaml accessor function for Getting Steps property
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static int GetSteps(DependencyObject obj)
        {
            return (int)obj.GetValue(StepsProperty);
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Xaml accessor function for Setting Steps property
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="value"></param>
        public static void SetSteps(DependencyObject obj, int value)
        {
            obj.SetValue(StepsProperty, value);
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// The number of steps, or tick placements between a menu item
        /// and the previous one.
        /// </summary>
        public static readonly DependencyProperty StepsProperty =
            DependencyProperty.RegisterAttached(
            "Steps",
            typeof(int),
            typeof(SliderMenuItem),
            new UIPropertyMetadata(1));

        #endregion

        #region Attached Property Value

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Gets or Sets the value for this slider.
        /// </summary>
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Xaml accessor function for Value property
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static double GetValue(DependencyObject obj)
        {
            return (double)obj.GetValue(ValueProperty);
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Xaml accessor function for Value property
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="value"></param>
        public static void SetValue(DependencyObject obj, double value)
        {
            obj.SetValue(ValueProperty, value);
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// The real value for the slider.  
        /// </summary>
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.RegisterAttached(
            "Value",
            typeof(double),
            typeof(SliderMenuItem),
            new UIPropertyMetadata(1.0d, Value_ValueChanged));

        #endregion

        #region Attached Property Skip

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Skip property for sub menu items.  Allows a menu item to 
        /// skip a tick mark.  Especially useful for separators.
        /// </summary>
        public static readonly DependencyProperty SkipProperty =
            DependencyProperty.RegisterAttached(
            "Skip",
            typeof(bool),
            typeof(SliderMenuItem),
            new UIPropertyMetadata(false));

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Xaml accessor function for Skip property.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool GetSkip(DependencyObject obj)
        {
            return (bool)obj.GetValue(SkipProperty);
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Xaml accessor function for Skip property.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="value"></param>
        public static void SetSkip(DependencyObject obj, bool value)
        {
            obj.SetValue(SkipProperty, value);
        }

        #endregion

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Listen for change to Value property.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="e"></param>
        private static void Value_ValueChanged(DependencyObject obj,
            DependencyPropertyChangedEventArgs e)
        {
            // find appropriate tick spot, and set slider value
            SliderMenuItem item = obj as SliderMenuItem;

            if (item != null)
            {
                SetTickToValue(item, (double)e.NewValue);
            }
        }
       
        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Listen for change to slider value.  Enables binding where
        /// SliderMenuItem is the target, and a framework element is the source.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Slider_ValueChanged(object sender,
            RoutedPropertyChangedEventArgs<double> e)
        {
            // find appropriate tick spot, and set slider value
            SetValueToTick(this, (double)e.NewValue);
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Sets the slider thumb to the closest match after the value changes.
        /// </summary>
        /// <param name="item"></param>
        /// <param name="newValue"></param>
        private static void SetTickToValue(SliderMenuItem item, double newValue)
        {
            // find tick spot where   
            double[] ticks = new double[item.m_TickValueMap.Keys.Count];
            item.m_TickValueMap.Keys.CopyTo(ticks, 0);

            // Find exact match
            if (item.m_TickValueMap.ContainsValue(newValue))
            {
                foreach (double tick in item.m_TickValueMap.Keys)
                {
                    if (item.m_TickValueMap[tick] == newValue)
                    {
                        item.m_Slider.Value = tick;
                        return;
                    }
                }
            }

            // Find closest match
            for (int i = 1; i < item.m_TickValueMap.Count; i++)
            {

                double lowTick = ticks[i - 1];
                double highTick = ticks[i];

                double lowValue = item.m_TickValueMap[lowTick];
                double highValue = item.m_TickValueMap[highTick];

                //double newValue = (double)e.NewValue;

                if (newValue > lowValue &&
                    newValue < highValue)
                {
                    double valueScale = highValue - lowValue;
                    double tickScale = highTick - lowTick;

                    // set slider to closest tick match
                    double newTick = (newValue - lowValue) / (valueScale) * tickScale + lowTick;

                    item.m_Slider.Value = newTick;
                }
            }
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// After the slider value has changed, update the Value property to 
        /// hold the scaled value.
        /// </summary>
        private static void SetValueToTick(SliderMenuItem item, double tickValue)
        {
            if (item.m_TickValueMap.ContainsKey(tickValue))
            {
                item.Value = item.m_TickValueMap[tickValue];
                return;
            }

            double[] keys = new double[item.m_TickValueMap.Keys.Count];
            item.m_TickValueMap.Keys.CopyTo(keys, 0);

            int index = Array.BinarySearch<double>(keys, tickValue);

            Debug.Assert(index < 0, "What? How come I didn't find the key already?");

            index = ~index;

            Debug.Assert(index < item.Items.Count, "How did tick value go above 1000?");
            Debug.Assert(index != 0, "Insert location was before element 0.");

            double lowTick = keys[index - 1];
            double highTick = keys[index];

            double lowValue = item.m_TickValueMap[lowTick];
            double highValue = item.m_TickValueMap[highTick];

            double valueScale = highValue - lowValue;
            double sourceScale = highTick - lowTick;

            double newValue = (tickValue - lowTick) * valueScale / sourceScale + lowValue;
            item.Value = newValue;
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// After template is applied, save reference to slider object.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.m_Slider = this.Template.FindName("PART_Slider", this) as Slider;

            if (m_Slider == null)
                throw new InvalidOperationException("Control template is missing part Slider_PART");

            m_Slider.ValueChanged += Slider_ValueChanged;
        }
 
        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// Arrange pass.  Call base method to figure out menu item placement,
        /// then place tick marks at the centers of the menu items.
        /// </summary>
        /// <param name="arrangeBounds"></param>
        /// <returns></returns>
        protected override Size ArrangeOverride(Size arrangeBounds)
        {
            Size returnSize = base.ArrangeOverride(arrangeBounds);

            FrameworkElement topElement = null;
            FrameworkElement bottomElement = null;

            for (int i = 0; i < Items.Count; i++)
            {
                FrameworkElement elem = Items[i] as FrameworkElement;

                Debug.Assert(elem != null, "Added an object that wasn't a FrameworkElement??");

                // Find the bottom element.  It must have a value greater or equal to the
                // top element
                if (topElement != null)
                {
                    if ((double)elem.GetValue(SliderMenuItem.ValueProperty) >=
                        (double)topElement.GetValue(SliderMenuItem.ValueProperty))
                    {
                        bottomElement = elem;
                    }
                }

                // Move along.  Nothing to see here.
                if ((bool)(elem.GetValue(SliderMenuItem.SkipProperty)))
                    continue;

                // set the first element
                if (topElement == null)
                    topElement = elem;
            }
            
            // Single element.  Not much of a slider, but don't crash
            if (bottomElement == null && topElement != null)
                bottomElement = topElement;

            // No elements.  Nothing to do.
            if (bottomElement == null && topElement == null)
                return returnSize;

            // Calculate top, bottom margins.
            // This margin enables the thumb stop at 0 and 100 to line up with
            // the center of the top and bottom menu items.
            Rect bound = LayoutInformation.GetLayoutSlot(topElement);

            double topMargin = bound.Top + ThumbHeight / 2;
            double pointZero = bound.Top + bound.Height / 2.0;

            bound = LayoutInformation.GetLayoutSlot(bottomElement);
           
            double bottomMargin = returnSize.Height - bound.Bottom + ThumbHeight / 2.0d;
            double pointOneHundred = bound.Top + bound.Height / 2.0d;

            // Set the margin.
            m_Slider.Margin = new Thickness(0, topMargin, 0, bottomMargin);


            for (int i = 0; i < Items.Count; i++)
            {
                FrameworkElement elem = Items[i] as FrameworkElement;

                if (elem is MenuItem)
                    ((MenuItem)elem).Click += new RoutedEventHandler(SliderMenuItem_Click);

                // Move along.  Nothing to see here.
                if ((bool)(elem.GetValue(SliderMenuItem.SkipProperty)))
                    continue;

                // Grab the coordinates of the child menu item
                bound = LayoutInformation.GetLayoutSlot(elem);

                // Get the number of steps, or tick spots between this child menu item
                //  and the previous one.
                int steps = (int)elem.GetValue(SliderMenuItem.StepsProperty);

                // A value of 0 for Steps is like setting Skip = true
                if (steps < 1)
                    continue;

                // Calculate tick spot.
                double thisTickSpot = 1000.0d * (bound.Top - pointZero + bound.Height / 2.0d)
                    / (pointOneHundred - pointZero);

                // Calculate continuous tick spots.  Only allow continuous after the first element.
                if (m_Slider.Ticks.Count > 0)
                {
                    double lastTickSpot = m_Slider.Ticks[m_Slider.Ticks.Count - 1];
                    double division = (thisTickSpot - lastTickSpot) / steps;

                    for (int current_step = 1; current_step < steps; current_step++)
                    {
                        double intermediateTickSpot = lastTickSpot + current_step * division;
                        m_Slider.Ticks.Add(intermediateTickSpot);
                    }
                }

                m_Slider.Ticks.Add(thisTickSpot);
                double sliderValue = (double)elem.GetValue(SliderMenuItem.ValueProperty);
                m_TickValueMap[thisTickSpot] = sliderValue;

            }

            // At end of arrange pass, set the tick to the inital value
            SetTickToValue(this, Value);

            return returnSize;
        }

        /// §§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§
        /// <summary>
        /// A child menu item was clicked.  Set the value automatically.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SliderMenuItem_Click(object sender, RoutedEventArgs e)
        {
            this.Value = (double)((DependencyObject)sender).GetValue(SliderMenuItem.ValueProperty);
        }
    }
}
 
I use : FiveWin for Harbour August 2020 (Revision) - Harbour 3.2.0dev (r1712141320) - Bcc7.30 - xMate ver. 1.15.3 - PellesC
User avatar
Silvio.Falconi
Posts: 4956
Joined: Thu Oct 18, 2012 7:17 pm

Re: How make it?

Post by Silvio.Falconi »

for now I resolve in this mode:

Image
the user can use the percentual on Total or make a descount on days
it is beautifull but not professonal work
I use : FiveWin for Harbour August 2020 (Revision) - Harbour 3.2.0dev (r1712141320) - Bcc7.30 - xMate ver. 1.15.3 - PellesC
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: How make it?

Post by cnavarro »

Dear Silvio
Currently it is not possible, but it is not impossible
For some time I was studying that possibility, but for lack of time I left it unfinished.
I hope to be able to return to the subject and get what you propose. It is not simple because although the item has hWnd it is not considered as a container of controls. We'll see
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
Post Reply