Discussion:
MFC Design Q
(too old to reply)
Janiv Ratson
2006-05-07 08:36:19 UTC
Permalink
Hi,

I'm writing a plug in application.
The GUI is managed in my application, and each plug in should be able to
update the GUI.
For example, I have a tree control and a list view that represent a home
network.
There are some plug ins (thay may be developed by 3rd parties) that add
their own items to the tree view and to the list view. I want them to handle
the tree update (adding their own icons, items, menu items, command handlers
etc).
I think I want to avoid creating an interface that accepts CTReeView and
CListView objects, it seems not so well designed, buy maybe this is the only
way to do it.
Anyway, I need your help on how to design my system.
How do I make the plugins (separate dllz) handle GUI events?
How do I enable plugin developers to updates the GUI control that in my
application?
How do I set the appropriate context menu to be poped up when user right
clicks on a tree item?
Thanks,
Janiv Ratson.
Janiv Ratson
2006-05-08 10:12:18 UTC
Permalink
Thanks Joe for the great help.

I have some further questions regarding your solution.
You said that the plugin cannot handle GUI events (for example, context
menu -> remove).
You also said that the events must be translated and converted to anstract
operation.
However, I must pass concrete GUI controls to the plugin, which means that
my interface include concrete GUI controls in it. For example.
User right click on a tree control item and a context menu is poped up: how
do I make the popup menu displayed from within the specific item's plugin?.
User chooses to Remove the item using the Remove menu item: how do I enable
the plugin to handle the Remove commnad (is it necessary to handle the
remove command within the plugin, or should I handle it within my
application GUI handler?).
Whether the app or the plugin handle the event, somehow the item icon should
be removed (and maybe some more changes should be made to the tree control),
hence, the plugin must accept somehow (How?) the concrete CTReeCtrl object
as a funnction parameter, which break encapsulation.

If I understand it correctly, you suggest that the app GUI will update the
GUI controls (CTReeCtrl for example), and the plugin will use an abstract
interface to made the required changes.
However, there might be a case in which, the plugin will need to make some
special GUI care to the control (for example, while most of the plugins will
add an icon to the tree, on an Add command, one plugin, may add an item to
the tree control which has some more sub items, and also would need to
update some other items within the tree control). I will never be able to
anticipate any GUI updates on every GUI control I have. I must let the
plugin handle the GUI controls ,on one hand, and on the other hand, I want
to keep encapsulation.

Also, how do I make sure that resources will not be ambiguous (dialog names,
control ids, registered event names, etc.) ?

