|


Dynamic Dialog class
These classes are being used for displaying a modal/modelles dialog, on which
the controls are dynamically added, without the need of having a dialog
template as resource. These classes were developed as base classes for use
in a script parser, where users can build there own dialogs, using a
VB-script alike language. So basically there can be any number of controls
on the dialog, at any place on the dialog.
Global structure of the CDynDialogEx class:
- class is derived of
CDialog
- in the class there is an array of
CDynDialogItemEx
pointers, the dialog controls
- class includes
DoDataExchange() function.
- add controls to dialog through function
AddDlgControl()
Global structure of the CDynDialogItemEx class:
- class is derived of
CWnd
- holds the data of the control that was added to the dialog, like the
caption, the rectangle, etc.
- creates the controls on the dialog
Small piece of sample code on how to use the classesvoid CTestDynDialogDlg::OnButton1();
{
int nRadio1 = 0;
CRect rect(10,5,60,19);
CDynDialogEx dlg(this);
dlg.SetWindowTitle(_T("Dynamic Dialog : WindowTitle....."));
dlg.AddDlgControl(_T("BUTTON"),
_T("Press me!"),
STYLE_BUTTON,
EXSTYLE_BUTTON,
&rect,
NULL,
IDC_DYN_BUTTON);
dlg.AddDlgControl(_T("BUTTON"), _T("Radio1Caption 1"),
STYLE_RADIO_GROUP, EXSTYLE_RADIO, NULL, (void*)&nRadio1);
dlg.AddDlgControl(_T("BUTTON"), _T("Radio1Caption 2"),
STYLE_RADIO, EXSTYLE_RADIO);
dlg.DoModal()
}
Working explained
CDynDialogEx::AddDlgControl() function creates new
object of class CDynDialogItemEx and adds it to the array
of controls. Function also checks/sets the size of the dialog, so the
control is seen on the dialog.
CDynDialogEx::DoModal() function initializes the
DLGTEMPLATE structure using the selected font and calls
CDialog::InitModalIndirect() for modal dialogs or
CDialog::CreateIndirect() for modless dialogs
CDynDialogEx::OnCreate() function creates all the
controls on the dialog
CDynDialogItemEx::CreateEx() does nothing (ActiveX controls)
or creates the window
CDynDialogEx::OnInitDialog() function repositions
all the controls on the dialog or creates the ActiveX controls
CDynDialogItemEx::SetWindowPos() function converts from
dialog units to screen units and creates ActiveX control
Update 18-06-2002
- Class
CDynDialogItemEx now derived from CWnd instead of heaving a CWnd member
- Added modless gialog possibility as supposed by CodeBuddy. (
CDynDialogEx::SetUseModeless())
- Added subclassed controls, because I needed them. After adding the control you can use
SubclassDlgItem with the Control_ID returned by calling
CDynDialogEx::AddSubclassedDlgControl()
- Improved
DDX_Control support for dialog items
- Added partial ActiveX controls support. Partial because the controls are created, but there is
no support for the EVENT_SINK! But there is code for creating licensed controls dynamicly.
- Added examples for modeless dialog, adding and filling a CListbox,
an ActiveX control on a dialog
Tip!
Possible extensions:
- improving ActiveX controls support, specially EVENT_SINK related
- adding Menus dynamically to the dialog
- ...
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 45 (Total in Forum: 45) (Refresh) | FirstPrevNext |
|
|
 |
