Anthony Pecorella

For reference, I'm working in VS Express, C#.  I'll try to keep background short and need-to-know.  Also, my apologies on the font size - I tried to make it normal and apparently I have failed...

In my efforts to follow a good OO approach to programming a project, I have created an abstract object called Item (as in an item on a test) with an abstract method Display (which displays the item and returns an int that is the answer given).  I also have a TestAdministrator class that selects the items in a test and presents them to the test taker.

Furthermore, in an effort to keep load times to a minimum, I have created an ItemDisplayForm class that gets passed into the Display function.  The idea was to have a single, full-screen form that each item would manipulate to put the proper text, image, video, answer choices, whatever, in order to remove the load overhead for creating a new form each time an item is displayed. 

Each time an item is administered, I simply use:


 // item is of course an Item, and IDF is an ItemDisplayForm
 
int answerGiven = item.Display( IDF )

 

The Display function in my current implementation looks like this:


//LoadItem() initializes the fields on the ItemDisplayForm

public override int Display( ItemDisplayForm IDF )
{
     IDF.LoadMovieItem( itemText, answers );
     DialogResult result = IDF.ShowDialog();
     if (result == DialogResult.OK)
     {
          return IDF.AnswerGiven;
     }
     else
     {
          throw new Exception( "There was a problem." );
     }
}

 

The problem is that the ShowDialog() method closes the dialog (IDF).  My goal is to find a way to return the dialog result without closing the dialog.  Or alternatively find a way for the program to wait until the test taker has pressed the "next question" button, at which point hopefully Display would return the answer given.  Is this doable with my current implementation   Any other implementation   Am I being dumb and missing an obvious way to do this

Thank you so much for the help.



Re: Windows Forms General Dialog result without closing / event handling

BonnieB

Anthony,

Have your "Next Question" button be the one that issues the DialogResult.OK. There is a DialogResult property for a button ... set it to DialogResult.OK in the Property Sheet.






Re: Windows Forms General Dialog result without closing / event handling

Anthony Pecorella

A good suggestion - but I think I tried that and the problem is that setting dialog result to anything closes the current form. The problem with that is I then need to reload the form for the next question - which adds about a 2-3 second overhead per question. Thanks for the response though - I didn't know if anyone would respond to someone on a first post - so, yeah - thanks!



Re: Windows Forms General Dialog result without closing / event handling

BonnieB

Anthony,

You wouldn't have to reload it each time, just do an IDF.ShowDialog() again and that should work. The Form isn't actually closed, it's just hidden.






Re: Windows Forms General Dialog result without closing / event handling

Anthony Pecorella

You know, I read that somewhere and that's what I was hoping would happen (though I needed to make a bit of a hack and put a second, blank screen up so when the dialog is hidden you wouldn't see what's behind it), but for some reason even then I have a significant load time.  I should note that I am playing a QuickTime movie in these tests (using the AxQTControl).  I wonder if QuickTime has some behavior that unloads the movie when the dialog is hidden   I'll have to look into that. 

Thanks for confirming the hiding action of the dialog though - that'll help narrow my focus.  I do know that if I keep a form shown and switch movies it is near instantaneous, but when I reload it's slow and I just discovered a null reference error upon trying to access the AxQTControl.Movie properties/methods.  I bet that's my problem.  Of course, I'm not sure what to do if QuickTime decides it wants to unload itself every time a dialog result is given.  Hmmm...

Actually, on that note - is AxQTControl the correct way to embed QuickTime in a WinForm   The name implies it's an ActiveX control (and I'm not working with browsers at all), but it's the only QuickTime control I can find.  It does seem to work quite well outside of this spontaneous combustion on form hiding...





Re: Windows Forms General Dialog result without closing / event handling

BonnieB

Anthony,

Well, I don't know anything about the QuickTime ActiveX control, sorry. How and where is it being instantiated How and where does it get the movies to play Here's what happens when you call a Form with ShowDialog():

When you instantiate the form (MyForm = new MyForm()), that's when MyForm's constructor method runs. Anything put in there will only ever run once. Everytime you call MyForm.ShowDialog(), that's when MyForm's Load event handler runs. So, any code put in there will run every time you do the ShowDialog(). My guess is that either you're loading something or setting something up in the Load event of your Form or the QuickTime control itself is doing some extra stuff in it's load event.

If it's the QuickTime control that's doing it, I'm not sure that there's anything you can do to control it. But if it's because of some settings or method calls you're doing in the Load, that perhaps you could put elsewhere, then maybe it might work the way you want. Without seeing your code (and also without knowing anything about the QuickTime control) I can't give you any suggestions, just ideas about where to look to tweak things if possible.






