Solved

Listbox not enabled

Posted on 2014-09-11
30
256 Views
Last Modified: 2014-09-19
Using Borland Builder C++: I have placed a listbox on in a Panel on my form, together with a button.

On startup the listbox appears, and functions as expected - ie I can make a selection and the button causes the appropriate code to execute. On startup, it's the only control I can use, but I don't want it yet.

But - I don't want the listbox at all on startup. I need it much later in the program. I don't know how to achieve this.

I tried setting the panel to not visible - so it's not there on startup - good. But when I try to use the panel/listbox later on, I can't make it function. I set the panel to visible - I can see it, but it's not populated with the text lines any more. And it doesn't have focus - doesn't respond to keyboard / mouse.

Help?
0
Comment
Question by:VaughanMx
  • 15
  • 13
  • 2
30 Comments
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
>>>But - I don't want the listbox at all on startup

so why create it on startup?

if you still need to create it then make it invisible in the first place.
Setting the parent panel to be invisible will control the visibility of all its children. Why don't you set just the listbox to be invisible on startup and perhaps the button as well.

later on check if the panel is visible and then turn on visibility for the Listbox
if( pPanel->Showing )
		pLstBox->Visible = True;

Open in new window


As for the listbox being disabled check its enabled property before starting any processing on it.

However to avoid all this I would suggest creating the Listbox only when necessary jit.
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
you can programmatically set focus on the listbox by calling the SetFocus() method on it. But first make sure its enabled.
0
 
LVL 32

Expert Comment

by:sarabande
Comment Utility
if the listbox should not show in the startup you may consider to using two forms, one for startup and one where the listbox functionality was needed. it normally is not a good design to show forms where only a few controls were visible but where the space for further controls was shown blank.

instead of switching visibility you may think of switching the 'Enabled' property (with pListBox->SetEnabled). if doing so, the listbox was grayed when it was inactive what might be a better design.

Sara
0
 

Author Comment

by:VaughanMx
Comment Utility
Firstly, I created the ListBox at Design time because I don't know how to create it at run time. Perhaps someone will help here?

Making the ListBox Visible only causes the panel / ListBox to show up on the screen at run time - but it is not populated with the strings which are placed there at Design time. On stepping through the program, Form1->ListBox1->Items->Strings[1]; does display the expected string value.

Enabled and Focused - doesn't improve the situation.

Is it necessary to invoke the ListBox by using a button event maybe?

I don't seem to be any further forward.
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
Form design should be COHESIVE. A form should have a DEFINITE purpose and functionality and all controls on the form should work towards achieving the purpose of the form.

It is poor design to create additional forms just because a control should not be visible at startup and then move out the control to a different form.

It is perfectly valid design to switch off the visibility of a control on a form or panel depending on runtime conditions IF the layout of the panel still has an ACCEPTABLE look and feel.


The listbox can be created at RUNTIME within the form's constructor . The below snippet is just sample code

TListBox* lstBox = new TListBox(this);
    lstBox->Parent = parentPanel;

Open in new window


You can add items at runtime as well. Sample snippet shown below :

lstBox->Items->Add("Experts");
lstBox->Items->Add("Exchange");

Open in new window


Take a look at this tutorial
http://www.functionx.com/bcb/classes/tlistbox.htm
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
so the TListBox class can be used to instantiate listboxes at runtime and the Add() method is used to add items dynamically.

Remember the listbox created within a function will be visible only within that function.
Quoting from the tutorial :
If you create the list box in a function, a method, or an event, the list will exist only inside of that function: you cannot manipulate it from another function, method, or event. If you want the control to be accessed by many functions declare a TListBox object in the header file of the form where the control will be hosted..

Look at the code snippet shown in that tutorial as to how to declare a listbox within a form class in a header file and then initializing the listbox in the form's constructor.
0
 

Author Comment

by:VaughanMx
Comment Utility
We're making progress...

I have now created a second ListBox within the original Panel, this time at runtime.

That's the good news.

The bad news is that all three (2 Listboxes, 1 button)  items are in effect greyed out when I get to see them after making the Panel Visible.

