A better way to write / read dozens of textboxes?
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 42

Thread: A better way to write / read dozens of textboxes?

Hybrid View

  1. #1
    Join Date
    Jun 2012
    Posts
    37

    Post A better way to write / read dozens of textboxes?

    Hi there, how are you?

    I'm using VC++ 2008 / Windows Forms Application (CLI)

    My question is quite simple:

    Let's suppose I have 60 textboxes that I would like to send a message. So, my first obvious and extensive option would be:

    textBox1->Text = "My message";
    textBox2->Text = "My message";
    textBox3->Text = "My message";
    ....
    ....
    textBox60->Text = "My message";

    That's obviously not a professional manner to code a program!

    How could I do the same by using some sort of loop? I know how to do such thing sending data to an array for example, but to print and read textboxes, numerics updowns, trackbars, etc, I have no idea.

    I'd really appreciate your input on this matter.

    Thank you in advance!

    All best,

    Fernando

  2. #2
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,016

    Re: A better way to write / read dozens of textboxes?

    Quote Originally Posted by fernando306 View Post
    How could I do the same by using some sort of loop? I know how to do such thing sending data to an array for example, but to print and read textboxes, numerics updowns, trackbars, etc, I have no idea.
    It's the same way, you store the textboxes in an array or some other container. Then set the text in a loop.
    However, in terms of user interface design, it would probably be better to use a list raster than 60 edit boxes.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  3. #3
    Join Date
    Jun 2012
    Posts
    37

    Re: A better way to write / read dozens of textboxes?

    Hi D_Drmmr, thanks for your input!

    Ok, but how can I do that?

    For example, if the names of my textboxes are textBox1 ... textBox60, that's a name that I can't use a variable in the middle to increment. I can't do something like textBox[n]. That's why I'm lost! Could you provide me a piece of code for that? I'm sorry to ask such a primary thing, but I'm used to code C for microcontrollers, where you don't have any of that.

    About the LIST, ok it might be a replacement for textboxes, but how about the NumericUpDowns, TrackBars and ComboBoxes? I have the same problem. For you to have a better idea, these are Parametric audio EQ bands:

    Name:  EQ_Band.jpg
