I want to check all checkboxes when click on the button. All object are in form application of visual studio 2010 c++. The point of problem is that every object (checkbox) has various name, CheckBox1, CheckBox2, ... I make UnicodeString with value "CheckBox", and int value that begin with 1, and put it together in third variable to find object, and that's work, but don't have a clue how to check all those boxes, please help.
Windows 7, 64, Visual studio 2010(c++) or c++ builder 2010
I did something similar for another component, this is how I did using C++ Builder.
for (int i = 0; i < this->ComponentCount; i++)
{
TCheckBox *TempCheckBox = dynamic_cast<TCheckBox *>(this->Components[i]);
if (TempCheckBox)
{
TempCheckBox->Checked = true;
}
}
This will iterate through all the components on your form, if the component is a TCheckBox it will be checked.
Why dont you add everything to a vector containing checkboxes, and then iterate through them all when necessary? This will allow you to reference each checkbox individually, but yet all at once.
cliext::vector<System::Windows::Forms::CheckBox^> items;
items.push_back(checkbox1);
.
.
.
items.push_back(checkboxN);
It is important that you also include
#include <cliext/vector>
due to the fact that the normal vector in the standard library is currently unable to support this control.
In C++Builder, you can place all of your TCheckBox* pointers into an array or std::vector, which you can then loop through when needed, eg:
TCheckBox* cb[10];
__fastcall TForm1::TForm1(TComponent *Owner)
: TForm(Owner)
{
cb[0] = CheckBox1;
cb[1] = CheckBox2;
...
cb[9] = CheckBox10;
}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
for (int i = 0; i < 10; ++i)
cb[i]->Checked = true;
}
If you have a lot of checkboxes and do not want to fill in the entire array by hand, you can use a loop instead:
__fastcall TForm1::TForm1(TComponent *Owner)
: TForm(Owner)
{
for (int i = 0; i < 10; ++i)
cb[i] = (TCheckBox*) FindComponent("CheckBox" + IntToStr(i+1));
}
Related
I am making tic tac toe game on the visual studio window form with c++.
How can I convert this C# code to C++ code?
private Void disableButtons()
{
try
{
foreach (Control c in Controls)
{
Button b = (Button)c;
b.Enabled = false;
}
}
catch{ }
}
You cannot convert it into pure C++ code without using any additional libraries that have classes Control and Button with Button class having an "Enabled" public member.
You can however convert it to C++/CLI code where you can mix pure C++ code too.
private Void disableButtons()
{
try
{
for each (Control^ c in Controls)
{
Button^ b = (Button^)c;
b->Enabled = false;
}
}
catch{ }
}
Here is an example on how to use the foreach of C# in c++:
#include <iostream>
int main()
{
const int SIZE = 3;
int myArray[SIZE] = { 1, 2, 3 };
for (int & i : myArray) // make sure to put the &
{
i = i + 10;
}
for (int i = 0; i < SIZE; i++)
{
std::cout << myArray[i] << std::endl;
}
return 0;
}
The syntax should be like this:
for(type name : collection) { // your code here }
and you can put & between type and name if you want to change the original elements
for(type & name : collection) { // your code here }
You've tagged this Visual C++ so I'm presuming you're using MFC. The answer would be different if you're using Qt or wxWidgets or something else.
If you already have the control ID's in a container that you want to for-each on, then:
UINT Controls[] = { IDC_BUTTON1, IDC_BUTTON2, IDC_BUTTON3, IDC_BUTTON4, IDC_BUTTON5 };
for (UINT c : Controls)
{
CWnd *b = GetDlgItem(c);
if (b)
b->EnableWindow(FALSE);
}
If however you don't have such a container of controls but somehow want to still iterate all the controls then:
CWnd *c = GetWindow(GW_CHILD);
while (c)
{
c->EnableWindow(FALSE);
c = c->GetNextWindow(GW_HWNDNEXT);
}
I recommend the first option because then you can be specific about which controls you want to modify. The second option will be tricky if you only want buttons.
I want to fill a form at runtime with a lot of comboboxes with identical lists. They also get the same event handler, which is acting depending on the Sender objects's Name. However, this takes a pretty long time and I was guessing I do something wrong.
I'm using XE2 Rad Studio C++ Builder and the VCL GUI.
Edit: Those boxes contain a different kinds of content and are distributed over a few tabPages within the form. however, it's necessary to display what it selected at at least 80 of them at a glance. Would it maybe be better to replace them with TLabels and create a TCombobox when clicking on the TLabel to select a different element?
The Code looks similar to this:
void __fastcall TForm::TForm(){
int i=0;
TStringList* targetlist = new TStringList();
targetlist->Add("Normal");
targetlist->Add("Inverted");
Vcl::Stdctrls::TComboBox **com = new Vcl::Stdctrls::TComboBox[512];
for(i=0;i<512;++i){
com[i]=new Vcl::Stdctrls::TComboBox(this);
com[i]->Parent=this;
com[i]->Name.printf(L"Combo_%d", i);
com[i]->SetBounds(10, 198 + 20 * i, 130, 200);
com[i]->Items = targetlist;
com[i]->ItemIndex = 0;
com[i]->Style = csDropDownList;
com[i]->OnChange = MyComboTriggerChange;
}
}
One iteration seems to take around 20ms on my machine (testedt with std::clock), which make this part ~10s long. The pointers are deleted at the form's destruction. I just put their declarations here for simplifications.
Is there a better way to create multiple comboboxes? Maybe clone them?
You seriously need to redesign your UI. Using 512 TComboBox controls on one screen with the same list of values makes no logical sense, and is a waste of time and resources. There are better ways to display 512 strings on a screen, such as a TListView in report mode, or a TListBox (both of them support a virtual mode so they can share common data without wasting memory). Or use a TValueListEditor or TStringGrid with an esPickList inline editor. Or, if you are really adventurous, write a custom control from scratch so you use 1 efficient control instead of 512 separate controls. Anything is better than 512 TComboBox controls.
That being said, TComboBox does not support a virtual mode, like TListBox and TListView do, but there are a couple of optimizations you can still make to speed up your TComboBoxes a little:
don't make 512 copies of the same TStringList content. Anything you add to the TComboBox::Items is stored inside the TComboBox's memory. You should strive to reuse your single TStringList and let everything delegate to it as needed. In this case, you can set the TComboBox::Style property to csOwnerDrawFixed and use the TComboBox::OnDrawItem event to draw the TStringList strings on-demand. You still need to add strings to each TComboBox, but they can be empty strings, at least.
subclass TComboBox to override its virtual CreateParams() method and it remove the CBS_HASSTRINGS window style, then the TComboBox does not actually need to store empty strings in its memory.
Try something like this:
class TMyComboBox : public Vcl::Stdctrls::TComboBox
{
typedef Vcl::Stdctrls::TComboBox inherited;
private:
TStrings *fSharedItems;
void __fastcall SetSharedItems(TStrings *Values)
{
if (fSharedItems != Values)
{
fSharedItems = Values;
Items->BeginUpdate();
try
{
Items->Clear();
if (fSharedItems)
{
for (int i = 0; i < fSharedItems->Count; ++i)
Items->Add(L"");
}
}
__finally
{
Items->EndUpdate();
}
}
}
protected:
virtual void __fastcall CreateParams(TCreateParams &Params)
{
inherited::CreateParams(Params);
Params.Style &= ~CBS_HASSTRINGS;
}
virtual __fastcall DrawItem(int Index, TRect Rect, TOwnerDrawState State)
{
// draw the items however you want...
if (fSharedItems)
Canvas->TextRect(Rect.Left, Rect.Top, fSharedItems->Strings[Index]);
}
public:
__fastcall TMyComboBox(TComponent *Owner)
: Vcl::Stdctrls::TComboBox(Owner)
{
Style = csOwnerDrawFixed;
}
__property TStrings* SharedItems = {read=fSharedItems, write=SetSharedItems};
};
class TMyForm : public TForm
{
...
private:
TStringList* targetlist;
TMyComboBox **com;
void __fastcall MyComboTriggerChange(TObject *Sender);
...
public:
__fastcall TMyForm(TComponent *Owner);
__fastcall ~TMyForm();
...
};
__fastcall TMyForm::TMyForm(TComponent *Owner)
: TForm(Owner)
{
targetlist = new TStringList;
targetlist->Add("Normal");
targetlist->Add("Inverted");
com = new TMyComboBox*[512];
for(int i=0;i<512;++i)
{
com[i] = new TMyComboBox(this);
com[i]->Parent = this;
com[i]->Name = String().sprintf(L"Combo_%d", i);
com[i]->SetBounds(10, 198 + 20 * i, 130, 200);
com[i]->SharedItems = targetlist;
com[i]->ItemIndex = 0;
com[i]->OnChange = &MyComboTriggerChange;
}
}
__fastcall TMyForm::~TMyForm()
{
delete targetlist;
delete[] com;
}
void __fastcall TMyForm::MyComboTriggerChange(TObject *Sender)
{
TMyComboBox *cb = static_cast<TMyComboBox*>(Sender);
// use targetlist->Strings[cb->ItemIndex] as needed...
}
I wanted to call function by choosing line from ComboBox, but I don't know how to write it properly
void __fastcall TForm1::ComboBox1Change(TObject *Sender) {
if (ComboBox1.Lines.Count == 1) {
mode = 1;
}
else if (ComboBox1.Lines.Count == 2) {
mode = 0;
}
Check value of ComboBox::SelectedIndex property if it is Visual C++.
Check value of TComboBox::ItemIndex field if it is Embarcadero C++ Builder.
Depending on the value of this property take appropriate action.
So I have reached my ceiling of knowledge when it comes to Qt and C++ in general I guess. I am creating check boxes in a QScrollArea based off the input from a QComboBox. Depending on the value selected in the QComboBox, a specific number of check boxes are created. Once I created those check boxes, I am having a problem understanding how to interact (in my case, simply check to see if they are checked or not) with them outside of the function they are being created and called in. I know how to work with them if the buttons were static, but since the check boxes are dynamic (is that the right word?) and can change, I don't know what to do. Below is a little snippet of code on how the check boxes are created. If I now want to simply check if any of the boxes are checked, how do I do that. Can I "return" or "call" the created check boxes in another function somehow? I know I'll simply need to loop through the array and check, I just simply don't know how to get the array of check boxes into another function or how to return them in the function below.
Thanks for the help!
void MyProgram::create_checkboxes(QString opnum)
{
QWidget* MDAcheckboxes = new QWidget(ui->MDA);
QVBoxLayout* MDAlayout = new QVBoxLayout(MDAcheckboxes);
QCheckBox *MDAmycheckBox[9];
QList<QString> boxes;
if (opnum == "640")
{
boxes << "16-1" << "16-2";
for (int i = 0; i < 2; i++)
{
MDAmycheckBox[i] = new QCheckBox(MDAcheckboxes);
MDAmycheckBox[i]->setText(boxes[i]);
MDAlayout->addWidget(MDAmycheckBox[i]);
}
ui->MDA->setWidget(MDAcheckboxes);
}
else if (opnum == "645")
{
boxes << "13-01"<<"13-2"<<"13-3"<<"13-4"<<"13-5";
for (int i = 0; i < 5; i++)
{
MDAmycheckBox[i] = new QCheckBox(MDAcheckboxes);
MDAmycheckBox[i]->setText(boxes[i]);
MDAlayout->addWidget(MDAmycheckBox[i]);
}
ui->MDA->setWidget(MDAcheckboxes);
}
else if (opnum == "650")
{
boxes << "13-6"<<"13-7"<<"13-8"<<"13-9"<<"13-10"<<"13-11"<<"13-12"<<"13-13"<<"13-14";
for (int i = 0; i < 9; i++)
{
MDAmycheckBox[i] = new QCheckBox(MDAcheckboxes);
MDAmycheckBox[i]->setText(boxes[i]);
MDAlayout->addWidget(MDAmycheckBox[i]);
}
ui->MDA->setWidget(MDAcheckboxes);
}
}
All your checkBoxes should have a parent. In this case you will be able to find it with findChildren. It also can be done without groupBox if you sure that app has no any other checkboxes and findChildren will not return you checkboxes which you don't need.
Try this:
QList<QCheckBox *> allButtons = ui->groupBox->findChildren<QCheckBox *>();
qDebug() <<allButtons.size();
for(int i = 0; i < allButtons.size(); ++i)
{
if(allButtons.at(i)->isChecked())
qDebug() << "Use" << allButtons.at(i)->text()<< i;//or what you need
}
In general case:
QList<QCheckBox*> allButtons = parentOfCheckBoxes->findChildren<QCheckBox *>();
Moreover findChildren allows you to find children with special objectName which can be useful in some cases. Note that you can set the same objectName to the different objects.
http://qt-project.org/doc/qt-5/qobject.html#findChildren
Trying to write a simple VCL program for educating purposes (dynamicly created forms, controls etc). Have such a sample code:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TForm* formQuiz = new TForm(this);
formQuiz->BorderIcons = TBorderIcons() << biSystemMenu >> biMinimize >> biMaximize;
formQuiz->Position = TPosition::poDesktopCenter;
formQuiz->Width = 250;
formQuiz->Height = 250;
formQuiz->Visible = true;
TButton* btnDecToBin = new TButton(formQuiz);
btnDecToBin->Parent = formQuiz;
btnDecToBin->Left = 88;
btnDecToBin->Top = 28;
btnDecToBin->Caption = "Dec to Bin";
btnDecToBin->Visible = true;
}
I wonder how can i write a function for dynamic created button, so it would be called when the button is clicked. In this example i need a 'btnDecToBin->Click();' func but i don't know where should i place it.
Inside 'void __fastcall TForm1::Button1Click(TObject *Sender){}' ?
I will appreciate any input, some keywords for google too.
You could do two things, you could either create an action and associate it with the button, or you could make a function like so:
void __fastcall TForm1::DynButtonClick(TObject *Sender)
{
// Find out which button was pressed:
TButton *btn = dynamic_cast<TButton *>(Sender);
if (btn)
{
// Do action here with button (btn).
}
}
You bind it to the button instance by setting the OnClick property btnDecToBin->OnClick = DynButtonClick please note that the function is inside the form Form1. This will work due to the nature of closures (compiler specific addition). The problem comes if you delete Form1 before formQuiz without removing the reference to the click event. In many ways it might be a more clean solution to use an Action in this case.
Edit: On other way to do this, if you have a standard layout for your quizforms, you could make a custom TQuizForm class inheriting from TForm. In this way you wouldn't have to bind the event each time you create the form.
all buttons have the normal "events" you just need to reference them to the method you will deal with the event.
example:
...
btnDecToBin->OnClick = &Test;
-- and add a additional method to .cpp
void __fastcall TForm1::Test(TObject *Sender)
{
TButton *btn = dynamic_cast<TButton *>(Sender);
if (btn->name == "your_button_name"){
// Do action here with button (btn).
}
}
and on .h
void __fastcall TForm1::Test(TObject *Sender);
reference the button either by the tag or name. I usually use a array of buttons that I create dynamically. ALWAYS sanity check your "sender" by casting it. There are other ways to hack info from the object but they are a path to heartache... LOL.