I have ensured that the Panel is Visible, Enabled, and has focus - to no avail.

And I'm very happy that the extra form solution can be discounted.
0
 

Author Comment

by:VaughanMx
Comment Utility
A MessageDialogue statement takes the user straight to a new window, where he is invited to contribute from keyboard or mouse.

I suppose I am looking for a comparable statement which will take the user to the Listbox. Does such a thing exist or am I completely on the wrong track here?
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
good to hear you've made progress.

>>>>I have ensured that the Panel is Visible, Enabled, and has focus - to no avail.
Have you enabled the listbox and buttons? There should be a property to enable just the listbox.

something like

yourButton->Enabled = True;
yourLstBox->Enabled = True;

Open in new window


if you want to play around with the properties create another sample project and draw a sample listbox using the designer statically, select it and scroll through all its properties in the properties window. I'm suggesting you do this only to learn the properties. Don't make this a part of the actual project you are working on.

Alternately send me the code and I can have a look
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
ensure the showing property of the panel returns true and you have actually enabled the panel

if( !yourPanel->Showing )
		yourPanel->Visible = True;

Open in new window


then also check the enabled property for the controls as shown in my previous post
0
 

Author Comment

by:VaughanMx
Comment Utility
Below is the subroutine referencing the panel, and two listboxes - one created at design time, and one created in the subroutine itself.

On stepping through the program, it is possible to confirm that both listboxes contain the expected strings.

I hope you can help?


int name_the_suit(int type, int x, int y)
{
   int i, n;
   TListBox *Listing;
   AnsiString *s[20];

  Listing = new TListBox(Form1->Panel2);
  Listing->Parent = Form1->Panel2;
  Listing->Left = 15;
  Listing->Top = 15;
  Listing->Items->Add("Spades");
  Listing->Items->Add("Hearts");
  Listing->Items->Add("Diamonds");
  Listing->Items->Add("Clubs");
  Listing->Items->Add("No Trumps");
  Listing->Enabled = true;

   Form1->Panel2->Visible = true;
   Form1->Panel2->Enabled = true;
   Form1->Panel2->SetFocus();
   Form1->ListBox1->Show();
   Form1->ListBox1->Enabled = true;
   Form1->ListBox1->SetFocus();

   Form1->ListBox1->Items->Strings[1];
   Listing->Items->Strings[1];
   Form1->ListBox1->Selected[1];
   {
      for(int i = 0;i < Form1->ListBox1->Items->Count; ++i)
      {
         if(Form1->ListBox1->Selected[i]);
//      Form1->Memo4->Lines->Add(Form1->ListBox1->Items->Strings[i]);
//         if(Form1->ListBox1->Selected[i]) s = Form1->ListBox1->Items->Strings[i];
      }
   }
   return(1);
}

Open in new window

0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
As you step through your code at which line do you see the greying out happen?

Also you will need to clean up the implementation. Remove the listbox which is not needed. You are creating one at runtime so why do need the static one?

Ideally you should define a class for the form and layout the controls you need there.
You are creating a listbox within a function, its not going to be visible anywhere else outside the function.

Did you read the link I mentioned in my previous post?
http://www.functionx.com/bcb/classes/tlistbox.htm

Search for the following line and change your code accordingly
"If you create the list box in a function, "
0
 

Author Comment

by:VaughanMx
Comment Utility
I don't anticipate requiring this listbox outside the current function.

At startup, the panel2 is visible, and the ListBox1 is visible, together with a Button. The button / listbox combination work as advertised.

The program calls several ShowMessage type dialogues which obviously change focus etc..., before getting to the 'name_the_suit' function. On entering the function the panel is still visible, and the strings are still showing in the listbox.

Then the function repositions the listbox (cosmetic, by resetting the Left & Top properties of the listbox), and the listbox appears only as a white shape. The button has the dotted line marker which usually means it is the selected control, but here it is over an empty shape of a button. (Empty meaning I see a part of a background image through button shape).

Does this help?
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
Form1->ListBox1->Items->Strings[1];
   Listing->Items->Strings[1];
   Form1->ListBox1->Selected[1];