|
|
I've posted info about another kind of dynamic dialog that can complement this one. Here are some links:
http://sourceforge.net/projects/dyndlgdemo[^]
http://en.wikipedia.org/wiki/Differential_Execution#Dynamic_Dialog[^]
The basic idea is that you write a method (deContents) to create the controls you want in the dialog as a function of the current state of application data. Once you have done that, you're done. That function is executed via a function (Run), and each time it is run it determines what is different and only updates what is necessary. There is no need to store the controls in instance variables because you don't have to send them messages. There is no need to write event handler functions because the controls themselves update the application data. Code to respond to button presses is written immediately adjacent to the button control itself. If whole blocks of controls are to appear conditionally on the state of the application data, that is easily expressed with IF, FOR, and other conditional statements in the procedure.
It is based on a simple control structure called differential execution. The idea is that, as the deContents procedure runs, it simultaneously serializes its state and deserializes its prior state, using the difference between the two to incrementally update the controls in the dialog, all of which happens very quickly.
The overall result is that complex dialogs can be written with an order of magnitude less source code than by the usual event-driven means. The example given on sourceforge uses about 40 lines of C++ code to edit a variable list of employees. It takes several hundred lines by the usual methods.
-- modified at 9:16 Saturday 24th November, 2007
MikeDunlavey
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I created a new dialog class using an existing dialog class as its base class. This base class has no button resource. I want to add a button resource to the dialog. Modifying the base class is not allowed. I was able to add and display the button. However, I can't detect the button click event. Is there a way to detect the button click event from the new dialog class?
I have already tried adding a message map and it didn't work. I have also tried the OnCommand function and it also didn't work.
Hope you can help me with my problem.
Best regards, Odette
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
salu2. . . bueno me parece muy bueno tu programa pero tengo una duda muy grande.. pues tu estas creando los dialogos dinamicos que tienen como padre tu vntana principal . . . como hago para crearlo directamente si tengo un proycto creado sin el wizard y x lo tnto no tngo rc. . . y mi padre es una clase derivada de CFrameWnd. . . me gustaria un ejemplo simple de como crear un objeto derivado de la clase CDialog sin el Wizard . . . Gracias
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Utiliza el Servicio de Traducción Automática del Instituto Cervantes (http://oesi.cervantes.es/traduccionAutomatica.html)
salu2.. . good your program seems very good to me but I have a very great doubt. then your these creating the dinamicos dialogos that have like father your main vntana. . . since I make to create it directly if I have proycto created without wizard and x tnto not tngo rc.. . and my father is a class derived from CFrameWnd.. . gustaria me a simple example of like creating an object derived from the CDialog class without the Wizard. . . Thanks
Y luego, acaba de 'pulir' la traducción.
Antes deberás pasar tu texto por un corrector ortográfico: salu2 dinamicos dialogos vntana proycto tnto tngo gustaria
Y también, no escribir tus mensajes desde el móvil.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Is it possible to add a new control to an existing dialog? I would like to set an instance of CDynDialogEx do an existing dialog, and after call the AddDlgControl(_T("BUTTON")...
thank you.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
No, you cannot attach a existing dialog to the <b>Dynamic Dialog Class</b>. You 'd better create and positon the control yourself. And handle the Command for the button
In header of Dialog class <code>CButton m_ButtonToAdd</code>
In cpp of Dialog class in ::OnInitDialog() <code>//Add button GetDlgItem(IDOK)->GetWindowRect(&rect); //Get position of OK button ScreenToClient(&rect);
GetClientRect(rectWnd); rect.MoveToX(rectWnd.left + 7); rect.MoveToY(rect.top);
m_ButtonToAdd.Create(_T("ButtonText"), WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, rect, this, <b>IDD_BUTTONTOADD</b> ; m_ButtonToAdd.SetFont(GetFont()); </code>
In cpp of Dialog class in ::OnCommand(WPARAM wParam, LPARAM lParam) <code> //wParam //The low-order word of wParam identifies the command ID of the menu item, control, or accelerator. //The high-order word of wParam specifies the notification message if the message is from a control. //If the message is from an accelerator, the high-order word is 1. //If the message is from a menu, the high-order word is 0.
//lParam //Identifies the control that sends the message if the message is from a control. Otherwise, lParam is 0.
WORD wControlID = LOWORD(wParam); WORD wMessageID = HIWORD(wParam); if (wControlID == <b>IDD_BUTTONTOADD</b> { switch(wMessageID) { default: OnButtonToAdd(); break; } return TRUE; }</code>
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Can I add a button on the dialog box with Caption 'Dynamic dialog : Window Title........ by clicking on the button on the same dialog box with the caption 'Press me!'
dd
-- modified at 4:59 Thursday 6th April, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
No, you can't. You will have to add the control befor calling DoModal(). It could be invisable when you add the control to the dialog and in the event handler of the button you can than make it visible.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi, for those who are using a non-modal dialog, and neither the DoDataExchange function here is my solution. I am using controls inside a Dockable controlbar, and I had the problem i didn't receive any kind of message from OnCommand when the user clicks over the Spinner button arrows. That's because that message is received from OnNotify, wich is not added in CDynDialogEx...
BOOL CDynDialogEx::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) { //if we have a parent send the message to the parent, so we can handle the message over there. WORD wControlID = LOWORD(wParam);
if (wControlID != 0) { if (m_pParentWnd != NULL) { ::SendMessage(m_pParentWnd->GetSafeHwnd(), WM_NOTIFY, wParam, lParam); } }
return CDialog::OnNotify(wParam, lParam, pResult); }
If you have any better solution, please let me know. BYE!!!
// Savior
-- modified at 19:25 Tuesday 28th February, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Everything is great but I found on bug.
Click on the "Create modeless dialog" button and click on "Press me" button message box will be displayed and click "OK". Now close the modeless dialog by clicking Close ("X") at the right top. The main dialog will minimize!
If you have a solution for this, then it will be of greate help to many.
Thanks Murthy
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Try it:
A) Use MessageBox instead of AfxMessageBox
or
B) Before the AfxMessageBox do SetActiveWindow().
Don't ask me about an explanation about it.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Did you ever find out how to add items to the combo box??? I'm hoping to do the same, but there isn't anything which indicates how to deal with the Combo box after you create it.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
Following the example provided for a list control (and changing things for a combo box) is okay if you know in advance how many such controls you wish to appear on your dialog box, and this number of list boxes is invariant. I use Marcel's stuff to generate dialogs with from 0 (zero) to whatever number of combo box's on it. So extending CDynDialogEx is not much use as I don't know in advance how many combo boxes I need. So to get around this I just add the combo boxes to the CDynDialogEx dialog as I need them (as shown in the CTestDynDialogDlg::OnButton2 example - but I include an extra parameter at the end which is a pointer to a CList object.....
First I changed the following bits of code:-
DynDialogEx.h
virtual UINT AddDlgControl(DLGITEMTEMPLATECONTROLS TypeControl, LPCTSTR lpszCaption, DWORD dwStyle, DWORD dwExtendedStyle, LPRECT pRect = NULL, void *pData = NULL, UINT nID = 0, void *pData2 = 0);
virtual UINT AddDlgControl(LPCSTR lpszClassName, LPCTSTR lpszCaption, DWORD dwStyle, DWORD dwExtendedStyle, LPRECT pRect = NULL, void *pData = NULL, UINT nID = 0, void *pData2 = 0);
virtual UINT AddSubclassedDlgControl(LPCSTR lpszClassName, LPCTSTR lpszCaption, DWORD dwStyle, DWORD dwExtendedStyle, LPRECT pRect = NULL, UINT nID = 0, void *pData2 = 0);
and its implementation in DynDialogEx.cpp, for the 3 respective functions change their function definitions and then the 3 appropriate lines to be as follows....
nRet = pDynDialogItemEx->InitDialogItem(TypeControl, dwStyle, dwExtendedStyle, pRect, lpszCaption, nID, FALSE, pData, pData2);
nRet = pDynDialogItemEx->InitDialogItem(lpszClassName, dwStyle, dwExtendedStyle, pRect, lpszCaption, nID, FALSE, pData, pData2);
nRet = pDynDialogItemEx->InitDialogItem(lpszClassName, dwStyle, dwExtendedStyle, pRect, lpszCaption, nID, TRUE, NULL, pData2);
DynDialogItemEx.h Add a new member variable...
void *m_pData2;
and modify the 2 InitDialogItem function definitions....
UINT InitDialogItem(DLGITEMTEMPLATECONTROLS TypeControl, DWORD dwStyle, DWORD dwExtendedStyle, LPRECT pRect, LPCTSTR lpszCaption, UINT nID = 0, BOOL bSubclassed = FALSE, void *pData = NULL, void *pData2 = NULL);
UINT InitDialogItem(LPCSTR lpszClassName, DWORD dwStyle, DWORD dwExtendedStyle, LPRECT pRect, LPCTSTR lpszCaption, UINT nID = 0, BOOL bSubclassed = FALSE, void *pData = NULL, void *pData2 = NULL);
In the corresponding implementation file DynDialogItemEx.cpp ensure that the function definitions match what you have just changed in the header file and add the following line to each function after the m_pData = pData; line....
m_pData2 = pData2;
Add some extra stuff in CDynDialogItemEx::DoDataExchange to populate the combobox with whatever is in m_pData2....
.. . . CWnd::DoDataExchange(pDX); if(m_pData2 != NULL) { switch(m_eTypeControl) { case COMBOBOX: { // m_pData2, it it's valid, points to a list of CString * CList *pListComboData = (CList *)m_pData2; POSITION posComboData = pListComboData->GetHeadPosition(); while(posComboData) { ((CComboBox *)this)->AddString(*pListComboData->GetNext(posComboData)); } break; } default: break; } }
Okay, that's the original code updated, now to make use of it.
// For each combo box added, keep a note of the list created to hold the list of strings added to this list (so that it and its contents can be deallocated after use). CList<CList<CString *, CString *> *, CList<CString *, CString *> *> listComboBoxStringLists;
// I will add just one combo box for this example, although this would ordinarily // be enclosed in some sort of decision-loop adding any number of combo-boxes.... CList<CString *, CString *> *pListComboBoxStrings = new CList<CString *, CString *>;
// Add some strings to this combo box. Again this would normally be a varying // number of strings, different for each combo box. CString *pNewString1 = new CString(_T("String 1")); CString *pNewString2 = new CString(_T("String 2")); pListComboBoxStrings.AddTail(pNewString1); pListComboBoxStrings.AddTail(pNewString2);
// And add the whole list to our list of lists so we can remove it after // closing the dialog.... listComboBoxStringLists.AddTail(pListComboBoxStrings);
dlg.AddDlgControl(_T("COMBOBOX"), _T(""), STYLE_COMBOBOX_DROPDOWN, EXSTYLE_COMBOBOX, NULL, NULL, 0, pListComboBoxStrings);
.. . // Open the dialog and once closed do whatever with the results.....I have not implemented this bit yet but Marcel's code shows how to do this. int nEditRtn = dlg.DoModal(); if(nEditRtn == IDOK) { }
// And finally deallocate all the allocated memory POSITION posCStringList = listComboBoxStringLists.GetHeadPosition(); while(posCStringList) { CList<CString *, CString *> *pListList = listComboBoxStringLists.GetNext(posCStringList); POSITION posCString = pListList->GetHeadPosition(); while(posCString) { delete pListList->GetNext(posCString); } delete pListList; }
------------------------------------------------------------------ I'm sorry this is so complicated but this is the only way I could come up with to achieve having a variable number of combo boxes on a dialog, and being able to add strings to the list.
There are bound to be syntax errors in this code, so please let me (and everyone else know).
"On this day at least 13 people fell off their bicycles, and some of the sea evaporated."
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Adding a callback function after the dynamic dialog has been instantiated will give you much more flexibility - you will be able to get to all the dialog items via the GetDlgItem() method and then you may modify your combo box (add/delete entries) and perhaps SetCurSel(), etc.
In DynDialogEx.h:
class CDynDialogEx; typedef void (CALLBACK * CDynDialogExInitCBF)(CDynDialogEx * dlg);
///////////////////////////////////////////////////////////////////////////// // CDynDialogEx dialog
class CDynDialogEx : public CDialog { // Construction public: CDynDialogEx(CWnd * pParent = NULL, CDynDialogExInitCBF cbFunc = NULL); ~CDynDialogEx(); ... ... protected: ... CDynDialogExInitCBF m_cbFunc; }
In DynDialogEx.cpp:
CDynDialogEx::CDynDialogEx(CWnd * pParent, /*=NULL*/ CDynDialogExInitCBF cbFunc /*=NULL*/) : CDialog() { ... m_cbFunc = cbFunc; ... }
...
BOOL CDynDialogEx::OnInitDialog() { ... CDialog::OnInitDialog(); if (m_cbFunc != NULL) { m_cbFunc(this); } CenterWindow(); ... }
In your own application:
void CALLBACK CondBPCallback(CDynDialogEx * dlg) { CComboBox * myCombo = (CComboBox *)dlg->GetDlgItem(IDC_MY_COMBOLISTBOX); if (myCombo != NULL) { myCombo->AddString(str0); myCombo->AddString(str1); myCombo->AddString(str2); myCombo->AddString(str3); myCombo->AddString(str4); myCombo->AddString(str5); myCombo->AddString(str6); myCombo->SetCurSel(3); } }
... void CTestDynDialogDlg::OnButton1() { ... CDynDialogEx dlg(this, CondBPCallback); .. }
That's all. There is no need to modify any other parts of this excellent utility.
Rudy Wang
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
 |
|
|
Very nice!
A iactually coocked up something quite simmilar recently, but i ran across one big problem... How on Earth do you add a bitmap (preferebly from a file, not a resource) to a button???
|
| Sign In·View Thread·PermaLink | 1.67/5 (3 votes) |
|
|
|
 |
|
|
Hi, I would like to add a scrollbar when the number of controls added make the dialog not fit on the screen. In the OnInitDialog method, I called EnableScrollBarCtrl, and ShowScrollBar(SB_VERT,FALSE);
In the AddDlgControl method, I tried to do GetDlgRect, and if the rect.bottom-top exceeds some limit - I tried ShowScrollBar(TRUE). This does not work as the m_hWnd is 0? Any tips/hints/code would be great.
|
| Sign In·View Thread·PermaLink | 2.33/5 (3 votes) |
|
|
|
 |
|
|
Hi, Excuse my english, I´m a brazilian.
What can i do to use Tab Control ? If you have any source sample, i appreciate. Thank´s for any help.
Mauro Cordon. mcordon@usa.com
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
I want to put a control, controled by a class included by me, in a dialog dynamicly created by DynDialogEx class. I think the subclassed controls are this, but after try to implementated I'm not sure. I Registered my class, and I create the control with the function AddSubclassedDlgControl. After that I execute the function SubclassDlgItem with de ID returned by AddSubclassedDlgControl, but my control is not created yet, in consecuence the control is not properly created in dynamic dialog.
Is possible add support for a new class in this class?. I seen the example CListDynDialogEx in DynamicDialog_demo, but I don't want a new dialog, and my control is from a other class!.
Any suggestion

Thanks in advance.
Amauta
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|