Results 1 to 12 of 12

Thread: [RESOLVED] How to select two pictureboxes during a single event

  1. #1

    Thread Starter
    Addicted Member colossus1958's Avatar
    Join Date
    Oct 2011
    Location
    Florence, KY, USA
    Posts
    208

    Resolved [RESOLVED] How to select two pictureboxes during a single event

    I am trying to do the following:
    1) Right-Click on the form's surface and...
    2) Select (2) PictureBoxes then...
    3) Remove the images from those PBs.

    The code I have now which is obviously not working is as follows:

    Code:
    Private Sub Main_RightClick(sender As Object, e As MouseEventArgs) Handles Me.Click
            Dim PB1 As New PictureBox
            Dim PB2 As New PictureBox
            If Windows.Forms.MouseButtons.Right Then
                If PB1 Is pbA1 Then
                    If PB2 Is pbLayoutLeft Then
                        'put code here
                        ACards.RemoveAt(0)
                        destCardLeft.RemoveAt(destCardLeft.Count - 1)
                    End If
                End If
            End If
        End Sub
    If there is a way to do this I would like to know how.
    All it takes for evil to triumph is for good men to stop programming. (My apologies to Edmund Burke)

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: How to select two pictureboxes during a single event

    Your description of what you want to do is too vague; specifically, step 2. What does "select" mean? Does the user have to do something to make this selection occur, e.g. are there multiple PictureBoxes and they have to click on two of them? What happens if the user right-clicks the form and then doesn't perform this selection? Please provide a FULL and CLEAR explanation of the problem.

  3. #3

    Thread Starter
    Addicted Member colossus1958's Avatar
    Join Date
    Oct 2011
    Location
    Florence, KY, USA
    Posts
    208

    Re: How to select two pictureboxes during a single event

    Sorry for not being clear (I should know better). By "select" I mean the user needs to be able to click on the pictureboxes in order to "select" those two for the operations to be performed. If the user right-clicks the form and makes no selection, there will need to be an option to close a dialog, or in some other manner, exit from the event without any changes being made. My initial problem is that I do not know to allow the user to click on pictureboxes as a result of right-clicking the form. Any other click event on a picturebox should not produce any results. I hope this is clearer.
    All it takes for evil to triumph is for good men to stop programming. (My apologies to Edmund Burke)

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: How to select two pictureboxes during a single event

    It would be possible to use a right-click on the form as a way to initiate this process but it would be unusual. More usual would be to right-click on the form to pop up a menu and then select an option to initiate the process. Either way, initiating the process could be as simple as setting a Boolean variable to indicate that the process is in progress.

    In the Click event handler of the PictureBoxes, you would test that flag and, if set, remember that the PictureBox has been selected. Again, that as easy as assigning the PictureBox to a variable. These variables have to be members of course, because they have to persist between method calls. After selecting a PictureBox, you would check whether two had been selected and, if so, do whatever needed to be done and then reset the flag.

    You'd also need to reset the flag on other events, e.g. clicking a Button or some other control on the form. It's up to you to determine what actions end the process and handle the appropriate events. You might provide the option to right-click the form again to explicitly end the process, either directly or via another menu selection.

  5. #5

    Thread Starter
    Addicted Member colossus1958's Avatar
    Join Date
    Oct 2011
    Location
    Florence, KY, USA
    Posts
    208

    Re: How to select two pictureboxes during a single event

    @jmcilhinney: Thanks, I think that is exactly what I needed. I'll test it out and see what happens. The menu approach may be best in the end as I think there may possibly be other functions like this that will need to be coded down the road. If so, it would best to have the right architecture already in place.
    All it takes for evil to triumph is for good men to stop programming. (My apologies to Edmund Burke)

  6. #6
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: How to select two pictureboxes during a single event

    I assume this is related to your solitaire game.
    I have a program (not a card game and the code is VB6 so won't bother posting) where I have a bunch of pictureboxes and I left and right click on them for various purposes. And there is a situation where I need to designate a number of them and do some processing based on all the boxes selected.
    So, by default, when I click on a picturebox with the left button it does some process on that box immediately.
    But, if I hold down the shift key, when I left click I see that the shift key is down so I don't do the normal process, but just add the picturebox's index to a list. Each left click, if the shift key is still down, I continue to add picturebox indexes to the list. When I see a click without the shift key, and I also see I have a number of pictureboxes indicated in my list, I then do the multi-picturebox processing on the designated pictureboxes and reset the list.
    It may be useful, if you haven't done it already, to have a single handler for you pictureboxes, so regardless of which picturebox is clicked, all the events of a give type go to a single handler so you don't have to repeat the same logic, or call the same logic from a bunch of individual event handlers. (An example of that is in the code I'm going to attach here).

    I did a solitaire game once, never completed, based on a solitaire game that was on the Silicon Graphics IRIX (version of UNIX) machine back in 1991. I probably did my version as an exercise so I would have it available on a Windows box when I no longer used the SGI regularly (around 1994), written in VB3, using the Cards.dll that Microsoft provided on the Windows 3.1 system. Around 2004 a question came up on another forum, so I updated the code to VB6, now using Cards32.dll (32-bit version) and added a lot of comments explaining what the code was doing in detail. The code was divided into two parts, the Form module, which had the high level logic of the game covered in only the three Mouse handlers (down, move, and up) for the pictureboxes. You can read through those three, short handlers and get the complete interaction and logic of the game. The code in those handlers called functions in a module, where all the support code for the game resided.

    Now, we have Windows-7 64-bit, and Cards32.dll is no longer included in the OS distribution from Microsoft.
    But, since you posted about your solitaire in another post, it got me interested in digging up that old code, and deciding how I would port that to work with VB.Net (2010). The original code from VB3/6 used control arrays of pictureboxes to hold the card images and allow the user to drag them about. The game was SeaHaven Towers, and you can look it up if you are not familiar with it. The Wiki page has some inaccuracies, as the game was on the Mac before it was on the SGI, but is still a good general description of the game.

    Anyway, since your post got me interested, I spent a number of hours this past Sunday porting it pretty much as written from VB6 to VB.Net. Of course, you don't have inherent control arrays to load any longer, so I removed the initial pictureboxes and just create an array of all the pictureboxes needed dynamically, adding common event handlers for all of them.
    There are two arrays, picCards which hold the 52 card images, and picDest, which represent eight target areas where cards can be dragged to (the four foundations, and four cells). The game is similar to FreeCell, but only a King can be moved to a new column, and the tableau is built down in suit, not alternating red and black.
    Anyway, there is another UDT (now a structure), used to track the position of the cards and serve as a linked list for cards that are "stacked" on the various places where cards can be positioned. Linking the cards in a linked list makes it easy to move multiple cards, because you just pick the one you want to move, and if the drag is legal, the card you picked is unlinked from the stack it is on, and all the other cards linked to it move with it. When you drop it on another location, you just link the first card to the new stack, all the other cards are already linked to the dragged card.

    Since you marked that thread resolved, I didn't bother posting this example of one way of using pictureboxes to implement a solitaire game. Being it is a straight port from original VB3 code, it is not a good example of taking advantage of classes and objects and references available in VB.Net. But it could be interesting, none the less. I just noticed a little while ago (decided to mod it again for the fun of it to draw the cards, rather than use pictureboxes, so you have to add form mouse processing and determine which "card" clicked yourself, since you don't have pictureboxes to do that for you.), that a lot of the methods (coming from VB3), don't have the Private or Public modifiers on them. Oh well, won't fix that just now, so let if default to Public in the Module.
    Since the Cardsxxxx.dll is no longer available, although I'm sure one could find some replacement on the web, I just had the VB6 version draw the cards and capture in a bitmap, and included it as a resource in the VB.Net code. I then chop it back up and put the individual pictures in the pictureboxes in place of calling the dll to fetch the images.

    Added a lot of new comments concerning the VB.net in the code, so enough said here. Don't know if it will be useful to your directly, but since you indirectly inspired the port, I'll go ahead and post it for what it is worth.

    As mentioned, it was never completed. You can play a full game, and you can undo and redo moves, or restart the game you're playing, but the original had an autoplay mode to determine if the game was winable (not all are winable), but if you gave up and hit autoplay and the game was not winable, that counted as a win for you. Only if the game could be won and you gave up, would it be counted as a loss. Also, the current game, along with the statistics were written to a file, so you could always quit (without giving up), and comeback and restart the same game again when you came back to it. I didn't add any of that to this yet (and after 20 years, not sure that I ever will).
    Attached Files Attached Files
    Last edited by passel; Jul 2nd, 2014 at 09:19 PM.

  7. #7
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Location
    Good Old Europe
    Posts
    3,863

    Re: How to select two pictureboxes during a single event

    I didn't look at passels code, however why are you using several pictureboxes? That way the drawing might be easy(just setting the backgroundimage once) but you need a picturebox for each card, alreday knowing that you will see only parts of most them at a time.
    My solution was using a single picturebox and drawing each card in the correct position, more exactly drawing all possible staples(correct word?) wiith its cards. When clicking on a staple on a specific position the logic decides how many cards are selected and can be moved ( drawing them on the move or not). For sure the exact logic of your game tells wether cards can be moved or not.
    Like passel I did my own patience game, so I'm interested how you will do it and I'm standing by for further questions down the road.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button


    Wait, I'm too old to hurry!

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: How to select two pictureboxes during a single event

    I wasn't aware of the application but I would go along with drawing on a single PictureBox. You might like to check out this CodeBank thread of mine for some idea of how to work with the drawn "objects":

    http://www.vbforums.com/showthread.p...g-GDI-Drawings

  9. #9
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: How to select two pictureboxes during a single event

    I think either way for this type of game, i.e. a card game or simple board game is viable.
    Using pictureboxes is much easier to code, but using a lot of controls updates relatively slower than drawing directly.
    For cards, its not a big deal either way.
    I just converted the code in post #6 earlier today to draw the cards rather than use pictureboxes as a quick exercise and to have a ready example for comparison in the future.

    The advantage of the pictureboxes is, as was mentioned, much less drawing. In fact, if I didn't have the card highlighting function there would be no drawing at all since the pictureboxes maintain the drawing themselves. The Z-Order of the pictureboxes get changed when dragging or auto moving the cards, and that is a simple thing to do.

    Drawing the images myself, means I have about 40 to 50 lines I added to the Paint event for the Form, to draw the cards in the various places in the proper order. Now that code can be reduced and simplified by simply adding a Z-Order linked list to the card objects like windows has for its windows. I could then use the same logic I'm using for the pictureboxes to bring the cards forward when moving, and the drawing in the paint even will be a simple loop through all the cards in z-order and I won't care where they are in particular, which would reduce the 40-50 lines down to 10 lines of code probably.

    Then there is the matter of responding to the selection of the card.
    With the pictureboxes all being handled by the same event handler, it is two lines of code to know which card was clicked on and then the additional lines to deal with it.

    When you draw the cards yourself, then you are going to have to add code to do the hit testing, which will have to do a bit of searching to find which card, or possible cards are under the mouse, and take into consideration the z-order of the cards to determine which is on top when the cards overlap.
    Right now, what is done in two lines with the pictureboxes, is about 25-30 lines currently in the Mouse Down event to determine which card was clicked.
    Again, once I add the Z-order link list for the drawing order of the cards, then the hit test can use the same list to make the hit test a simple single loop, and reduce the 25-30 down to probably 5 lines of code.

    The advantage for drawing is that it is much faster visually (and more flexible), and of course less resource heavy. But because the drawing is quick, I'm going to have to use a timer to regulate the movement when sending cards home, or if I want to animate the dealing, whereas the controls being repositioned was slow enough to sort of regulate itself (with the baneful use of DoEvents).
    Last edited by passel; Dec 17th, 2014 at 05:08 PM.

  10. #10

    Thread Starter
    Addicted Member colossus1958's Avatar
    Join Date
    Oct 2011
    Location
    Florence, KY, USA
    Posts
    208

    Re: How to select two pictureboxes during a single event

    Thanks for all the recent posts guys. I have already dumped most of my original layout as being too clumsy. There are now only eight PictureBoxes on the main form (game board). I will still have to use pictureboxes for a while until I better understand GDI. My attempts to paint on the surface (actually a Panel at the time) while successful were difficult for me to work with. I will get the hang of it in time. Right now the game is nearing completion. I only have two minor routines and one major routine to deal with and I will be ready for clean up (additional comments, finding possible crashes, etc.). I doubt mightily that anyone is going to want to see this code even when I am through with it except to get a good laugh. My coding abilities are not what they could be but at least I am trying. I have noticed that some people who ask questions on this forum seem to make no initial efforts. What a pity. They are missing out on one of the last great creative functions left in America IMHO. Thanks again for all your help. Consider this particular thread thread closed. I'll get back if there is anything else I can't figure out on my own.
    All it takes for evil to triumph is for good men to stop programming. (My apologies to Edmund Burke)

  11. #11
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: How to select two pictureboxes during a single event

    Quote Originally Posted by colossus1958 View Post
    I doubt mightily that anyone is going to want to see this code even when I am through with it except to get a good laugh. My coding abilities are not what they could be but at least I am trying.
    I laugh at stuff I did six months ago, never mind years ago.
    Quote Originally Posted by colossus1958 View Post
    I have noticed that some people who ask questions on this forum seem to make no initial efforts. What a pity. They are missing out on one of the last great creative functions left in America IMHO.
    Hallelujah!

  12. #12
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: [RESOLVED] How to select two pictureboxes during a single event

    Well, I don't know if it might be of any use in the future, but since I modified the code in post #6 to draw the cards (using DrawImage with a bitmap of each card) instead of pictureboxes for each individual card, I may as well post it.
    I've already described some of the changes done in post #9.
    This is still based on the original code, which has a history back to VB3 so doesn't use classes. The code could benefit a lot I think by redoing it, taking advantage of the object oriented design that wasn't available back in VB3 days (at least not in VB3).
    To reiterate and expand on the changes done to post #6 example to this:
    1. Remove all the pictureboxes. Create a structure with a bitmap and rectangle to take the place of the pictureboxes. Create two arrays of those structure, the same dimension (52 cards, and 8 stacks) that we used previously.
    2. Add new double linked list links to the Card_Type, to maintain the Z-Order (drawing order) of the bitmaps, which is also used in reverse order to determine which image was clicked on.
    3. Add the routine that searches the Z-Order list in reverse to determine which card or stack was clicked on. (only care about home stacks, other stacks are ignored).
    4. Add a routine to initially link all the cards and stacks to the Z-Order list, and another routine to move a card to the top of the Z-Order (last to be drawn).
    5. Add a routine for the paint event to call, to draw all the stacks and cards on the form.
    (the drawing and mouse events could easily be moved to another control, such as a panel or picturebox, with very little change to the code other than modifying the reference names).
    6. Set the Form's DoubleBuffered property.
    7. Added a timer to regulate the drawing speed, and a function for the timer to call to do one step of the card animation.
    The step code wasn't changed, but the loop it was in at the bottom of the Send_any_Free_Cards_Home sub was removed, and the step code put in the new function for the timer to call to do the one step. The function returns false, until all the animation is done, at which time the timer will stop, until started the next time animation is to be done.

    If you tried the code in post #6, and compare the running of that code against this, there shouldn't be much of a difference visually, or the way it looks and feels compared to the Pictureboxes version. The main way to tell them apart when first running, is that the transit stacks (cells), are pictureboxes with 3D borders in the picturebox version, and just a white drawn rectangle in the non-picturebox version. Also, in the non-picturebox version, later in the game, you'll see the Normal Stacks, aka the tableau columns, base positions are also outlined in white, where as I didn't bother to use pictureboxes for those positions, nor draw rectangles there, in the pictureboxes version.

    So, in spite of its VB3 design, I'll post this version just for contrast in how the card images are managed between the two implementations.
    Attached Files Attached Files

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width