|
-
December 30th, 2005, 06:55 AM
#1
Dynamic adding of controls (MFC)
Hi,
Basically I'm creating an app where the entire thing is controlled by scripts. I want to be able to create a window on-the-fly, with controls added via scripting. The problem is I'm also trying to do it in MFC.
I've had a look at the message map, and realised it's static, so even if i could hack into it and change some entries dynamically, I'd still have to create a different class for each different window, which is not what i want.
I've also had a look at overriding the WindowProc() function in my dialog, and dispatching WM_PAINT, WM_NCPAINT, and WM_DRAWITEM messages to my list of controls. Although this seems the most promising approach, the controls don't draw. (The OnPaint() handlers ARE called successfully though.) I usually wouldnt just die there and post on a forum but i actually have no idea how to debug this!
Any help would be MUCH appreciated!
James Molloy
-
December 30th, 2005, 12:29 PM
#2
Re: Dynamic adding of controls (MFC)
 Originally Posted by mankeyrabbit
Hi,
I'd still have to create a different class for each different window, which is not what i want.
WHat do you mean by different class for different window ? You mean different obhject for each window ? Please elaborate.
Also, please explain how you are creating the controls at runtime.
I've also had a look at overriding the WindowProc() function in my dialog, and dispatching WM_PAINT, WM_NCPAINT, and WM_DRAWITEM messages to my list of controls.
You don't post these messages yourself. Leave that work for windows. If the controls do not paint the problem is something else. It is not clear what you are doing. So, if you could give some more details on how these child controls are created, that would be cool.
-
December 30th, 2005, 12:58 PM
#3
Re: Dynamic adding of controls (MFC)
Kirants: Thanks for your reply;
Quote:
Originally Posted by mankeyrabbit
Hi,
I'd still have to create a different class for each different window, which is not what i want.
WHat do you mean by different class for different window ? You mean different obhject for each window ? Please elaborate.
This referred to the possibility of hacking around with the messagemap of a class, to add controls onthefly. What i meant was to manually change the CWnd::_messageEntries variable. I then found that this variable is static. Thus, if I add the controls I need for one window, all other windows of that class's messagemap would change. So, I would actually require a new class for each window, not merely a new object instance. Is this clearer? I'm sorry I'm not a newbie but I'm having difficulty explaining it properly!
Also, please explain how you are creating the controls at runtime.
at runtime, a script tells my app to create a new control, say a button. The script interpreter instantiates a new object of type CScriptedButton.
Code:
class CScriptedButton :
public CButton, public CScriptedObject
the CScriptedObject superclass just enables the button to be recognised and instantiated by my interpreter.
Also, a window will have been created:
Code:
class CScriptedWindow : public CDialog, CScriptedObject
the script calls an Attach() function on the button:
Code:
void CScriptedButton::Attach(CScriptedWindow *p, int anchors)
{
RECT r;
r.left = tmpx; r.right = tmpx+tmpw;
r.top = tmpy; r.bottom = tmpy+tmph;
CButton::Create(tmplabel.c_str(), 0, r, (CWnd *)p, 0);
CDialogItem a(r.left, r.top, r.right-r.left, r.bottom-r.top, anchors);
a.SetWnd((CWnd *)this);
p->AddControl(a);
}
void CScriptedWindow::AddControl(CDialogItem item)
{
m_Controls.push_back(item);
}
(CDialogItem is a struct containing a CWnd * and information relating to the positioning and anchors of the control)
That's how they are created. Sorry it was a bit long-winded!
OK, so now to get messages to the controls, I overrided CWnd::WindowProc in my Window class:
Code:
LRESULT CScriptedWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT l = __super::WindowProc(message, wParam, lParam);
switch(message)
{
case WM_NCDESTROY:
OnNcDestroy();
break;
case WM_PAINT:
DoDispatchMessage(WM_PAINT, wParam, lParam);
break;
case WM_NCPAINT:
DoDispatchMessage(WM_NCPAINT, wParam, lParam);
break;
case WM_DRAWITEM:
DoDispatchMessage(WM_DRAWITEM, wParam, lParam);
break;
}
return l;
}
void CScriptedWindow::DoDispatchMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{
// send to all.
vector<CDialogItem>::iterator it;
for(it = m_Controls.begin(); it != m_Controls.end(); it++)
{
it->GetWnd()->SendMessage(msg, wParam, lParam);
}
}
How should I be doing this? Please help me make it better!
James Molloy
-
December 30th, 2005, 01:33 PM
#4
Re: Dynamic adding of controls (MFC)
 Originally Posted by mankeyrabbit
This referred to the possibility of hacking around with the messagemap of a class, to add controls onthefly. What i meant was to manually change the CWnd::_messageEntries variable.
message map entries are for messages, not for controls. They are for messages sent to a window, so I am confused, but anyways, this doesn't seem to be having a role in the discussion here.
at runtime, a script tells my app to create a new control, say a button. The script interpreter instantiates a new object of type CScriptedButton.
So, I beleive, you do a
Code:
pNewButton = new CScripButton;
pNewButton->Attach();
sort of thing ?
Code:
LRESULT CScriptedWindow::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT l = __super::WindowProc(message, wParam, lParam);
switch(message)
{
case WM_NCDESTROY:
OnNcDestroy();
break;
case WM_PAINT:
DoDispatchMessage(WM_PAINT, wParam, lParam);
break;
case WM_NCPAINT:
DoDispatchMessage(WM_NCPAINT, wParam, lParam);
break;
case WM_DRAWITEM:
DoDispatchMessage(WM_DRAWITEM, wParam, lParam);
break;
}
return l;
}
This is wrong and you shouldn't even have to attempt to do such a thing.
It is wrong, because, these messages are posted to a specific window and may hold no meaning whatsoever to other windows.. for e.g. a WM_DRAWITEM is sent to a window when it needs to be drawn, and the info in the WPARAM , LPARAM are very specific to that. So, you cannot simply pass this meaningless info to other windows. Those windows might just go crazy interpreting the data sent . I hope you are understanding.
And I say, you dont' even have to attempt doing such a thing, because, all these messages are generated by windows and are sent to appropriate window procedures. These windowprocedures are all setup as soon as you call Create functiosn on the controls.
SO, summary, there is something wrong going on elsewhere.
Some questions:
- What kind of window is ScriptedWindow, how is it created ? is it a modal dialog, modeless ? If so, does the thread creating that window have a message loop ?
- If you do none of the WindowProc thingy, what is your observation ?
- Is it possible to upload your project ?
-
December 30th, 2005, 02:47 PM
#5
Re: Dynamic adding of controls (MFC)
Thanks again for the reply; I knew I didn't know what i was doing with that WindowProc function, and that just proves it.
I actually (seemingly by luck) managed to get it to work - I needed to call ShowWindow(SW_SHOW) on the button control.
Thank you for replying.
James Molloy
-
December 30th, 2005, 02:57 PM
#6
Re: Dynamic adding of controls (MFC)
Now, that you mention, please take a look at Create call.. You are not passing any styles there. You need to pass styles, at a minimum controls need WS_CHILD set. Also, if you combine WS_VISIBLE, you do not even have to call ShowWindow later on.
So, I would stronlgy recommend you to review your Create calls for all control types and make sure you have the necessary styles set. Here are the list of all common controls and under each control you have the style information etc.
http://msdn.microsoft.com/library/de...divcontrol.asp
This is again important because some of the styles cannot be set after creation of the control
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|