Re: Windows Forms General Dialog result without closing / event handling

Anthony Pecorella

Bonnie,

Thanks for the continued help. :) InitialComponents() is the only thing in the contsructor. This function (which you know is generated automatically) does contain the instantiation and setup of the movie control. The Load event calls a function that simply switches the filename for the movie. I've tried this same function in a regular form that doesn't hide between switches and it works very well and very fast (set filename to a new file and bam, new movie shows).

However, when I return the DialogResult from my test item, then ShowDialog for the next item, I get a null reference error when I attempt to access the movie. This is why I was thinking it might be a QuickTime problem. I guess the one specific question I could ask is: how can you see if any functions are called upon a hide/close of a dialog box If I could go in and find where QuickTime was unloading, perhaps I could figure out how to properly reload it. I'm gonig to go ahead and see if I can re-initialize it anyway, but I worry that once again we'll hit that overhead.

Anyway, thanks for the help.

- Anthony





Re: Windows Forms General Dialog result without closing / event handling

BonnieB

Anthony,

Create a method on your Form that does the resetting of the movie, rather than doing it in the Form's Load event. So, you'd do this:

MyForm = new MyForm();

MyForm.SetMovie(MyMovieName);

MyForm.ShowDialog()

// .... more stuff

MyForm.SetMovie(MyNextMovieName);

MyForm.ShowDialog();






Re: Windows Forms General Dialog result without closing / event handling

Anthony Pecorella

A nice suggestion. I tried it, but somehow still I get null references when I attempt to access the quicktime file in the second question (it refuses to play automatically, doesn't give proper dimensions, and so forth). I'll play around with it today and focus on the quicktime. Perhaps I'll post more code tomorrow if I'm still stuck. Thank you so much for your help though!



Re: Windows Forms General Dialog result without closing / event handling

BonnieB

Yes, please post some code ... that was going to be my next suggestion.




Re: Windows Forms General Dialog result without closing / event handling

Anthony Pecorella

Alrighty, sure, why not :-) Hopefully this will cover everything that's needed. Sorry it's kinda long. Also, I gave up on including the little grey "code" boxes - they were making things hard to read. I hope this formatting is okay.

There are three major components involved: the Item class, the Test class, and the ItemDisplayForm.

Item class Display function:

 1     public override int Display(ItemDisplayForm IDF)
 2     {  
 3       IDF.LoadMovieItem(itemText, answers, mediaPath);
 4       DialogResult result = IDF.ShowDialog();
 5       if (result == DialogResult.OK)
 6       {
 7         return IDF.AnswerGiven;
 8       }
 9       else
 10       {
 11         throw new Exception("There was a problem.");
 12       }
 13     }

Main loop in Test class (edited for length, but kept the important parts in).

 1     /* Summary: 
 2     *  Sets up a lot of the parameters and variables needed to run the test. This includes
 3     *  initializing the ItemDisplayForm, populated the AvailItems List, and running the main
 4     *  loop that continues until we're out of questions.
 5     * Parameters:
 6     *  testID: The database ID for the test that is going to be administered.
 7     *  CurrSubject: The database ID for the subject taking the test.
 8     *  takenTest: The database ID for this instance of the test
 9     * Returns:
 10     *  A float that represents the final score.
 11     * Exceptions:
 12     */
 13     private float RunTest(int testID, int CurrSubject, int takenTest)
 14     {
 15       try
 16       {
 17         bool TestDone = false; // Used as the stopping flag for the loop
 18         int questionNum = 0; // Tracks the order in which the questions are asked
 19         int answerGiven = -1; // Tracks the answer given for each question
 20         
 21         Item CurrItem; // Tracks the current test item
 22         SortedList<int, Item> TakenItems = new SortedList<int, Item>();
 23         SortedList<int, Item> AvailItems = new SortedList<int, Item>();
 24         SortedList<int, int> AnswerResults = new SortedList<int, int>();
 25 
 26         // TODO: This is a shameful hack (having a phony background) and should be fixed
 27         GreyBackground Background = new GreyBackground();
 28 
 29         Background.Show();
 30 
 31         ItemDisplayForm DisplayForm = new ItemDisplayForm(); 
 32         while (!TestDone)
 33         {
 34           questionNum++;
 35           CurrItem = SelectNextItem(AvailItems, TakenItems);
 36 
 37           answerGiven = CurrItem.Display(DisplayForm);
 38 
 39           AvailItems.Remove(CurrItem);
 40           TakenItems.Add(questionNum, CurrItem);
 41           AnswerResults.Add(questionNum, answerGiven);
 42 
 43 
 44           if (AvailItems.Count < 1)
 45             TestDone = true;
 46 
 47         }
 48 
 49         Background.Hide();
 50         Return GiveScore(AnswerResults);
 51       }
 52       catch (Exception exc)
 53       {
 54         MessageBox.Show("An error was received: " + exc.Message.ToString());
 55         return -10000f; // -10000f indicates that there was a problem with the test
 56       }
 57 
 58     }