Views: 252
Size:  12.0 KB
    Last edited by fernando306; October 14th, 2012 at 02:02 PM.

  4. #4
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,016

    Re: A better way to write / read dozens of textboxes?

    Quote Originally Posted by fernando306 View Post
    Hi D_Drmmr, thanks for your input!

    Ok, but how can I do that?

    For example, if the names of my textboxes are textBox1 ... textBox60, that's a name that I can't use a variable in the middle to increment. I can't do something like textBox[n].
    Sure you can. When you add a text box to a form, VS will add some code like this.
    Code:
    		void InitializeComponent(void)
    		{
    			this->textBox1 = (gcnew System::Windows::Forms::TextBox());
    			this->SuspendLayout();
    			// 
    			// textBox1
    			// 
    			this->textBox1->Location = System::Drawing::Point(12, 12);
    			this->textBox1->Name = L"textBox1";
    			this->textBox1->Size = System::Drawing::Size(100, 20);
    			this->textBox1->TabIndex = 0;
    Instead of creating a single text box, you can also create an array of text boxes. Then call the same code to initialize each of them. It's probably best to put this code outside the InitializeComponent function, else the form editor may get lost. Not sure about that, though.
    Quote Originally Posted by fernando306 View Post
    About the LIST, ok it might be a replacement for textboxes, but how about the NumericUpDowns, TrackBars and ComboBoxes? I have the same problem. For you to have a better idea, these are Parametric audio EQ bands:
    If your controls have specific meaning, I would suggest using more useful names than textBox1, etc. If you have the same set of controls for each band, then you should wrap those controls in a class, such that you can simply create several instances of the class, rather than duplicate the code.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  5. #5
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,594

    Re: A better way to write / read dozens of textboxes?

    Quote Originally Posted by fernando306 View Post
    Hi D_Drmmr, thanks for your input!

    Ok, but how can I do that?

    For example, if the names of my textboxes are textBox1 ... textBox60, that's a name that I can't use a variable in the middle to increment. I can't do something like textBox[n]. That's why I'm lost![...]
    Yeah, in fact that can be done. However...

    Quote Originally Posted by D_Drmmr View Post
    [...] It's probably best to put this code outside the InitializeComponent function, else the form editor may get lost. Not sure about that, though.
    Caution! Never ever do that! The code between #pragma region Windows Form Designer generated code and #pragma endregion, which mostly comprises the InitializeComponent() function, is maintained by the IDE and must not be modified by the developer, under any circumstances, (There also is a comment clearly stating this at the beginning of the region, but quoting it here would not be of much use, since it's German in my version, and certainly most users around here neither are using that version nor speak German.) The IDE keeps some sort of checksum of the region and gets really angry should anyone else modify it.

    But D_Drmmr's InizializeComponent() snippet contains a really important hint: The IDE sets the Name property of each control it creates equal to the name of the control variable. (The property can be different from the variable name, but only if you change it in your code, create the control yourself or assign an IDE-generated control object to another variable in your code.) Furthermore, the controls are accessible by that name in the form's controls collection. And that's why you can do this:

    Code:
    for (int i = 1; i <= 60; ++i)
      Controls[String::Format("textBox{0}", i)]->Text = "Your message";
    But I'm afraid that's somewhat inefficient. Probably better would be iterating over the controls rather than doing a lookup for every single one:

    Code:
    for each (Control ^ctl in Controls)
      if (ctl->Name->StartsWith("textBox"))
        ctl->Text = "Your message";
    Distinguishing the text boxes from other controls by their type rather than their name probably would be even more efficient, but making use of the Name property allows you to apply some naming scheme to narrow down the iteration to a certain subset of the text boxes, like, e.g., txtBoostCut1 to txtBoostCut60. That's probably helpful: I have seen text boxes of different use on your screen shot.

    I have also seen that your text boxes (and other controls) are inside group boxes. Controls inside group boxes are children of the group box, not the hosting form. That would make the scheme outlined above a bit more complex in that you'd need to iterate over the group boxes and then over the controls inside, somewhat like this:

    Code:
    for each (Control ^ctl in Controls) {
      GroupBox ^gbx = dynamic_cast<GroupBox ^>(ctl);
      if (gbx) {
        for each (Control ^ctlInner in gbx->Controls)
          if (ctlInner->Name->StartsWith("textBox"))
            ctlInner->Text = "Your message";
      }
    }
    This also demonstrates distinguishing controls by type, as mentioned above, with regard to the group boxes.

    Finally, the most elegant and efficient approach would probably be, like already suggested by D_Drmmr, to create your own class to bundle the controls for each channel. I'd probably do that myself in the form of an EQ band control class, derived from Panel or even GroupBox. That would be some additional effort up-front but is likely to pay later by simplifying things.

    (Snippets not tested, may contain bugs.)
    Last edited by Eri523; October 15th, 2012 at 08:28 AM.
    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.

  6. #6
    Join Date
    Jun 2012
    Posts
    37

    Re: A better way to write / read dozens of textboxes?

    Hey Eri523, that was incredibly helpful! Thank you so much. I'm having problems with my HP laptop (hate it) , but I will certainly test your solution ASAP and post back here!!!

  7. #7
    Join Date
    Jun 2012
    Posts
    37

    Re: A better way to write / read dozens of textboxes?

    Quote Originally Posted by Eri523 View Post
    Yeah, in fact that can be done. However...
    Code:
    for each (Control ^ctl in Controls) {
      GroupBox ^gbx = dynamic_cast<GroupBox ^>(ctl);
      if (gbx) {
        for each (Control ^ctlInner in gbx->Controls)
          if (ctlInner->Name->StartsWith("textBox"))
            ctlInner->Text = "Your message";
      }
    }
    I see... And I have these GrouBoxes inside a TabPage, so probably I have to first look for GroupBoxes inside the TabPage, then for NumericUpDowns inside the Groupboxes, right?

    How can I perform a search in TabPage2 for example?

    Wish me luck burning the midnight oil, and if you have any tips it will be very welcome! I'm honestly still feeling kinda lost!
    Last edited by fernando306; October 16th, 2012 at 10:08 PM.

  8. #8
    Join Date
    Jun 2011
    Posts
    25

    Re: A better way to write / read dozens of textboxes?

    I'm on my first VC project so followed this thread with avid interest.

    What I would appreciate is one or more pointers to info on how to achieve what has been hinted at here, namely encapsulating controls in a class.
    Quote Originally Posted by Eri523 View Post
    Finally, the most elegant and efficient approach would probably be, like already suggested by D_Drmmr, to create your own class to bundle the controls for each channel. I'd probably do that myself in the form of an EQ band control class, derived from Panel or even GroupBox. That would be some additional effort up-front but is likely to pay later by simplifying things.
    I know how to access controls from a class but that's not the same thing as encapsulating (or "wrapping") is it.
    "Add component class" (project menu) looked promising with designer code section in .h but no meaningfull designer view and I can't find any help on what this is or how to use it. Tried to search this forum but... (it still seems to be working on my first search...)
    RD
    Last edited by RogerD; October 18th, 2012 at 07:22 AM.

  9. #9
    Join Date
    Jan 2010
    Posts
    1,102

    Re: A better way to write / read dozens of textboxes?

    Also, if you have a bunch of controls already placed in the designer, and you opt not to create a specialized class to structure things in a better way, you should know that, assuming the number of UI elements is not going to change at runtime, you can search for the text boxes once, say, after the InitializeComponent() method, store the results, and reuse them throughout the rest of the app. That is, you don't want to search for then every time - find them once, and that's it.

  10. #10
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,594

    Re: A better way to write / read dozens of textboxes?

    Hi Cthulhu, long time no see!

    Really a good idea. ... actually, one that I already had myself while writing post #5, but considered it "probaly premature optimization at the moment", so I postponed it to the "advanced" section and potential later posts, mainly to keep post #5 compact. (No kidding! )

    When it's about a moderate number of IDE-generated controls that is unlikely to change frequently, I actually even tend to hard-code these control arrays, like this:

    Code:
    array<TextBox ^> ^atxtSpecificPurposeBoxes = gcnew array<TextBox ^>{
        txtSpecificPurpose1, txtSpecificPurpose2, txtSpecificPurpose3
      };
    In one real-life application I actually had 46 IDE-created picture boxes (on a single form, of course), and there were eight control arrays (with intersections) referring to them, everything hard-coded. Man I tell you, that was tideous... In the current version of the app, however, these boxes, now of a PictureBox-derived type, are programmatically created by a static member function of that derivate class, along the lines of this:

    Code:
      m_aclSec = ClockLight::CreateLightArray(9, ptNextLocation, szLightLocationIncrement, 7, nullptr);
      lstclAll->AddRange(m_aclSec);
      aclTemp = ClockLight::CreateLightArray(1, ptNextLocation, szLightLocationIncrement, -1, nullptr);
      lstclSeparators->AddRange(aclTemp);
      lstclAll->AddRange(aclTemp);
      m_acl10Sec = ClockLight::CreateLightArray(5, ptNextLocation, szLightLocationIncrement, 6, nullptr);
      lstclAll->AddRange(m_acl10Sec);
    There's still the tideosity (is this really an english word?) of assigning the control objects to the "what purpose is that for?" arrays, but the overall cut-down on manual effort was about factor seven. (The total count of these objects has increased to 62 in the meantime, BTW.)

    Eventually, the OP's scenario will likely result in programmatic creation of an array of EQ band (control) objects. ... at least I hope so... One secondary advantage that would have would be simplifying to make the total number of bands widely configurable.
    Last edited by Eri523; October 16th, 2012 at 07:43 PM.
    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.

  11. #11
    Join Date
    Jun 2012
    Posts
    37

    Re: A better way to write / read dozens of textboxes?

    And I tried to access the control in a different manner, referring to it as the element of the array instead of it's name, still I can't access the "value" property, but I can access other properties such as "visible" for example. Controls[8] is the NumericUpDown that I'm trying to change the value

    Name:  eqband1.png
Views: 235
Size:  16.0 KB

    I just don't understand why when accessing the control by its full name (directly) I get access to all of its properties, but when I access the same control by it's array position "Controls[8]" or from "ctlInner" I get access for SOME of its properties but not all of them...

  12. #12
    Join Date
    Jan 2010
    Posts
    1,102

    Re: A better way to write / read dozens of textboxes?

    Quote Originally Posted by Eri523 View Post
    Hi Cthulhu, long time no see!
    Hi Eri

    Quote Originally Posted by fernando306 View Post
    And I tried to access the control in a different manner, referring to it as the element of the array instead of it's name, still I can't access the "value" property, but I can access other properties such as "visible" for example.

    [...]

    I just don't understand why when accessing the control by its full name (directly) I get access to all of its properties, but when I access the same control by it's array position "Controls[8]" or from "ctlInner" I get access for SOME of its properties but not all of them...
    It's because when you use "Controls[i]" or "ctlInner" the type of the control is Control, which is at the root of the inheritance hierarchy for WinForms controls and even forms themselves. Basically, the variables you use are of a more abstract type - you just need to cast them back to their actual type. When you access the control "by its full name", the type of the variable is NumericUpDown, so you can access NumericUpDown-specific members. As you move up the inheritance chain, the representations become more and more abstract. A variable of type Control cannot access NumericUpDown-specific members since the variable might refer to anything that is a control, not only a NumericUpDown - it could be a TextBox, a Panel, a Label, a Form...
    However, you know what the actual type is, so you can do the cast.

    Now, in C# (which is the angle I'm coming from), you'd simply do:
    NumericUpDown nupdwn = (NumericUpDown)ctlInner;


    But, C-style casts are considered a no-no in C++ (without a particularly good reason if you ask me...), so use whatever casting operator is appropriate in the context of C++/CLI.

  13. #13
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,594

    Re: A better way to write / read dozens of textboxes?

    TheGreatCthulhu, basically the same idea behind our two posts (no surprise, though, as they're answering the same question), but yours (of which the notification arrived here while I was writing mine) is much more compact (as usual... ) and from a slightly different POV. Can only be helpful!

    Quote Originally Posted by TheGreatCthulhu View Post
    But, C-style casts are considered a no-no in C++ (without a particularly good reason if you ask me...) [...].
    I personally do use them, but rather rarely, and then mostly in the context of calls to native API functions. And the reason why I try to avoid them is not a "codiquette" one; it's because (at least to me) it's somewhat obscure what they actually do in C++[/CLI]: Depending on context, they sometimes behave like a static_cast and sometimes like a reinterpret_cast, and probably there are some more variants that don't come to mind now.

    Congrats to 1k posts, BTW!
    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.

  14. #14
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,594

    Re: A better way to write / read dozens of textboxes?

    Quote Originally Posted by fernando306 View Post
    I just don't understand why when accessing the control by its full name (directly) I get access to all of its properties, but when I access the same control by it's array position "Controls[8]" or from "ctlInner" I get access for SOME of its properties but not all of them...
    The reason for this is the fact that the items inside the controls collection are of type Control ^. All the Windows Forms control classes (including Form) are derived from that class, so they all are Control objects, just with some extras (the magic of polymorphism... ). And as what you get out of the controls collection is of type Control ^, initially you can just access the basic members of that class. So now the object you retrieved from the controls collection actually is of type NumericUpDown ^, just disguised as a Control ^. You do know that, but the compiler does not, so you need to tell it somehow, and that's done by casting.

    The idea of that is already visible in the last snippet in post #5, though admittedly not very obvious. The dynamic_cast returns an object of type GroupBox ^ if it succeeds, otherwise nullptr (i.e. the object passed in istn't actually a GroupBox). So I then could access GroupBox-specific members via gbx, I'm just not making use of that ability, merely using the cast to check the object's concrete type.

    There are three sorts of cast to choose from in such a scenario:
    • dynamic_cast, as already mentioned: Will return nullptr in case of failure. Specifically useful when you're not actually sure about the concrete type of the object you have.
    • safe_cast: Quite similar to the dynamic_cast but throws an InvalidCastException in case of failure. Most useful when you expect an object of a certain type but want to assert it. The difference may seem minor but is of great diagnostic value: safe_cast immediately throws an exception that clearly communicates what went wrong, while using a dynamic_cast the same way will result in a more general NullReferenceException being thrown when you try to use the returned handle, and that may be hundreds of code lines away from where the actuall error occurred. (The safe_cast has some more handy differences from the dynamic_cast but they're irrelevant in the context here, so I omit them for brevity.)
    • static_cast: Simply assumes that the object you're casting actually is of the type you're casting to. It will result in the all-time popular undefined behavior in case of failure. I have read somewhere that a failed static_cast may even destabilize the entire .NET runtime and the hosting OS (i.e. Windows), but I, personally, have only seen it crashing my own app with rather cryptic symptoms; bad enough, though. It's way faster than the other two, but that's only ever relevant in really performance-critical code, and that's why I practically never use it in GUI code nor recommend doing that.

    This snippet, adapted from you screen shot in post #10, illustrates that:

    Code:
    safe_cast<NumericUpDown ^>(gbx->Controls["Freq_OUT1_EQ" + x.ToString()])->Value = 1000;
    It also accuounts for that, though it's according to my own recommendations, what you're doing in the screenshot snippet is inefficient: If you only want do access a single control of which you know the complete name, a direct lookup in the controls collection is the way to go.
    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.

  15. #15
    Join Date
    Jun 2012
    Posts
    37

    Re: A better way to write / read dozens of textboxes?

    Hi Eri523 and TheGreatCthulhu!

    Thank you so much for your kind consideration helping me! Indeed it was the cast problem, I tested it and it works like a charm now! I am very pleased with your helpful posts and I appreciate that a lot. I'm new to C++ and Windows programming, I've been programing in C for embedded microcontrollers, so I'm still "getting used to it" Thanks to you I'm almost finished developing my Windows App and I understand things clearer now!

    Kind Regards,

    Fernando P.

Page 1 of 3 123 LastLast

Tags for this Thread

Posting Permissions

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


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center