Scrollbar and Image Position modifications

Started by rodolfodsr, June 22, 2015, 03:56:07 PM

Previous topic - Next topic

rodolfodsr

Hi! Thank you for this amazing control, it's been very helpful for me and saving a lot of coding.

I'm using the version 1.1.5.1 from the imagebox source code and importing the .dll file to my c# project in Visual Studio for desktop 2013. I already made a minor modification in the code limiting the zoom capability to 200% just altering the ZoomLevelCollection class.

Now, I have to do 2 other alterations in the code and can't find where!

1 -
My imagebox need to zoom via mouse click and mouse wheel (just fine here). The problem is, when the image is zoomed, i need the PAN capability (click, hold and move the image) but i don't want the scrollbars to show. Is there any way to hide them? I already tried to set AutoScroll = false , but then so PAN is disable, although AutoPAN = true.
Any ideias how to hide the scrollbars??

2 -
When the imagebox property "AutoCenter" is disabled, the image (when not zoomed) automatically goes to the top left corner of the imagebox. I need to choose where it goes: top right, bottom right, bottom left... It's like and ANCHOR property for the image inside the imagebox.
How to set this?
I already tried the ANCHOR property, but it refers to the imagebox itself, not the image inside. I also can't use the "AutoSize" property, since my imagebox is inside a panelLayout and it would mess up my layout.

Thank you in advance, hope i made myself clear  :D

Richard Moss

Hello,

Thanks for the question, glad you like the control.

Currently you cannot hide the scrollbars. Recently I was working on v2 of the control, which involved breaking the inheritance chain and implementing scrolling manually (which does allow the scrollbars to be hidden without breaking anything). The branch with the code is on GitHub, but I haven't released it yet as I haven't finished testing it :) While it does involve some breaking changes, I want these to be as few as possible and only related to the removal of inherited base classes, so I still have more checking to do.

As for positioning a non-zoomed image, you need to change the GetImageViewPort function (as it is virtual you could override it and do your own logic without touching the core source code). Part of the code looks something like this:

          if (this.AutoCenter)
          {
            int x;
            int y;

            x = !hScroll ? (innerRectangle.Width - (this.ScaledImageWidth + this.Padding.Horizontal)) / 2 : 0;
            y = !vScroll ? (innerRectangle.Height - (this.ScaledImageHeight + this.Padding.Vertical)) / 2 : 0;

            offset = new Point(x, y);
          }
          else
          {
            offset = Point.Empty;
          }


