Re: FormatMessage LoadString from string table
On 14 Sep., 20:26, Joseph M. Newcomer <newco...@flounder.com> wrote:
See below...
On Tue, 14 Sep 2010 09:41:38 -0700 (PDT), mfc <mfcp...@googlemail.com> wr=
ote:
Why write a function, when you could have written instead a simple + o=
perator on the
CString values?
I`ve two CStrings which looks like
CString str3items ("here should be the first item %1, here should be
the second item %2, here should be the third item %3 and so on");
CString str2items ("here should be the first item %1, here should be
the second item %2);
CString firstItem ("first");
CString secondItem ("second");
CString thirdItem ("third");
Now I want to use FormatMessage to add these items to str2items or
str3items;
*
If you wish to be able to re-order the sequences of items using %n, then,=
indeed, you are
going to need some number of %i values. So make this formatting string=
the first string
in the sequence: IDS_TEST_FIRST. Start your loop at IDS_TEST_FIRST+1. =
Then your
formatting string and the strings it handles are all in the resource STRI=
NGTABLE and easy
to maintain!
Or, if it is some kind of XML template, then it might say
<%1:%2 value="%3"
<%1:%4 name="%5"....
and so on, which is how I create the templates for my Locale Explorer. =
I allow the user
to specify template files. Again, this is not Rocket Science, just usi=
ng the obvious
mechanisms in the obvious way. And if you need to have an array of 40 =
strings, well,
that's just tough, because what you want to do REQUIRES an array of 40 st=
rings (or 42, or
47, or 51, so if if you hardwire this value you have made a very deep and=
fundamental
programming error)
CString DoSubstitution(const CString & template)
{
CStringArray Parameters;
for(int i = IDS_START; i < IDS_MAX; i++)
{ /* data loop */
CString s;
s.LoadString(IDS_START+i);
if(s.IsEmpty())
break;
Parameters.Add(s);
} /* data loop */
LPTSTR msg;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSA=
GE_FROM_STRING,
=
...provide various parmeters (Exercise for the
Reader )
=
(LPTSTR)&msg,
....more parameters
=
Parameters.GetSize(),
=
Parameters.GetData());
CString result(msg);
LocalFree(msg);
return result;
}
Error checking is left as an Exercise for the Reader. I think the last=
two parameters are
the string count and the string array pointer, but this is an EFTR.
Note that at NO POINT does this code presume there is a fixed number of s=
trings, just a
maximum upper bound (e.g., 100, whereas I might only be using 27 of those=
strings)
My string table normally looks like
IDS_TEST <...This is the start of the sequence of strings used for...>
IDS_MAX <..All strings must fit in this range>
Note I set IDS_MAX to be IDS_TEST+100, e.g., I define IDS_TEST=10000 an=
d set IDS_MAX to be
10100, and start my loop at IDS_TEST+1, so I have actual DOCUMENTATION in=
my string table.
NEVER assume that because MFC doesn't have some capability you need that =
is possessed by
the raw API that you cannot use the raw API! Just use it!
Take a look at my FormatMessage example, or look at the numerous calls on=
FormatMessage in
my Locale Explorer source.
=
joe
*****
thanks for your help. The part with the CStringArray is totally clear
to me but the FormatMessage() call is not clear to me...
Only a small demo code;
LPTSTR msg ("%1% and %2% and %3%"); //represents the string which
should include all itmes from the CStringArray after the
FormatMessage()-call -> see out-string
LPWSTR out = NULL; //output-string which includes the msg-string
with all arguments from the CStringArray
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_STRING,
(LPTSTR)&msg, //lpSource (in - Pointer to a
string that consists of unformatted message text)
0,
0,
(LPWSTR ) &out, //lpBuffer(out A pointer to
a buffer that receives the null-terminated string that specifies the
formatted message)
0,
(va_list *)0
};
the (va_list*) argument seems to me that it should include the
Parameter.GetData() CStringArray - but that doesn`t work...
va_list args = NULL;
va_start(args, Parameters.GetData());
also (va_list *)Parameters.GetData() in the function call
FormatMessage() won`t work.