ItemDisplayForm, important pieces:
 1     public ItemDisplayForm() 
 2     { 
 3       InitializeComponent(); 
 4     } 
 5 
 6 
 7     public void LoadMovieItem(string _itemText, string[] _answers, string _mediaPath) 
 8     { 
 9       itemText  = _itemText; 
 10       answers   = _answers; 
 11       mediaPath  = GetDataDirectory() + "\\" + _mediaPath; 
 12       DisplayType = DisplayTypes.Movie; 
 13       answerGiven = -1; 
 14     } 
 15 
 16     private void DisplayMovieItem() 
 17     { 
 18 
 19       label1.Text = itemText; 
 20 
 21       try 
 22       { 
 23         if (mediaPath.Length > 0) 
 24         { 
 25           MovieControl.FileName = mediaPath; 
 26           MovieControl.AutoPlay = "false"; 
 27           MovieControl.Movie.Stop(); // This is the line that generates a null reference on item 2 
 28         } 
 29         else 
 30           MovieControl.Hide(); 
 31       } 
 32       catch (Exception exc) 
 33       { 
 34         MessageBox.Show("There was a problem loading the movie: " + exc.Message.ToString()); 
 35       } 
 36     } 
 37 
 38     private void ItemDisplayForm_Load(object sender, EventArgs e) 
 39     { 
 40       if (DisplayType == DisplayTypes.Movie) 
 41       { 
 42         DisplayMovieItem(); 
 43       } 
 44       else 
 45       { 
 46         // No other types yet...   
 47       } 
 48     }
(Running version 1.2.0.21780 of CodeHTMLer, which is awesome...)




Re: Windows Forms General Dialog result without closing / event handling

BonnieB

Anthony,

Sorry I didn't get back to you sooner ... I was away doing some training for some folks in another of our offices.

Thanks for posting the code, but there are still a few questions, since you haven't posted *all* of the code.

23 if (mediaPath.Length > 0)
24 {
25 MovieControl.FileName = mediaPath;
26 MovieControl.AutoPlay = "false";
27 MovieControl.Movie.Stop(); // This is the line that generates a null reference on item 2
28 }

My question is where does MovieControl.Movie come from This is obviously what the null reference is, but I don't see where you're instantiating that anywhere. I mean, you obviously have to be, since it works the first time through ... but you've neglected to post that part of the code. Wanna try again






Re: Windows Forms General Dialog result without closing / event handling

Anthony Pecorella

No prob - I'm glad you're trying to help. :)

It actually I don't believe is explicitly instantiated, at least not by me - it is a property of MovieControl (which is from the Quicktime COM reference):

private AxQTOControlLib.AxQTControl MovieControl;

I can't really find any other references to it, and I've tried to locate the constructor but have had no luck (I found the prototype function but can't find the implementation). I've had difficulty finding good documentation on the COM control, though I suppose I may have been looking in the wrong places. I'll scour around the Quicktime dev website some more and see what I can dig up. I've actually had a different (hopefully unrelated) error pop up as well, which I also posted in http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1304316, but unfortunately I haven't gotten any bites there.

Thanks again for the help.





Re: Windows Forms General Dialog result without closing / event handling

Anthony Pecorella

I think my answer is going to be to get a better understanding of event handling so that instead of using a DialogResult I simply publish an event so that I can keep my ItemDisplayForm open at all times. I've been doing some reading and hopefully can get that working. That still leaves my protected memory problem in Quicktime, but that's in my other forum post, so I won't restate it here. Thanks for the help, and I'll let you know if I hit another wall when I get into these events.

- Anthony





Re: Windows Forms General Dialog result without closing / event handling

BonnieB

Anthony,

Sorry about not getting right back to you ... swamped with stuff.

Having your Form raise an event when it's done displaying a movie (or rather, when the user clicks on the "next" button), might be a good way to go. Good thinking!! (I had assumed you were tied into a Dialog form). Let me know how that goes, or if you get end up having any event questions.

Regarding your other memory problems ... I see no one has answered your other post yet. COM stuff can be tricky, from what I understand (I haven't really had much experience with it) ... unmanaged code and all that. I hope you find your answer to that one.