|
Ben Aldhouse wrote: void CNode::Serialize(CArchive &ar)
{
Did you forget to call base class member here ? CObject::Serialize(ar) in this case .
|
|
|
|
|
Thanks for your answer,I will go away and have a look...
|
|
|
|
|
Ok , so I have checked. I had been calling the ancestor function in the CSubNode class, but not in the CNode class serialization function. Both serialization functions now call the ancestor function. The result is the same. I can save (at least, to some extent), but not reload the data back into the array.
|
|
|
|
|
I've got this sorted out now. The full solution to the problem is written up here. Looking at the above message, it seems to me that, at the time, my mistake was in the CNode::Serialize function where I had simply tried to serialize the CObArray object (of sub nodes) with the insertion and extraction operators along with the other node object members. The way to get this to work, it turns out, is to not treat the collection of sub nodes like the other node object members but instead call its CObArray serialization function. Hence the node object serialization function looks like this:
void CNode::Serialize(CArchive &ar)
{
CSubNode::Serialize(ar);
int iNoSubNodes = 0;
if (ar.IsStoring())
{
iNoSubNodes = m_oaSubNodes.GetSize();
ar << m_iSubNodePosition << m_strString << iNoSubNodes;
}
else
ar >> m_iSubNodePosition >> m_strString >> iNoSubNodes;
m_oaSubNodes.Serialize(ar);
}
|
|
|
|
|
Hi,
I have a custom file format i would automatically assign to an application.
How do i do this? Is there any sample code out there or does the Windows API / MFC support some helpers for that?
I already implemented a class to store and read registry items. If there are no helper functions out there can you tell me where and what i have to write into the registry to assign a file format to an application?
Hope to hear from anyone soon . Thanks a lot for your help in advance!!!
- Ben
|
|
|
|
|
The easiest way, IMO, is to create an SDI application, and look at the .reg file that gets created as a result. That will show you the minimum registry keys/values that need to be created.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Directly from MSDN:
REGEDIT
HKEY_CLASSES_ROOT\.riy = FMA000_File_assoc
HKEY_CLASSES_ROOT\FMA000_File_assoc = File_assoc
HKEY_CLASSES_ROOT\FMA000_File_assoc\shell\open\command = fileasso.EXE
HKEY_CLASSES_ROOT\FMA000_File_assoc\shell\open\ddeexec = [Open(%1)]
HKEY_CLASSES_ROOT\FMA000_File_assoc\shell\open\ddeexec\application
= Myserver
HKEY_CLASSES_ROOT\FMA000_File_assoc\shell\open\ddeexec\topic = system
HKEY_CLASSES_ROOT\FMA000_File_assoc\shell\print\command = fileasso.EXE
HKEY_CLASSES_ROOT\FMA000_File_assoc\shell\print\ddeexec = [Open(%1)]
HKEY_CLASSES_ROOT\FMA000_File_assoc\shell\print\ddeexec\application
= MYServer
HKEY_CLASSES_ROOT\FMA000_File_assoc\shell\print\ddeexec\topic = System
HKEY_CLASSES_ROOT\FMA000_File_assoc\shell\print\ddeexec\ifexec =
[Test(%1)]
Peace!
-=- James If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! DeleteFXPFiles & CheckFavorites (Please rate this post!)
|
|
|
|
|
Have a look also on IQueryAssociations (retrieve using AssocCreate). This won't work for rewrite, but for query will do it.
|
|
|
|
|
In my MFC project, I declare a struct Stru_A,
struct Stru_A{
char Name[30];
int Age;
}
I would like to initialize the member variable Name with sth like a constructor used for a class. Does this make sense?
|
|
|
|
|
Yes.
Peace!
-=- James If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! DeleteFXPFiles & CheckFavorites (Please rate this post!)
|
|
|
|
|
it depends if you allocate your struct with new or with malloc .
if it's with new , then, yeah, add a constructor.
If it's with malloc , even if you have a constructor, it will not be called, juste create a wrapper function to allocate and initialize the structure.
something like :
Stru_A* MallocStru_A( char* name, int age )
{
}
|
|
|
|
|
Thanks, Maximilien
Would you please more specific about how to create a constructor for the struct
struct Stru_A{
char Name[30];
int Age;
};
And, how to use
<br />
Stru_A* MallocStru_A( char* name, int age )<br />
{ <br />
}<br />
<br />
to initialize a struct for later use.
|
|
|
|
|
cy163@hotmail.com wrote: Would you please more specific about how to create a constructor for the struct
In exactly the same way you'd create one for a class:
struct Stru_A
{
Stru_A() {}
char Name[30];
int Age;
};
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Is the following way correct for inckuding a constructor in a struct
<br />
struct Stru_A{<br />
Stru_A(char Name[30], int Age) <br />
{<br />
<br />
strcpy(this->Name, Name);<br />
this->Age = Age;<br />
}<br />
char Name[30];<br />
int Age;<br />
<br />
}*pStru_A;<br />
<br />
<br />
pStru_A xyz = new Stru_A("ABC", 123);<br />
<br />
|
|
|
|
|
Rather than use C-style types such as char , use the C++ type string . This will avoid the use of memset() , strcpy() and strncpy() . Hard-coding numbers (e.g, 30) is usually not a good thing.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
Might want to make sure that the OP is not going to be doing memory-style copies with the structure first before suggesting something like that. For example, if passing the address of an instance of the structure to something like fwrite(...) or WriteFile(...) , it will likely not work as expected if you have a dynamic-allocating string object in it.
DavidCrow wrote: Hard-coding numbers (e.g, 30) is usually not a good thing.
Usually? Limits are what normally define the functionality of a system. They just have to be enforced in order to prevent problems.
Peace!
-=- James If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! DeleteFXPFiles & CheckFavorites (Please rate this post!)
|
|
|
|
|
James R. Twine wrote: Usually?
I was erroring on the side of "there might be an exception." I know of no reason to use:
foo(char Name[30]); especialy if multiple of them exist. Once the size of the variable changes, every function prototype would also have to be changed.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
DavidCrow wrote: I was erroring on the side of "there might be an exception." I know of no reason to use:
foo(char Name[30]); especialy if multiple of them exist. Once the size of the variable changes, every function prototype would also have to be changed.
You are correct - there is no reason to write a prototype that way (except for documentation purposes) because array types in a prototype decay into pointers. So even if you did write it that way, the specified lengths would not enforced. So if you did change lengths, the functions would still compile. That is why you cannot write code like this:
void foox( char caData[ 30 ] ) { TRACE1( "foo %s\n", caData ); }
void foox( char *cpData ) { TRACE1( "foo2 %s\n", cpData ); }
void foox( char cvData[] ) { TRACE1( "foo3 %s\n", cvData ); } Because all three are really the same thing - the compiler will likely complain about duplicate function bodies. That is also why you can do the following:
void foo( char caData[ 30 ] ) { TRACE1( "foo %s\n", caData ); }
void foo2( char *cpData ) { TRACE1( "foo2 %s\n", cpData ); }
void foo3( char cvData[] ) { TRACE1( "foo3 %s\n", cvData ); }
char *cpTest = "Test";
char caTest30[ 30 ] = { "Test" };
char caTest10[ 10 ] = { "Test" };
char cvTest[] = "Test";
foo( cpTest ); foo( caTest30 );
foo( caTest10 ); foo( cvTest );
foo2( cpTest ); foo2( caTest30 );
foo2( caTest10 ); foo2( cvTest );
foo3( cpTest ); foo3( caTest30 );
foo3( caTest10 ); foo3( cvTest ) And the compiler will not complain, allowing all of the variable types to be passed to foo1/foo2/foo3 without issue.
<HR> First rule of buffers: when you pass a buffer, pass its usable length.
The point about changing lengths is exactly why you use something like const DWORD IDENTIFIER s to manage buffer lengths - change it once, change it everywhere. Combine that with a strategy like Size+1 and you have a way to manage string limits without risk of buffer overruns. All it takes to use and limit buffers correctly is a little discipline.
Peace!
-=- James If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! DeleteFXPFiles & CheckFavorites (Please rate this post!)
|
|
|
|
|
In C++ the only difference between struct and class is the default visibility of members. A constructor for a struct is defined just like a constructor for a class .
|
|
|
|
|
struct Stru_A{
char Name[30];
int Age;
}Stru_A, *pStru_A;
pStru_A foo = new Stru_A;
foo->Name(blah blah blah);
foo->Age(blah blah blah);
I win because I have the most fun in life...
|
|
|
|
|
I believe this may be what you are looking for:
struct Stru_A
{
char Name[30];
int Age;
Stru_A::Stru_A()
{
Age = 0;
memset(Name,0,30);
}
}
Hope that helps.
Karl - WK5M
PP-ASEL-IA (N43CS)
PGP Key: 0xDB02E193
PGP Key Fingerprint: 8F06 5A2E 2735 892B 821C 871A 0411 94EA DB02 E193
|
|
|
|
|
Is the following way correct for inckuding a constructor in a struct
<br />
<br />
struct Stru_A{<br />
Stru_A(char Name[30], int Age) <br />
{<br />
<br />
strcpy(this->Name, Name);<br />
this->Age = Age;<br />
}<br />
char Name[30];<br />
int Age;<br />
<br />
}*pStru_A;<br />
<br />
<br />
pStru_A xyz = new Stru_A("ABC", 123);<br />
<br />
|
|
|
|
|
I believe for what you're trying to do, you'll need this (note there are two constructors here - one with no parameters and the one you are trying to use):
struct Stru_A{
char Name[30];
int Age;
Stru_A::Stru_A()
{
memset(Name, 0, 30);
Age = 0;
}
Stru_A::Stru_A(char* inName, int inAge)
{
memset(Name, 0, 30);
strncpy(Name, inName, 29);
Age = inAge;
}
}*pStru_A;
pStru_A xyz = new Stru_A("ABC", 123);
Note also that you should use strncpy to be sure the copy doesn't overwrite the 30 character size you have, and still leaves space for the null terminator.
Hope that helps.
-- modified at 16:32 Thursday 21st December, 2006
Karl - WK5M
PP-ASEL-IA (N43CS)
PGP Key: 0xDB02E193
PGP Key Fingerprint: 8F06 5A2E 2735 892B 821C 871A 0411 94EA DB02 E193
|
|
|
|
|
krmed wrote: Note also that you should use strncpy to be sure the copy doesn't overwrite the 30 character size you have, and still leaves space for the null terminator.
You also will have to manually put that terminating NUL into the Name buffer - strncpy(...) will not place a terminating NUL if reaches the specified limit.
Peace!
-=- James If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong! Avoid driving a vehicle taller than you and remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road! DeleteFXPFiles & CheckFavorites (Please rate this post!)
|
|
|
|
|
Actually, since I have a memset to put a zero in all elements, manually adding a terminating NULL is not required - you'll notice I only copied 29 characters into the buffer in my example.
Karl - WK5M
PP-ASEL-IA (N43CS)
PGP Key: 0xDB02E193
PGP Key Fingerprint: 8F06 5A2E 2735 892B 821C 871A 0411 94EA DB02 E193
|
|
|
|