CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 30

Threaded View

  1. #16
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: Some questions regarding my project

    Quote Originally Posted by Tusike View Post
    [...]

    That seemed pretty weird to me. But it gets worse... I thought perhaps because of the multiline, chr(13) is somehow added to the textbox's text when I press enter (even though for each new word & mistaken word, I always reset textBox->Text = ""). [...]
    Yes, there is something extraneous in the text box' Text but what's there probably not is exactly what you expect it to be and, more important, not where you think it is.

    Programs behaving diferently "in real life" and when debugging is a really bad thing, and I reproduced your test running the program in the debugger, but in order to minimize if not eliminate interference of the debugger with the program I didn't set a breakpoint but added this line right at the beginning of CheckDef():

    Code:
    Diagnostics::Debug::WriteLine(String::Format("Form1::CheckDef() called, textBox1 contains: {0}",
      textBox1->Text));
    And this is the output I got from it:

    2012-07-09_223925.png

    Obviously there is something extraneous in it in the second iteration, but why is it before the user input? [<- rhetorical smiley] Also, when dealing with text boxes, it's not a chr(13) (or CR), in C++ speak called \r, it's a \r\n (AKA CRLF), but this detail is, at least in the context here, of minor relevance.

    The prevalent question now is: How the heck did it get there? Actually, you've fallen victim to one of the peculiarities of the KeyPress event. (Yes, I told you so... ) This event handler is invoked before the control gets notice of the keystroke. Consequentially this happens (without the breakpoint):

    1. You type "der Hund" and then hit Enter, thereby triggering the event and initiating execution of the real business code of your event handler.
    2. The event handler calls CheckDef() which confirms that the answer is correct.
    3. The event handler clears the contents of the text box.
    4. The event handler returns.
    5. Only now the keystroke is passed on to the control for processing, and causes it to add a \r\n at the end of the (at this point empty) contents of the text box. (It wouldn't do that if the text box wasn't multi-line.)

    So the string you get in the second iteration is "\r\ndie Katze", but the line break isn't actually part of the "Katze" input, it's a remnant of the "Hund" input.

    Setting the breakpoint now introduced this change in behavior, leading to the different results: The breakpoint gets hit between steps two and three. At this time the debugger gets control and at the same time something somewhere passes the keystroke to the text box for processing. When step three is reached, the line break has already been inserted into the text box and gets cleared along with the other stuff already there as was your intention. Consequentially, there's nothing more to insert into the text box at step five.

    One possible solution might be to set e->Handled to true after the main business processing of your handler, preventing the text box to process the keystroke. But I didn't check that, and I usually check everything (I can think of... ) when it comes to keyboard event handlers.

    Another solution that I did check successfully is this change to CheckDef() (and the equivalent change to the handling of lang1 a few lines down):

    Code:
    for (int i = 0; i<Lists::words[WordOrder[CurrentWord]]->lang2->Length; i++)
    {if (textBox1->Text->Trim()->ToLower() == Lists::words[WordOrder[CurrentWord]]->lang2[i]->ToLower()) return 1;}
    The Trim() removes any potential whitespace of from the beginning and the end of the string, and these line break characters count as whitespace.

    Another minor improvement may be the use of a string comparison that is ignoring case by itself, thereby eliminating the need for the case conversion:

    Code:
    for (int i = 0; i<Lists::words[WordOrder[CurrentWord]]->lang2->Length; i++)
    {if (!String::Compare(textBox1->Text->Trim(), Lists::words[WordOrder[CurrentWord]]->lang2[i], true)) return 1;}
    The funny thing is that this is exactly the same number of source code characters as the variant above. However, I find that stylistically neater and it even may be slightly more efficient in terms of performance (which of course is completely irrelevant here ).

    However, when initially looking at your KeyPress handler, I obviously was so distracted by the bulky comment that I simply overlooked the very first line of the handler, the if (e->KeyChar != (char)13) return;. Now this line means that the actual business part of the handler only is executed in response to hitting Enter, which indicates a perfect case for an accept button click handler, leading me to the (tested) solution I'd eventually like to propose:

    The form doesn't have any accept button at all (which actually is not uncommon for an app's main form), so I added one to the second tab page and set the the form's AcceptButton property accordingly. I did not change the button's DialogResult to anything different from the default None because the button shall not close the form like accept buttons usually do. (But AFAIR it wouldn't do so anyway unless the form has been shown as a modal dialog using ShowDialog().) Then I moved everything from the KeyPress handler except the initial if line verbatim to the new button's Click handler and finally removed the KeyPress handler. Oh, I also reverted the text box' MultiLine property to false; it looks like it was never intended to actually be multi-line in the first place anyway. Works great and IMO is much cleaner.

    If you don't want your users to see a "Check It!" (that's what I named it) button on that tab, you may move it outside the visible area of the tab page/form. Do not simply make the button invisible, since, just like disabled buttons, hidden buttons not just can't be clicked (obviously), they also don't catch keystrokes.
    Last edited by Eri523; July 9th, 2012 at 07:11 PM. Reason: Fixed line break/wrap in the first snippet
    I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

    This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

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

Featured