In this example N is the number of controls you want on the dialog.
#AutoDefine "off"
const N = 12; // change this and recompile
class VariableDialog:CDialog
{
}
sub main()
{
VariableDialog dlg;
int w = 870; // width of dialog
int h = 198 + 163*((N-1)/3); // height of dialog
dlg.Create(0,0,w,h,0x80CA0080,0,"test",0);
for(int i = 0; i < N; i++)
{
int x = 55 + 266*(i%3);
int y = 35 + 163*(i/3);
dlg.AddControl(CTGROUPBOX,"Box " + NumToStr(i+1),x,y,228,112,0x50000007,0x0,i+3);
}
dlg.DoModal();
return 0;
}
Very interesting code Bruce!
thank you for sharing.
I wonder if it is possible to add an image in the boxes created.
In fact i would like to know if it is possible to load pictures in a control window.
cheers!
Very nice example Bruce. :)
It also works using an INT variable. If a select/case was added you could probably vary the type of controls as well.
// Variable Controls - change the value for N
// VariableControls.src
// by peaslee
#AutoDefine "off"
class VariableDialog:CDialog
{
}
sub main()
{
int N = 9; // change this and recompile
VariableDialog dlg;
int w = 870; // width of dialog
int h = 198 + 163*( ( N - 1 ) / 3 ); // height of dialog
dlg.Create(0,0,w,h,0x80CA0080,0,"test",0);
for(int i = 0; i < N; i++)
{
int x = 55 + 266*(i%3);
int y = 35 + 163*(i/3);
dlg.AddControl( CTGROUPBOX, "Box " + NumToStr(i+1),
x, y, 228, 112, 0x50000007, 0x0, i+3);
}
dlg.DoModal();
return 0;
}
It would seem that anything you can add to a dialog can be added in this manner.
This is only a shell. My project will have check boxes in each group box and OK and CANCEL buttons at the bottom. The only tricky part is keeping track of the control ID numbers, necessary of course for getting data from the dialog, but it is certainly possible.
If you don't know at run time how many controls you have, how do you read them?
Here's one way, where the controls' IDs are computed the same way they were when the control was created.
select true
{
case *(CButton)GetControl(nCtrl*10 + 1).GetCheck():
sMSG("Present"); // sMSG() is a quick message box for debugging/testing
case *(CButton)GetControl(nCtrl*10 + 2).GetCheck():
sMSG("Absent");
case *(CButton)GetControl(nCtrl*10 + 3).GetCheck():
sMSG("Excused");
}
The check boxes are in a group so only one can return true.
It was a thread with Paul and Parker that suggested this technique.
I've added the ability to add or delete people from my project which increases or decreases the number of controls.
After adjusting the number of people, I call again the method that creates the dialog. I added this:
if(m_dlgAttendance.m_pDlgTemplate <> null)
Delete m_dlgAttendance.m_pDlgTemplate;
...
m_dlgAttendance.Create(...);
It appears to work. Is this the correct way?
No ;) That would result in huge memory leaks.
Open up the Aurora source archive and study dialog_instance.src, specifically what the destructor does. There is a list of control pointer, dynamically allocated title strings, etc that have to be accounted for.
You could just take CDialog::_CDialog() and make your own method out of it like FreeDialog or something.
Paul.
"Look before you leak" is always good advice. :D
Actually, I did examine dialog_instance.src, where I got the idea for the above code. Taking only one piece of the destructor didn't feel right, so I thought I better ask.
Thanks.
Quote from: Paul Turley on May 07, 2007, 08:55:52 PM
You could just take CDialog::_CDialog() and make your own method out of it like FreeDialog or something.
Done. And it works fine.
Thanks again.