You would need to change the line offset = Point.Empty; to account for the different anchors you require - you can use the x = and y = lines above as a guide to how to do this. I don't really have time to look at this fully now or I'd try and provide a detailed example, sorry about that  :-[

I hope this information helps! (If not, I'll try and find some time to come up with a demo for this later towards the end of the week if I managed to get through some other tasks).

Regards;
Richard Moss
Read "Before You Post" before posting. Do not send me private messages. Do not expect instant replies.

All responses are hand crafted. No AI involved. Possibly no I either.

rodolfodsr

Quote from: Richard Moss on June 22, 2015, 08:35:16 PM
Hello,

Thanks for the question, glad you like the control.

Currently you cannot hide the scrollbars. Recently I was working on v2 of the control, which involved breaking the inheritance chain and implementing scrolling manually (which does allow the scrollbars to be hidden without breaking anything). The branch with the code is on GitHub, but I haven't released it yet as I haven't finished testing it :) While it does involve some breaking changes, I want these to be as few as possible and only related to the removal of inherited base classes, so I still have more checking to do.

As for positioning a non-zoomed image, you need to change the GetImageViewPort function (as it is virtual you could override it and do your own logic without touching the core source code). Part of the code looks something like this:

          if (this.AutoCenter)
          {
            int x;
            int y;

            x = !hScroll ? (innerRectangle.Width - (this.ScaledImageWidth + this.Padding.Horizontal)) / 2 : 0;
            y = !vScroll ? (innerRectangle.Height - (this.ScaledImageHeight + this.Padding.Vertical)) / 2 : 0;

            offset = new Point(x, y);
          }
          else
          {
            offset = Point.Empty;
          }


You would need to change the line offset = Point.Empty; to account for the different anchors you require - you can use the x = and y = lines above as a guide to how to do this. I don't really have time to look at this fully now or I'd try and provide a detailed example, sorry about that  :-[

I hope this information helps! (If not, I'll try and find some time to come up with a demo for this later towards the end of the week if I managed to get through some other tasks).

Regards;
Richard Moss

Thank you Richard!
I can't wait to have the v2 of this imagebox. As soon as you release it, let us know in the forum!

About the "anchor" function, i had some issues with my computer yesterday and have to format it, but as soon as I implement it , i will post the code here to help some others. What you said may be enough for me to solve my problem

Thank you for the quick reply and pointing out at what coding i need to do

Best Regards!

rodolfodsr

Quote from: Richard Moss on June 22, 2015, 08:35:16 PM
Hello,

Thanks for the question, glad you like the control.

Currently you cannot hide the scrollbars. Recently I was working on v2 of the control, which involved breaking the inheritance chain and implementing scrolling manually (which does allow the scrollbars to be hidden without breaking anything). The branch with the code is on GitHub, but I haven't released it yet as I haven't finished testing it :) While it does involve some breaking changes, I want these to be as few as possible and only related to the removal of inherited base classes, so I still have more checking to do.

As for positioning a non-zoomed image, you need to change the GetImageViewPort function (as it is virtual you could override it and do your own logic without touching the core source code). Part of the code looks something like this:

          if (this.AutoCenter)
          {
            int x;
            int y;

            x = !hScroll ? (innerRectangle.Width - (this.ScaledImageWidth + this.Padding.Horizontal)) / 2 : 0;
            y = !vScroll ? (innerRectangle.Height - (this.ScaledImageHeight + this.Padding.Vertical)) / 2 : 0;

            offset = new Point(x, y);
          }
          else
          {
            offset = Point.Empty;
          }


You would need to change the line offset = Point.Empty; to account for the different anchors you require - you can use the x = and y = lines above as a guide to how to do this. I don't really have time to look at this fully now or I'd try and provide a detailed example, sorry about that  :-[

I hope this information helps! (If not, I'll try and find some time to come up with a demo for this later towards the end of the week if I managed to get through some other tasks).

Regards;
Richard Moss

Richard, I want to add another Option in the the imagebox properties. If the user check AutoCenter = false, another option appears with the Image Anchor Options.

I already managed how to set the image position, but I need to add this so the user can choose what position he wants.

Please point me in the code where it's possible  ;D

Richard Moss

Hello,

I assume you mean you want to create a property? The absolute simplest way of doing this would be adding something like this:

public Type PropertyName {get; set; }

Where Type is the name of your enum (such as Anchor) assuming you're using enums and PropertyName is the name of your property, e.g. ImageAnchor.

Generally I tend to create properties with change events which is slightly more verbose, but you can look at any property in the control for details.

Then it would just be a case of reading the value in your code, for example

          if (this.AutoCenter)
          {
            ...
          }
          else
          {
            switch(this.ImageAnchor)
            {
              case TopLeft:
                 ...
                break
              case TopRight:
                 ...
                break
              ...
            }
          }

Hope that helps.

Regards;
Richard Moss
Read "Before You Post" before posting. Do not send me private messages. Do not expect instant replies.

All responses are hand crafted. No AI involved. Possibly no I either.

rodolfodsr

MY FINAL SOLUTION:

Here is what i did to build the "image anchor" option:

In Imagebox.cs i added the following code:

Line 116:

private string _imageAnchorPosition;

To create the property, in the line 1050 i did:

    [DefaultValue("TopLeft")]
    [Category("Appearance")]
    public virtual string ImageAnchor
    {
        get { return _imageAnchorPosition; }
        set
        {
            if (_imageAnchorPosition != value)
            {
                _imageAnchorPosition = value;
            }
        }
    }


Then, in the line 2046 (still Imagebox.cs) , i did the following to select and set the positions:

          if (this.AutoCenter)
          {
            int x;
            int y;

            x = !this.HScroll ? (innerRectangle.Width - (this.ScaledImageWidth + this.Padding.Horizontal)) / 2 : 0;
            y = !this.VScroll ? (innerRectangle.Height - (this.ScaledImageHeight + this.Padding.Vertical)) / 2 : 0;

            offset = new Point(x, y);
          }
          else
          {
              int x;
              int y;
              string location = this.ImageAnchor;
             
              x = !this.HScroll ? (innerRectangle.Width - (this.ScaledImageWidth + this.Padding.Horizontal)) : 0;
              y = !this.VScroll ? (innerRectangle.Height - this.ScaledImageHeight + this.Padding.Vertical) / 2 : 0;

              switch (location)
              {
                  case "CenterRight":
                    x = !this.HScroll ? (innerRectangle.Width - (this.ScaledImageWidth + this.Padding.Horizontal)) : 0;
                    y = !this.VScroll ? (innerRectangle.Height - (this.ScaledImageHeight + this.Padding.Vertical)) / 2 : 0;
                    break;
                  case "CenterLeft":
                    x = !this.HScroll ? (0 + this.Padding.Horizontal) : 0;
                    y = !this.VScroll ? (innerRectangle.Height - (this.ScaledImageHeight + this.Padding.Vertical)) / 2 : 0;
                    break;
                  default:
                    x = !this.HScroll ? (innerRectangle.Width - (this.ScaledImageWidth + this.Padding.Horizontal)) : 0;
                    y = !this.VScroll ? (innerRectangle.Height - (this.ScaledImageHeight + this.Padding.Vertical)) / 2 : 0;
                    break;
              }

              offset = new Point(x, y);
          }


So, when I write "CenterRight" or "CenterLeft" and set "AutoCenter" to false, i get what I want. I made only this 2 positions because they are all I need for my project. Also, there is a problem:  I have to write "CenterRight" and "CenterLeft" in the properties. It would be nice if a dialog box could poup-up with those options, but i wasn't able to implement that  :-[

Thank you A LOT Richard and I hope this little code and discussion can help more people

Richard Moss

Glad you got it working, and thanks for positing your solution for other users.

If you don't mind a little critique, using a string as the basis of your property is a pretty bad idea. For example, what happens if the user sets it to "centerright" (valid value, wrong case) or "OutsideTheBox" (invalid value). This sort of property should use an enum, for example

  public enum AnchorEdge
  {
    TopLeft,
    Top,
    TopRight,
    Left,
    Middle,
    Right,
    BottomLeft,
    Bottom,
    BottomRight
  }


Storage is simpler - an int rather than a string, easier to validate, and no string comparisons. You can see usages of enums throughout the ImageBox source if you are unfamiliar with these.

Regards;
Richard Moss
Read "Before You Post" before posting. Do not send me private messages. Do not expect instant replies.

All responses are hand crafted. No AI involved. Possibly no I either.