Open in new window


the above lines server no purpose.

The first 2 are trying to capture the text but don't and the 3rd line returns a boolean which isn't used.

Also I thought you said you didn't want to use the static listbox created using the designer.

If you are down to just one listbox this is how it may be coded

int name_the_suit(int type, int x, int y)
{
   int i, n;
   TListBox *Listing;
   AnsiString *s[20];

  Listing = new TListBox(Form1->Panel2);
  Listing->Parent = Form1->Panel2;
  
  Listing->Left = 15;
  Listing->Top = 15;
  
  Listing->Items->Add("Spades");
  Listing->Items->Add("Hearts");
  Listing->Items->Add("Diamonds");
  Listing->Items->Add("Clubs");
  Listing->Items->Add("No Trumps");
  

  Form1->Panel2->Visible = true;
  Form1->Panel2->Enabled = true;   
  Listing->Enabled = true;

  return(1);
}

Open in new window

0
 

Author Comment

by:VaughanMx
Comment Utility
The (obscure, I admit) purpose of the purposeless lines of code above, enables me to see the strings which supposedly populate the listbox, when I step through the program.

I have used the code you propose - no errors - but lines 27 thru 31 do not display while stepping thru the code. And after the return statement, I can't access the listbox to select anything - not that I can see anything there to select!
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
and when a control is created it is by default enabled and visible. So when you create the listbox in the function it should be visible by default. The enabled and visible setting being done in the snippets are actually redundant if the panel has not been disabled.

Give my snippet a try. Its a pretty straightforward listbox creation, item add and display...I haven't tested it since I don't have BCB on hand but I hope it gives you some idea how to move ahead
0
 

Author Comment

by:VaughanMx
Comment Utility
Sorry - I was a bit premature there - the first step after return was as I described - but when I released the program (via F9)  the panel did display the strings.

Of course I haven't any longer got any code in there to select an entry, and use the information which it would provide. That code used to be in the name_the_suit function.
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
>>>>after the return statement, I can't access the listbox to select anything
that's why you need to create it in a class so that its accessible outside the function
0
 

Author Comment

by:VaughanMx
Comment Utility
I'll be back later!!!
0
 

Author Comment

by:VaughanMx
Comment Utility
OK - I have a nice display of the listbox including its contents.

The next thing the program does - many lines of coding later - is a ShowMessage box. I don't seem to have an opportunity to interact with my nice new listbox?

I have put the requested coding (TListBox *listing)  into Unit1.h, and left the actual creation of the listbox in my function. I hope that was right?
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
when the ShowMessage box takes focus, you can't obviously interact with the nice new listbox until you dismiss the message unless you want the message to always remain.

and name_the_suit() doesn't look like the member function of a class. Here a suggested layout for the code

this should be the header somefile.h

class MyUI:public TForm
{
   TListBox *Listing;

   public:
   MyUI(TComponent* Owner); //instantiate the Listbox in this constructor
   bool AddListItems();
   bool ProcessList();
   ....
   ....
   ....

};

extern PACKAGE TForm1 *Form1;

Open in new window


and this should be the implementation somefile.cpp

MyUI::MyUI(TComponent* tc)
:TForm(tc)
{
  Listing = new TListBox(Form1);
    Listing->Parent = Form1;
    Listing->Left = 120;
    Listing->Top = 80;
}

bool MyUI:: AddListItems()
{
  //logic to add list items to the listbox
}

bool MyUI::ProcessList
{
  //logic to select an item
 //logic to capture text
// etc etc
}

Open in new window

0
 

Author Comment

by:VaughanMx
Comment Utility
Firstly a big thank you for having got me this far.

name_the_suit() doesn't look like the member function of a class. - true - it's not.

I have tried  to include the code you have suggested.

I got
[C++ Error] card_top.h(991): E2303 Type name expected

I commented out
class MyUI   //:public TForm1

and that error cleared itself.
But was that the right thing to do?

Now I have something totally weird:-
[C++ Error] jpeg.hpp(23): E2040 Declaration terminated incorrectly

