3
\$\begingroup\$

I have a panel that has 4 images per row and a lot of rows. Each image has a 15 pixels separation and are 250,250 each.

Here is a screenshot:

enter image description here

I'd like to be able to click on a picture and identify the image number (from 0 top left to the right). Of course, avoiding the separation.

  protected override void OnMouseClick(MouseEventArgs e)
    {
        vsValue = VerticalScroll.Value;
        // what row ?
        double ScrollVposition = vsValue + e.Y;
        double row = Math.Floor(ScrollVposition / (BitmapHeight + BitmapSpacing)); // it's the right row, unless i clicked on the spacing
        int topEdge = ((BitmapHeight + BitmapSpacing) * (int)row) + BitmapSpacing; // the Y coordinate of the top of the image
        int bottomEdge = topEdge + BitmapHeight; // the bottom of that same image
        if (ScrollVposition < bottomEdge && ScrollVposition > topEdge) // check if the click happens between the top and the bottom of the image
        { } // row is the right row number
        else row = -1; // not an image
        // what column ? same logic as the row
        double width = e.X;
        double col = Math.Floor(width / (BitmapWidth + BitmapSpacing));
        col = Math.Min(col, perCol-1); // got space after the last col on the right
        int leftEdge = ((BitmapWidth + BitmapSpacing) * (int)col) + BitmapSpacing;
        int rightEdge = leftEdge + BitmapWidth;
        int ima;
        if (width < rightEdge && width > leftEdge && row >= 0)
            ima = ((int)row * perCol) + (int)col;
        else ima = -1;
        picture_id = ima;


        base.OnMouseClick(e);

    }

Do you think I can improve it?

EDIT : Here is the paint event :

        base.OnPaint(e);
        e.Graphics.TranslateTransform(this.AutoScrollPosition.X,
                       this.AutoScrollPosition.Y);
        First_id = getTopPictureId(VerticalScroll.Value);
        int buffer = 20;
        int limithaute = Math.Min(First_id + buffer, fp.Count());
        for (int i = First_id; i < limithaute; i++) // 
        {
            System.Drawing.Image img = GetImage(fp[i]);
            e.Graphics.DrawImage(img, new PointF(BitmapSpacing + (BitmapSpacing * (i % perCol) + (BitmapWidth * (i % perCol))),
                BitmapSpacing + (BitmapSpacing * (i / perCol)) + (BitmapHeight * (i / perCol))));
       }

A bit of explanation, the for loop goes through the images i'd like to show (the list of 3000+ total, the scrolling have a disposition process). Fp is the list of files that contains the images.

\$\endgroup\$
7
  • \$\begingroup\$ How are you showing the image? If you use a Picturebox, you can handle the MouseClick event directly instead of all those calculations. \$\endgroup\$
    – user33306
    May 7 '20 at 1:19
  • \$\begingroup\$ no i'm overriding the paint event with drawimage. \$\endgroup\$ May 7 '20 at 7:07
  • 1
    \$\begingroup\$ Is directly drawing them necessary? A PictureBox would make your life a lot easier. \$\endgroup\$
    – user33306
    May 7 '20 at 7:15
  • \$\begingroup\$ @tinstaafl: Sounds like a good answer to me! \$\endgroup\$
    – Graipher
    May 7 '20 at 9:41
  • \$\begingroup\$ Since it seems to matter how you draw your images, it might make ssense to include some code regarding that. \$\endgroup\$
    – Graipher
    May 7 '20 at 9:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.