Re: General Question ... Class & Members
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
news:8ntku5h0mp4lppeobsd534slinasr2uort@4ax.com...
Key here: explain how there is going to be exactly ONE place where I
specify the mapping
between strings and values, and still use DDX. In my case, I might write
class CMyParametersDialog :public CDialog {
protected:
CIDCombo c_Colors;
public:
COLORREF m_DesiredColor;
// Set to obtain preselected color on input
// Selected color available after completion
... other stuff
};
In the implementation, I would write:
static const IDData colors[] = {
{IDS_COLOR_BLACK, RGB(0,0,0)},
{IDS_CO:OR_RED, RGB(255, 0, 0)},
{IDS_COLOR_GREEN, RGB(0, 255, 0)},
{IDS_COLOR_BLUE, RGB(0, 0, 255)},
{0, 0} // end of table marker
In OnInitDialog I do
c_Colors.LoadStrings(colors);
if(c_Colors.Select(m_DesiredColor) < 0)
c_Colors.SetCurSel(0);
in OnOK I do
m_DesiredColor = (COLORREF)c_Colors.GetItemData(c_Colors.GetCurSel())'
Note that I am always guaranteed GetCurSel will be defined. What doesn't
"scale" about
something this trivial? Or is it just tne notion that I had to write code
to accomplish
what I need the issue? How would you handle this using DDX?
Now, to add new colors, I simply add new STRINGTABLE names, and the RGB
values, and it
works. And if I fail to add the IDS_ entry to the STRINGTABLE, I get a
compilation error,
not code that subtly fails six months after it is deployed. I don't care
what "name"
IDS_BLACK has in the localized STRINGTABLE, I will always get the correct
mapping between
the selected color and the RGB triple that represents it. This is a
trivial example
because I can encode the value directly in the ItemData component; mostly,
I use much more
complex structures which are referenced by ItemData pointers.
Note also that if the selected color fails, instead of selecting some
default (such as
whatever the first color is), then I might convert the parameter to an RGB
string and add
it to the combo box, and select that item. LoadStrings and Select are
methods of my
CIDCombo class. I wrote this once, over twelve years ago, and have not
needed to change
it (except to handle 64-bit ItemData) since. And it works, robustly and
reliably. It
makes my code completely insensitive to the actual colors available, and
it means the
caller of the dialog has a *natural* interface (the COLORREF), not some
artifice of an
index of a combo box.
Yes, you can make the DDX variables private, but then you still have to
write code in
OnInitDialog and OnOK, so what good did DDX do? Instead of having to
recast the problem
into a different domain, I eliminate the need to have lookup tables in
parallel with the
data and just use one table that creates the combobox with the data
preloaded, and
everyone else knows the data, whatever it might be, is preloaded, and not
one line of code
changes if I add more colors; instead, I just add an entry to the preload
table and a
corresponding entry inthe STRINGTABLE (and failure to update both places
means a
compilation error!) and I can "scale up" from 1 color to 256 colors or
24=bit color if I
want. (Don't tell me about the CColorDialog; I am using colors here to
illustrate a
point. Also, CColorDialog has to be a separate dialog, which is one of
the Really Stupid
Ideas of the "common dialogs", which is that they are necessarily dialogs,
which
introduces an unfortunate modality that does not need to exist, but that's
a separate
discussion)
This is a robust implementation and is justified due to the special meanings
of the combobox items. Mostly they are ordinary strings with no semantic
meaning like a specific color, and all this is unnecessary. Anyway, we seem
to be going in circles, so I will stop. I will note that your approach of
using the combo box's item data to store a pointer to a struct that takes
additional info about the item is not in keeping with modern MVC
(model-view-controller), TDD (test driven development) or unit testing, for
what that's worth (not much, IMO, but if you want to debate the merits of
your advanced scheme, you'll need to talk about that). TDD requires no UI
elements be constructed to test the logic, meaning the combobox can't be the
thing that stores the list.
BTW, the hidden tragedy of sticking with a legacy framework like MFC is that
you aren't exposed to modern advanced in application development like the
above.
-- David