Thanks again,
Janiv Ratson.
First, ActiveX is worth thinking about here. It is ideal for supporting
plugins, and
abstracts concepts such as what kind of control vs. what kind of
operation.
You will have to design an abstract interface that says "what do I want to
do" and in the
code you implement the details of how this is done. You might use a tree
control this
week and some weird custom control next week, but the ability to create
elements and
assign icons is what you are after.
My own preference on this is to use Registered Window Messages; the
plugins with either
export methods (and be careful: you can't really export C++ methods
because of name
mangling issues, since you usually want to define an interface class and
let the plugins
derive subclasses to implement their features. I usually just send
messages to the
plugin, either via an explicit window it produces or a hidden window
created for that
purpose; these then invoke virtual methods of the parent class which the
plugin
implementor has written in a subclass).
As to how to make a plugin "handle GUI events", in effect, it cannot. The
events have to
be translated from your GUI to the abstract operations you want the plugin
to perform.
The way to "update GUI controls" is to figure out what the abstract
interface is that your
GUI presents to the plugin (the complementary problem of the abstract
interface the plugin
presents to the application), and let the plugin send messages that ask
for operations to
be done to the GUI (such as updating a control), and the details of how
that abstraction
is implemented this week are subject to change without notice. So your
responsibility as
app designer is to make sure that in all future releases, the abstractions
you told the
plugin writers to use continue to make sense.
This is not a trivial design issue, but there is no simple "one answer
fits all" model,
either.
joe
Post by Janiv Ratson
Hi,
I'm writing a plug in application.
The GUI is managed in my application, and each plug in should be able to
update the GUI.
For example, I have a tree control and a list view that represent a home
network.
There are some plug ins (thay may be developed by 3rd parties) that add
their own items to the tree view and to the list view. I want them to handle
the tree update (adding their own icons, items, menu items, command handlers
etc).
I think I want to avoid creating an interface that accepts CTReeView and
CListView objects, it seems not so well designed, buy maybe this is the only
way to do it.
Anyway, I need your help on how to design my system.
How do I make the plugins (separate dllz) handle GUI events?
How do I enable plugin developers to updates the GUI control that in my
application?
How do I set the appropriate context menu to be poped up when user right
clicks on a tree item?
Thanks,
Janiv Ratson.
Joseph M. Newcomer [MVP]
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
--
NewsGuy.Com 30Gb $9.95 Carry Forward and On Demand Bandwidth
Joseph M. Newcomer
2006-05-09 02:49:02 UTC
Permalink
See below...
Post by Janiv Ratson
Thanks Joe for the great help.
I have some further questions regarding your solution.
You said that the plugin cannot handle GUI events (for example, context
menu -> remove).
You also said that the events must be translated and converted to anstract
operation.
However, I must pass concrete GUI controls to the plugin, which means that
my interface include concrete GUI controls in it. For example.
User right click on a tree control item and a context menu is poped up: how
do I make the popup menu displayed from within the specific item's plugin?.
*****
I'm a little confused about context here. A plugin should know NOTHING about the
implementation of the controls in the main application. If a right-click on the control
needs to pop up a context menu, and the plugin is providing part of the context menu, then
the main app might send a message UWM_QUERY_POPUP_ADDINS to the plugin, or call an
abstract method of the plugin superclass, CWhateverIsTheSuperclass::QueryPopupAddins,
which causes the plugin to return, for example, a CMenu * object which is the set of items
to pop up in addition to the default behavior (if any). If one of these CMenu items is
selected, the approach would be to send a message UWM_POPUP_SELECTED with the menu ID, or
call an abstract method of the plugin superclass,
CWhateverIsTheSuperclass::PopupItemSelected passing in the item ID. You translate back
and forth between concrete implementations (maintained by the application) and abstract
queries, actions, and notifications (maintained in the plugin). Then, if you decide to
rework the app, the interface remains constant. I've done this successfully many times,
so I know it works well. So there is no reason for the plugin to have the slightest clue
as to how the application interface works. It presents options, it reacts to events, but
it doesn't actually know what invoked the operations, or how its requests or replies are
actually implemented
*****
Post by Janiv Ratson
User chooses to Remove the item using the Remove menu item: how do I enable
the plugin to handle the Remove commnad (is it necessary to handle the
remove command within the plugin, or should I handle it within my
application GUI handler?).
*****
Is the plugin supplying the actual controls? In that case, you would simply have a
reserved area of the screen with coordinates provided (I tend to do this by creating an
invisible frame control, changing its ID from IDC_STATIC to IDC_WHATEVER_I_WANT, and
creating a CStatic frame control for it. Then, when time comes for the plugin to provide
its control, I would most likely have the plugin create a child CDialog-derived class in
the rectangle provided, and then it would handle all events within that dialog. So in my
plugin-load sequence, I'd call an abstract method of the plugin superclass, for example,
CWhateverIsTheSuperClass::InstallHere(CRect & r) where r is the
GetWindowRect/ScreenToClient transformation of the frame control. I'd make my plugin
"smart" about geometry so it could adjust its control layout (if necessary) within the
child dialog. Then the parent app doesn't even see the control notifications, which are
handled entirely within the child dialog subclass in the plugin, but if one of these
operations requires notification to the parent, a GetParent()->SendMessage can be used to
notify the parent.

Example: I have a set of plugins that provide for keyboard, musical staff, and fretted
instrument layouts. They each manage their own components of the dialog they control, and
occasionally do a GetParent()->SendMessage to notify the parent that something interesting
should happen, such as sending a note-on or note-off command, or all-notes-off, or making
a query about some aspect of the enclosing environment. If someone came to me and wanted
the image of a recorder complete with fingering options, I could write it in a couple days
and if I put it on the Web site, every existing user could download it and add it to their
app, even though we have several different versions of the app out there (they all use the
same interface to the plugins). So while the plugins manage "concrete" controls, they are
entirely self-contained and have no direct interaction with the parent (I use separate
dialogs, but the notion of embedding a child dialog in the parent is an idea I'm thinking
about for another app that we're working one which requires plugins)
*****
Post by Janiv Ratson
Whether the app or the plugin handle the event, somehow the item icon should
be removed (and maybe some more changes should be made to the tree control),
hence, the plugin must accept somehow (How?) the concrete CTReeCtrl object
as a funnction parameter, which break encapsulation.
*****
Think of the abstract operations. If the tree control is owned by the application (not
the plugin, as just described above), then any operation on the tree control must be
transmitted abstractly to the plugin, and the plugin will respond with appropriate
requests (e.g., UWM_REMOVE_ICON). If a later implementation uses a different
representation, perhaps the implementation of this message changes, but the abstract
concept of removing an icon remains the same. So I don't see any reason the plugin needs
to see the CTreeCtrl, or care that it *is* a CTreeCtrl. You could consider passing an
abstract LPARAM value to the plugin, which the plugin passes back via the message (perhaps
pointing to a structure that contains it). If, this week, the LPARAM is an HTREEITEM,
fine; if next week it is something else, that's fine also. The plugin shouldn't care.
*****
Post by Janiv Ratson
If I understand it correctly, you suggest that the app GUI will update the
GUI controls (CTReeCtrl for example), and the plugin will use an abstract
interface to made the required changes.
*****
Yes.
****
Post by Janiv Ratson
However, there might be a case in which, the plugin will need to make some
special GUI care to the control (for example, while most of the plugins will
add an icon to the tree, on an Add command, one plugin, may add an item to
the tree control which has some more sub items, and also would need to
update some other items within the tree control). I will never be able to
anticipate any GUI updates on every GUI control I have. I must let the
plugin handle the GUI controls ,on one hand, and on the other hand, I want
to keep encapsulation.
*****
If the concept is a tree of objects, then express things in terms of a tree of objects. If
this tree of objects is, this week implemented as a CTreeCtrl, fine. If next week it is
done by some other means, the plugin should not have to change. It expresses what it is
doing in terms of tree operations; someone else (the app) maps those to an implementaiton
of a CTreeCtrl
****
Post by Janiv Ratson
Also, how do I make sure that resources will not be ambiguous (dialog names,
control ids, registered event names, etc.) ?
*****
Dialog names never escape the plugin, so they doesn't matter. If you are registering
Window classes, use GUIDGEN to create a unique name, likewise for Registered Window
Messages, etc. See my essay on Message Management to see how I use GUIDs to avoid any
ambiguities in this regard. I tend to do names like HUMAN_READABLE-{long-guid-here} so I
can tell what is going on using various tools. I would only care about the guid if
someone else invented a HUMAN_READABLE-{other-long-guid-here} for some different purpose
and I happened to be using their module in my code. Also, these are much more readable in
Spy++ than names that are based on WM_USER or WM_APP.
****
****
Post by Janiv Ratson
Thanks again,
Janiv Ratson.
First, ActiveX is worth thinking about here. It is ideal for supporting
plugins, and
abstracts concepts such as what kind of control vs. what kind of
operation.
You will have to design an abstract interface that says "what do I want to
do" and in the
code you implement the details of how this is done. You might use a tree
control this
week and some weird custom control next week, but the ability to create
elements and
assign icons is what you are after.
My own preference on this is to use Registered Window Messages; the
plugins with either
export methods (and be careful: you can't really export C++ methods
because of name
mangling issues, since you usually want to define an interface class and
let the plugins
derive subclasses to implement their features. I usually just send
messages to the
plugin, either via an explicit window it produces or a hidden window
created for that
purpose; these then invoke virtual methods of the parent class which the
plugin
implementor has written in a subclass).
As to how to make a plugin "handle GUI events", in effect, it cannot. The
events have to
be translated from your GUI to the abstract operations you want the plugin
to perform.
The way to "update GUI controls" is to figure out what the abstract
interface is that your
GUI presents to the plugin (the complementary problem of the abstract
interface the plugin
presents to the application), and let the plugin send messages that ask
for operations to
be done to the GUI (such as updating a control), and the details of how
that abstraction
is implemented this week are subject to change without notice. So your
responsibility as
app designer is to make sure that in all future releases, the abstractions
you told the
plugin writers to use continue to make sense.
This is not a trivial design issue, but there is no simple "one answer
fits all" model,
either.
joe
Post by Janiv Ratson
Hi,
I'm writing a plug in application.
The GUI is managed in my application, and each plug in should be able to
update the GUI.
For example, I have a tree control and a list view that represent a home
network.
There are some plug ins (thay may be developed by 3rd parties) that add
their own items to the tree view and to the list view. I want them to handle
the tree update (adding their own icons, items, menu items, command handlers
etc).
I think I want to avoid creating an interface that accepts CTReeView and
CListView objects, it seems not so well designed, buy maybe this is the only
way to do it.
Anyway, I need your help on how to design my system.
How do I make the plugins (separate dllz) handle GUI events?
How do I enable plugin developers to updates the GUI control that in my
application?
How do I set the appropriate context menu to be poped up when user right
clicks on a tree item?
Thanks,
Janiv Ratson.
Joseph M. Newcomer [MVP]
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
--
NewsGuy.Com 30Gb $9.95 Carry Forward and On Demand Bandwidth
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
--
NewsGuy.Com 30Gb $9.95 Carry Forward and On Demand Bandwidth
Janiv Ratson
2006-05-10 08:32:20 UTC
Permalink
Hello Joseph,
You have no idea how helpful your information is.
Thanks so much.
I have few more questions:

Do you prefer using MFC Extension DLL or Regular DLL for the plug-ins?

Would you use COM/ATL? What for? Where?

If the main application holds the tree, and the plugin will send messages to
the application saying for example, AddItem, to add an item to the tree.
How will it pass the appropriate ICON (each plag-in in my application, has
its own set of icons to represent the concrete item (device))? Who holds the
ICON?

Regarding context menu, you suggest that I will have a function or a meesage
within the plugin that will return CMenu* to my application, to add specific
command items (M I right?).
When the user will choose the plugin commnad on the context menu, which
handlers will be called, the plugin handler or the application handler?

Thanks for your help, again,
Janiv Ratson.
Post by Joseph M. Newcomer
See below...
Post by Janiv Ratson
Thanks Joe for the great help.
I have some further questions regarding your solution.
You said that the plugin cannot handle GUI events (for example, context
menu -> remove).
You also said that the events must be translated and converted to anstract
operation.
However, I must pass concrete GUI controls to the plugin, which means that
my interface include concrete GUI controls in it. For example.
User right click on a tree control item and a context menu is poped up: how
do I make the popup menu displayed from within the specific item's plugin?.
*****
I'm a little confused about context here. A plugin should know NOTHING about the
implementation of the controls in the main application. If a right-click on the control
needs to pop up a context menu, and the plugin is providing part of the context menu, then
the main app might send a message UWM_QUERY_POPUP_ADDINS to the plugin, or call an
abstract method of the plugin superclass,
CWhateverIsTheSuperclass::QueryPopupAddins,
which causes the plugin to return, for example, a CMenu * object which is the set of items
to pop up in addition to the default behavior (if any). If one of these CMenu items is
selected, the approach would be to send a message UWM_POPUP_SELECTED with the menu ID, or
call an abstract method of the plugin superclass,
CWhateverIsTheSuperclass::PopupItemSelected passing in the item ID. You translate back
and forth between concrete implementations (maintained by the application) and abstract
queries, actions, and notifications (maintained in the plugin). Then, if you decide to
rework the app, the interface remains constant. I've done this successfully many times,
so I know it works well. So there is no reason for the plugin to have the slightest clue
as to how the application interface works. It presents options, it reacts to events, but
it doesn't actually know what invoked the operations, or how its requests or replies are
actually implemented
*****
Post by Janiv Ratson
User chooses to Remove the item using the Remove menu item: how do I enable
the plugin to handle the Remove commnad (is it necessary to handle the
remove command within the plugin, or should I handle it within my
application GUI handler?).
*****
Is the plugin supplying the actual controls? In that case, you would simply have a
reserved area of the screen with coordinates provided (I tend to do this by creating an
invisible frame control, changing its ID from IDC_STATIC to
IDC_WHATEVER_I_WANT, and
creating a CStatic frame control for it. Then, when time comes for the plugin to provide
its control, I would most likely have the plugin create a child CDialog-derived class in
the rectangle provided, and then it would handle all events within that dialog. So in my
plugin-load sequence, I'd call an abstract method of the plugin superclass, for example,
CWhateverIsTheSuperClass::InstallHere(CRect & r) where r is the
GetWindowRect/ScreenToClient transformation of the frame control. I'd make my plugin
"smart" about geometry so it could adjust its control layout (if necessary) within the
child dialog. Then the parent app doesn't even see the control notifications, which are
handled entirely within the child dialog subclass in the plugin, but if one of these
operations requires notification to the parent, a GetParent()->SendMessage can be used to
notify the parent.
Example: I have a set of plugins that provide for keyboard, musical staff, and fretted
instrument layouts. They each manage their own components of the dialog they control, and
occasionally do a GetParent()->SendMessage to notify the parent that something interesting
should happen, such as sending a note-on or note-off command, or all-notes-off, or making
a query about some aspect of the enclosing environment. If someone came to me and wanted
the image of a recorder complete with fingering options, I could write it in a couple days
and if I put it on the Web site, every existing user could download it and add it to their
app, even though we have several different versions of the app out there (they all use the
same interface to the plugins). So while the plugins manage "concrete" controls, they are
entirely self-contained and have no direct interaction with the parent (I use separate
dialogs, but the notion of embedding a child dialog in the parent is an idea I'm thinking
about for another app that we're working one which requires plugins)
*****
Post by Janiv Ratson
Whether the app or the plugin handle the event, somehow the item icon should
be removed (and maybe some more changes should be made to the tree control),
hence, the plugin must accept somehow (How?) the concrete CTReeCtrl object
as a funnction parameter, which break encapsulation.
*****
Think of the abstract operations. If the tree control is owned by the application (not
the plugin, as just described above), then any operation on the tree control must be
transmitted abstractly to the plugin, and the plugin will respond with appropriate
requests (e.g., UWM_REMOVE_ICON). If a later implementation uses a different
representation, perhaps the implementation of this message changes, but the abstract
concept of removing an icon remains the same. So I don't see any reason the plugin needs
to see the CTreeCtrl, or care that it *is* a CTreeCtrl. You could consider passing an
abstract LPARAM value to the plugin, which the plugin passes back via the message (perhaps
pointing to a structure that contains it). If, this week, the LPARAM is an HTREEITEM,
fine; if next week it is something else, that's fine also. The plugin shouldn't care.
*****
Post by Janiv Ratson
If I understand it correctly, you suggest that the app GUI will update the
GUI controls (CTReeCtrl for example), and the plugin will use an abstract
interface to made the required changes.
*****
Yes.
****
Post by Janiv Ratson
However, there might be a case in which, the plugin will need to make some
special GUI care to the control (for example, while most of the plugins will
add an icon to the tree, on an Add command, one plugin, may add an item to
the tree control which has some more sub items, and also would need to
update some other items within the tree control). I will never be able to
anticipate any GUI updates on every GUI control I have. I must let the
plugin handle the GUI controls ,on one hand, and on the other hand, I want
to keep encapsulation.
*****
If the concept is a tree of objects, then express things in terms of a tree of objects. If
this tree of objects is, this week implemented as a CTreeCtrl, fine. If next week it is
done by some other means, the plugin should not have to change. It expresses what it is
doing in terms of tree operations; someone else (the app) maps those to an implementaiton
of a CTreeCtrl
****
Post by Janiv Ratson
Also, how do I make sure that resources will not be ambiguous (dialog names,
control ids, registered event names, etc.) ?
*****
Dialog names never escape the plugin, so they doesn't matter. If you are registering
Window classes, use GUIDGEN to create a unique name, likewise for Registered Window
Messages, etc. See my essay on Message Management to see how I use GUIDs to avoid any
ambiguities in this regard. I tend to do names like
HUMAN_READABLE-{long-guid-here} so I
can tell what is going on using various tools. I would only care about the guid if
someone else invented a HUMAN_READABLE-{other-long-guid-here} for some different purpose
and I happened to be using their module in my code. Also, these are much more readable in
Spy++ than names that are based on WM_USER or WM_APP.
****
****
Post by Janiv Ratson
Thanks again,
Janiv Ratson.
First, ActiveX is worth thinking about here. It is ideal for supporting
plugins, and
abstracts concepts such as what kind of control vs. what kind of
operation.
You will have to design an abstract interface that says "what do I want to
do" and in the
code you implement the details of how this is done. You might use a tree
control this
week and some weird custom control next week, but the ability to create
elements and
assign icons is what you are after.
My own preference on this is to use Registered Window Messages; the
plugins with either
export methods (and be careful: you can't really export C++ methods
because of name
mangling issues, since you usually want to define an interface class and
let the plugins
derive subclasses to implement their features. I usually just send
messages to the
plugin, either via an explicit window it produces or a hidden window
created for that
purpose; these then invoke virtual methods of the parent class which the
plugin
implementor has written in a subclass).
As to how to make a plugin "handle GUI events", in effect, it cannot.
The
events have to
be translated from your GUI to the abstract operations you want the plugin
to perform.
The way to "update GUI controls" is to figure out what the abstract
interface is that your
GUI presents to the plugin (the complementary problem of the abstract
interface the plugin
presents to the application), and let the plugin send messages that ask
for operations to
be done to the GUI (such as updating a control), and the details of how
that abstraction
is implemented this week are subject to change without notice. So your
responsibility as
app designer is to make sure that in all future releases, the abstractions
you told the
plugin writers to use continue to make sense.
This is not a trivial design issue, but there is no simple "one answer
fits all" model,
either.
joe
Post by Janiv Ratson
Hi,
I'm writing a plug in application.
The GUI is managed in my application, and each plug in should be able to
update the GUI.
For example, I have a tree control and a list view that represent a home
network.
There are some plug ins (thay may be developed by 3rd parties) that add
their own items to the tree view and to the list view. I want them to handle
the tree update (adding their own icons, items, menu items, command handlers
etc).
I think I want to avoid creating an interface that accepts CTReeView and
CListView objects, it seems not so well designed, buy maybe this is the only
way to do it.
Anyway, I need your help on how to design my system.
How do I make the plugins (separate dllz) handle GUI events?
How do I enable plugin developers to updates the GUI control that in my
application?
How do I set the appropriate context menu to be poped up when user right
clicks on a tree item?
Thanks,
Janiv Ratson.
Joseph M. Newcomer [MVP]
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
--
NewsGuy.Com 30Gb $9.95 Carry Forward and On Demand Bandwidth
Joseph M. Newcomer [MVP]
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
--
NewsGuy.Com 30Gb $9.95 Carry Forward and On Demand Bandwidth
Max
2006-05-08 11:26:53 UTC
Permalink
As I see it you'll need to implement an object model. For expample, if you
have a tree view and want others to be able to add nodes to it, you'll have
an ITreeView interface with AddNode function.

It looks like a good practice to avoid passing MFC objects as arguments of
interface functions. After all you are not sure what tool third party
developer will use to write his code. If you use MFC specific objects in
interfaces you make him use MFC and exactly the same version you do.

Concerning events, you'll need to implement COM style events (e.g.
Connection Points) in your application. Just in case you did do that before,
COM events work as follows. COM CLIENT (plugin in your case) implements an
interface and registers itself within server (your application in this
case). If you are new to it - start reading MSDN from IConnectionPoint and
IConnectionPointContainer articles.
Post by Janiv Ratson
Hi,
I'm writing a plug in application.
The GUI is managed in my application, and each plug in should be able to
update the GUI.
For example, I have a tree control and a list view that represent a home
network.
There are some plug ins (thay may be developed by 3rd parties) that add
their own items to the tree view and to the list view. I want them to
handle the tree update (adding their own icons, items, menu items, command
handlers etc).
I think I want to avoid creating an interface that accepts CTReeView and
CListView objects, it seems not so well designed, buy maybe this is the
only way to do it.
Anyway, I need your help on how to design my system.
How do I make the plugins (separate dllz) handle GUI events?
How do I enable plugin developers to updates the GUI control that in my
application?
How do I set the appropriate context menu to be poped up when user right
clicks on a tree item?
Thanks,
Janiv Ratson.
RT
2006-05-08 13:33:34 UTC
Permalink
If you can get your plugin writers to use the same version of MFC that
you have, you can do the "plugging in" by creating extension dlls.
These dlls can be dynamically loaded (unloaded) using AfxLoadLibrary
(AfxFreeLibrary) functions at runtime, which is a very nice way of
dynamically linking object code. This gives you ultimate flexibility in
communicating with your plugin since after loading of an extension dll,
the code is indistinguishable from the main app. An extension dll does
not have a separate message pump. After loading, you can send any
message you want to your CTreeCtrl from a plugin ext dll.

There are two problems though which are easily solved: the resource IDs
have to be blocked out since they can conflict with each other. It may
take some thinking to find a unique numbering system for the ids. The
second problem is the C++ name mangling. Access to the various loaded
modules is best accomplished by, as Newcomer outlines below, using a
stable canonical interface derived from an abstract class which allows
you to use "C" type external interface for all extension dll plugins.
(Beware of MFC's generated extension dll's main .cpp file. This file
contains a use of static which is deprecated. Just comment it out and
it will be fine. (/*static*/ AFX_EXTENSION_MODULE MyExtDLL = { NULL,
NULL };))
RT
Ajay Kalra
2006-05-08 13:43:17 UTC
Permalink
Post by RT
If you can get your plugin writers to use the same version of MFC that
you have, you can do the "plugging in" by creating extension dlls.
This is something I would strogly object to. When you are writing a
plug in, you should not be forced to use any language. Typically
PlugIns can be developed in *any* language which supports COM(VB, VC,
Win32, VJ++ etc). If written using MFC, these plugins should never be
an Extension DLL. Using Regular DLL for this would be a very good
choice. Think of the case where you have mulitple plugins with
Extension DLLs. The management of resource IDs would be a nightmare.
Who decides what resource IDs get allocated to which Extension DLL. A
regular DLL would remove this problem.

---
Ajay
Joseph M. Newcomer
2006-05-09 02:50:14 UTC
Permalink
Which is one of the strong arguments for using ActiveX as a plugin technology.
joe
Post by Ajay Kalra
Post by RT
If you can get your plugin writers to use the same version of MFC that
you have, you can do the "plugging in" by creating extension dlls.
This is something I would strogly object to. When you are writing a
plug in, you should not be forced to use any language. Typically
PlugIns can be developed in *any* language which supports COM(VB, VC,
Win32, VJ++ etc). If written using MFC, these plugins should never be
an Extension DLL. Using Regular DLL for this would be a very good
choice. Think of the case where you have mulitple plugins with
Extension DLLs. The management of resource IDs would be a nightmare.
Who decides what resource IDs get allocated to which Extension DLL. A
regular DLL would remove this problem.
---
Ajay
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
--
NewsGuy.Com 30Gb $9.95 Carry Forward and On Demand Bandwidth
Ajay Kalra
2006-05-09 03:32:34 UTC
Permalink
Post by Joseph M. Newcomer
Which is one of the strong arguments for using ActiveX as a plugin technology.
Thats not really true. What OP needs is a COM server with published
interfaces/events. Clients can develop plugins in any language that supports
COM. ActiveX does not really fit in here. This is no different than any of
the Office products (which are all COM servers) which have rich object
models for PlugIn Development/Scripting.

--
Ajay Kalra [MVP - VC++]
***@yahoo.com
Ajay Kalra
2006-05-08 13:53:21 UTC
Permalink
Its really difficult to answer what you have asked. Your problem seems
to be with the fact that PlugIn is like your application. Its is not
and it should not be as far as objects that exist in *your*
application.

Almost always you have to have objects are created and passed on to
plugIn and you fire events for something interesting to a plugIn. This
topic is not trivial by any stretch. You need to know about COM, a lot
of it.

A plugIn will never need to know if you have a TreeView or ListView.
You will provide methods to plugIn to be able to add items thru your
object.

Take a look at object model for any of the Office application. Write a
plugIn for it and see what steps you are taking to add an entry to a
menu. Providing a plugIn mechanism is not trivial, if you do it the
right way.

One more comment, an ActiveX has nothing to do with it. These are two
different things. A plugIn can interact with GUI but it does not have
to.

---
Ajay
Janiv Ratson
2006-05-08 15:54:36 UTC
Permalink
Hello all,
I want to thank you for your kind and detaild help.

One huge problem I have is that I lack of COM expreince.
It seems that your suggested solutions require a deep knowledge of COM,
which I don' have.
I have an expreice in MFC.
I'd really appreciate it if you could tell me, what is the best for me:
Get into COM (we have a stress schedule for this development issue), or
use my MFC knowledge although it will be a bit harder or complicated?

Another thing I did not understand is the differnce between MFC extension
and regular dllz.
I know how to work with MFC extension dll, but how do I implement this
solution using regular dll, what about the resources? handlers ? etc ?

I know that for best practise the plugin can be written in any language.
Currently, no one in our company (business, CEO and developers) sees the
option that 3rd parties will implement plugins to our application. The idea
for plugins came up so the marketing will be able to sell packages with
various plugins. I think that I can swallow this constraint, and decide that
a plugin will be written in MFC 7.1.

Thanks again for the help,
Janiv Ratson.
Post by Ajay Kalra
Its really difficult to answer what you have asked. Your problem seems
to be with the fact that PlugIn is like your application. Its is not
and it should not be as far as objects that exist in *your*
application.
Almost always you have to have objects are created and passed on to
plugIn and you fire events for something interesting to a plugIn. This
topic is not trivial by any stretch. You need to know about COM, a lot
of it.
A plugIn will never need to know if you have a TreeView or ListView.
You will provide methods to plugIn to be able to add items thru your
object.
Take a look at object model for any of the Office application. Write a
plugIn for it and see what steps you are taking to add an entry to a
menu. Providing a plugIn mechanism is not trivial, if you do it the
right way.
One more comment, an ActiveX has nothing to do with it. These are two
different things. A plugIn can interact with GUI but it does not have
to.
---
Ajay
Ajay Kalra
2006-05-08 15:08:12 UTC
Permalink
Post by Janiv Ratson
Get into COM (we have a stress schedule for this development issue), or
use my MFC knowledge although it will be a bit harder or complicated?
You will need both. In addition, using ATL for all the COM work is a
good combination.
Post by Janiv Ratson
I know how to work with MFC extension dll, but how do I implement this
solution using regular dll, what about the resources? handlers ? etc ?
There is not much difference. You will need to use AFX_MANAGE_STATE to
change states and look in appropriate resoruces. However most common
issue is which one to choose. I was recommending using a Regular DLL
for plugIn developers. As an application developer, you should use MFC
Extension DLL unless you have a good reason not to.

I want to emphasize that providing plugIn architecture is no small task
and requires a thoughtful design including exposing only the
objects/events you want. Given that this seems to be an afterthought
for your company, I would skip it for now.

----
Ajay
Continue reading on narkive:
Loading...