Thinking that maybe I had in some way changed something without realising, I downloaded a fresh copy of the jpeg.hpp file - same result. The two versions seem to be identical.

Have you any ideas about a way forward from here, please?
0
 

Author Comment

by:VaughanMx
Comment Utility
Update...
I had missed the semicolon at the end of the class declaration in the header file.

The jpeg.hpp mystery has now disappeared, thank goodness.

The only error being displayed now is E2113 Virtual function 'MyUI::MyUI(TComponent *)' conflicts with base class 'TForm'

That is on line 6 of your sample header file.
That's way beyond my limited experience to fix.
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
That just means the signatures don't match. from your comments I'm only grasping at straws since it appears you are using a whole lot more which could be indirectly affecting the compilation

my code was just a sample and its based on the link I pointed out to you but it isn't probably identical...so maybe I missed something

for a proper working example you will have to follow the example in the link I pointed you to and use the same implementation.
0
 

Author Comment

by:VaughanMx
Comment Utility
OK - everything you and the reference suggested seems to be working. Thank you.

But there's more. Maybe I should start a new question? I'll spell it out anyway...

From the start screen, a menu item takes me to a function, which takes me to another function, and on to a 3rd function: and that is where I want to offer the user the choices in the listbox.

If I get back to the start screen, via several 'return' statements, I can use the listbox. Then I have to get back up the functions tree to where I left off. This obviously is possible, but seems to be a bit uncouth. Surely there is a better way?

Despite much research on the net, I haven't found anyone discussing this issue, yet it must be quite a common requirement among programmers?
0
 
LVL 12

Accepted Solution

by:
trinitrotoluene earned 500 total points
Comment Utility
glad that it worked finally.
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
your next problem is a design question, not related to this issue. Design questions cannot be taken in isolation.

A complete picture of what you are doing is needed.
0
 

Author Closing Comment

by:VaughanMx
Comment Utility
You were very patient and helpful - thank you.
0
 
LVL 12

Expert Comment

by:trinitrotoluene
Comment Utility
you are welcome.
0
 
LVL 32

Expert Comment

by:sarabande
Comment Utility
From the start screen, a menu item takes me to a function, which takes me to another function, and on to a 3rd function: and that is where I want to offer the user the choices in the listbox.
the functionality you described is only a little part of the design a windows program and the framework provided by C++ Builder would require.

windows is a reactive system and each windows application - differently to a console application - responds to messages rather than performing a complete workflow from begin to end. after Windows called the 'main' function of your application, the main creates at least one window and then calls a function which is called message pump as it runs an (infinite) loop that reads messages from a queue and performs the actions associated to these messages. such a message pump looks like the following

while (GetMessage(...) != QuitMessage())
{
      TranslateMessage(...);
      DispatchMessage(...);
}

Open in new window

when the user clicks on the menu item you mentioned, such user action will cause some messages to be added to the message queue. those messages were read from queue and can be "translated" (for example some keyboard actions like control codes) in the TranslateMessage function and "handled" in the DispatchMessage function. in your case the function you have written was associated with the menu item and was called by the framework as response to the user click. your code then created a listbox and added some string items to it. all these actions were pushing messages to the message queue and either were handled directly or asynchronously by the message loop after you returned from your function. because of that, you need not to "go back" to your function to handle user selection of a listbox item but you have to provide a new function - like the one you provided to handle the click on the menu item - to handle a user's selection of a listbox item.

in order to get an understandings of that, I strongly recommend you to learn the basics with a tutorial which you easily could find.

Sara
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

I annotated my article on ransomware somewhat extensively, but I keep adding new references and wanted to put a link to the reference library.  Despite all the reference tools I have on hand, it was not easy to find a way to do this easily. I finall…
I previously wrote an article addressing the use of UBCD4WIN and SARDU. All are great, but I have always been an advocate of SARDU. Recently it was suggested that I go back and take a look at Easy2Boot in comparison.
Video by: Tony
This video teaches viewers how to export a project from Adobe Premiere Pro and the various file types involved.
An overview on how to enroll an hourly employee into the employee database and how to give them access into the clock in terminal.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now