简体   繁体   中英

Pass mouse event from one PictureBox control to another C#

As the title suggests I am trying to pass mouse events from one control to another. I'm still a bit new to c# and not even sure if it's possible. I am creating a basic card game, and when I click the mouse down over the deck, I want to pop a card out and drag it without lifting the mouse button. Below is the code for the deck which is on my Main Form

public partial class Form1 : Form
{
    int CardWidth = 63;
    int CardHeight = 88;

    public List<Card> cards = new List<Card>();
    public List<Card> deck = new List<Card>();

    public Form1()
    {
        InitializeComponent();
        loadCards();
    }

    private void loadCards()
    {
        for(int i = 0; i < 10; i++)
        {
            cards.Add(new Card(i*CardWidth, CardHeight * 0, CardWidth, CardHeight,this));
        }

        deck.AddRange(cards);
        updateDeck();
    }

    public void updateDeck()
    {
        Console.WriteLine($"Deck has {deck.Count} cards in it!");
        int min = new[] { 4, deck.Count}.Min();

        if(deck.Count == 1)
        {
            pbDeck.Image = Properties.Resources.CardBackDefault;
        }
        if (deck.Count > 1)
        {
            switch (min)
            {
                case 2:
                    pbDeck.Image = Properties.Resources.Deck2;
                    break;
                case 3:
                    pbDeck.Image = Properties.Resources.Deck3;
                    break;
                case 4:
                    pbDeck.Image = Properties.Resources.Deck4;
                    break;
            }
        }
        if (deck.Count <= 0)
        {
            pbDeck.Image = Properties.Resources.DeckEmpty;
        }
    }

    private void pbDeck_MouseDown(object sender, MouseEventArgs e)
    {
        //Pickup Top card if exists
        if (deck.Count > 0)
        {
            //Get last value in Deck List (a.k.a. Last card placed in Deck
            Card card = deck.Last();

            //Set the card's location to the deck's location
            card.Location = pbDeck.Location;

            //Load the Card
            card.loadCard();

            //Remove the card from the deck
            deck.Remove(card);

            //Update the deck image
            updateDeck();

            card.card_MouseDown(sender, e);

            return;
        }
    }
}

This is the Card Class

//TODO: May need to be revisited how this value is accessed and modified
public Point Location { get; set; }

//Our Card's visual canvas
public PictureBox card;

//Reference to our main Form
private Form1 Form;

//How we know if the card has been picked up
public bool isMoving = false;

public Card(int X, int Y, int w, int h, Form1 form)
    {
        Location = new Point(X, Y);

        Form = form;

        card = new PictureBox();
        card.Image = Properties.Resources.CardDefaultTemplate;
        card.Location = Location;
        card.Name = "card";
        card.Size = new Size(w, h);
        card.SizeMode = PictureBoxSizeMode.StretchImage;
        card.TabIndex = 0;
        card.TabStop = false;
        card.MouseDown += new MouseEventHandler(card_MouseDown);
        card.MouseMove += new MouseEventHandler(card_MouseMove);
        card.MouseUp += new MouseEventHandler(card_MouseUp);
        card.Paint += new PaintEventHandler(card_Paint);
    }
    public void loadCard()
    {
        //Set the location of the card just in case it's changed
        card.Location = Location;

        //Add this object to the Form
        Form.Controls.Add(card);

        //Bring it in front of all other items on the form
        card.BringToFront();
    }

    public void removeCard()
    {
        //Remove card from form
        Form.Controls.Remove(card);
    }

    public void card_MouseDown(object sender, MouseEventArgs e)
    {
        //Let everyone know we're moving
        isMoving = true;

        //Bring card to frint of screen for visibility
        card.BringToFront();
    }

    public void card_MouseMove(object sender, MouseEventArgs e)
    {
        //If we're moving (a.k.a. Mouse is is down on the card)
        if (isMoving)
        {
            //Move the card center to mouse location
            card.Location = Form.PointToClient(new Point(Cursor.Position.X - (card.Width / 2), Cursor.Position.Y - (card.Height / 2)));
        }
    }

    private void card_MouseUp(object sender, MouseEventArgs e)
    {
        //Save the initial locations of the card
        int setX = card.Location.X;
        int setY = card.Location.Y;

        //Let everyone know we're not moving anymore
        isMoving = false;

        //If the card is past the right boundry
        if(setX+card.Width > Form.Width)
        {
            //Move it back within boundry
            setX = Form.Width - card.Width;
        }
        //If the card is past the left boundry
        else if (setX < 0)
        {
            //Move it back within boundry
            setX = 0;
        }
        //If the card is past the lower boundry
        if (setY+card.Height > Form.Height)
        {
            //Move it back within boundry
            setY = Form.Height-card.Height;
        }
        //If the card is past the upper boundry
        else if (setY < 0)
        {
            //Move it back within boundry
            setY = 0;
        }

        //Set final location
        card.Location = new Point(setX, setY);

        //If the final location is over the deck image on the form
        if (overDeck())
        {
            //Add this card to the deck
            Form.deck.Add(this);
            //Update the deck image
            Form.updateDeck();
            //Remove the card from the form
            removeCard();
        }

    }

    private bool overDeck()
    {
        //If the card's center X value is within the left and right boundries of the deck image on the form
        if (card.Location.X + (card.Width / 2) > Form.pbDeck.Location.X && card.Location.X + (card.Width / 2) < Form.pbDeck.Location.X + Form.pbDeck.Width)
        {
            //If the cards center Y value is within the left and right boundries of the deck image on the form
            if (card.Location.Y + (card.Height / 2) > Form.pbDeck.Location.Y && card.Location.Y + (card.Height / 2) < Form.pbDeck.Location.Y + Form.pbDeck.Height)
            {
                return true;
            }
        }

        //If the above is not true
        return false;
    }

The cards drag as I intended when out of the deck, but not when I pop them from the deck. Currently they will follow the cursor if I lift off the mouse button, and will drop when clicked again, which is not the desired result

Edit: Added more code for clarity. Changed Title to a more specific Title Edit 2: Added missing variables from Card Class

I'm not going to try to figure out how you should incorporate this into your code, but the property you are seeking to transfer the mouse input to another control is the Control.Capture Property .

This is boolean that you can set to true for the card PictureBox that you want to respond to moving the mouse. You can set this in another control's MouseDown event handler.

To demonstrate, create a new WinForm project and add a Label and PictureBox control to the form. Wire-up the following event handlers and run the program. Click down on the label and drag the mouse. The PictureBox will follow the cursor.

    private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        pictureBox1.Location = this.PointToClient(pictureBox1.PointToScreen(e.Location));
    }

    private void label1_MouseDown(object sender, MouseEventArgs e)
    {
        pictureBox1.Capture = true;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM