|
With very little work, I got the code to work in 6.0. For that reason, I will momentarily stop using .NET 2003 until absolutely necessary.
Thanks for your time!
Sean
|
|
|
|
|
Hi there,
I have this problem with two classes which need to access each other's methods. Allow me to exemplify:
<br />
class CBaseClass<br />
{<br />
public:<br />
CDerivedClass *pDerived;<br />
.<br />
:<br />
.<br />
};<br />
<br />
class CDerivedClass<br />
{<br />
public:<br />
CDerivedClass()<br />
{<br />
CBaseClass *pBaseClass;<br />
.<br />
:<br />
.<br />
};<br />
.<br />
:<br />
.<br />
};<br />
Now, as you may have guessed by now, I can't compile this as the compiler doesn't recognise CDerivedClass (it is declared after CBaseClass...).
I know this can be solved -- I just don't know how. Could you please give me a hand?
That would be much appreciated.
David
|
|
|
|
|
Use a declaration or move the CDerivedClass definition above CBaseClass'.
Example:
class CDerivedClass;<DIV>
class CBaseClass
{
public:
CDerivedClass* pDerived;
.
.
. This works. It's the same thing as using function declarations, e.g. header files, etc.. If you forget to write the CDerivedClass definition now, you'll get a linker error.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Thanks Antti, once again.
I did exactly like you said (which is very logical, now that I think about it), but it isn't working yet. This time I get different compiling errors:
m:\~alibrary\projects\vc++\xig1\v2.0\xig1view.h(27) : error C2027: use of undefined type 'CXiG1View'<br />
m:\~alibrary\projects\vc++\xig1\v2.0\xig1view.h(15) : see declaration of 'CXiG1View'<br />
m:\~alibrary\projects\vc++\xig1\v2.0\xig1view.h(27) : error C2065: 'classCXiG1View' : undeclared identifier<br />
m:\~alibrary\projects\vc++\xig1\v2.0\xig1view.h(35) : error C2027: use of undefined type 'CXiG1View'<br />
m:\~alibrary\projects\vc++\xig1\v2.0\xig1view.h(15) : see declaration of 'CXiG1View'<br />
m:\~alibrary\projects\vc++\xig1\v2.0\xig1view.h(35) : error C2227: left of '->pConsole' must point to class/struct/union<br />
m:\~alibrary\projects\vc++\xig1\v2.0\xig1view.h(35) : error C2227: left of '->Output' must point to class/struct/union
By the way:
CXiGView is a CFormView (and has a CPrompt object)
CPrompt is declared before CXiG1View (and is a custom control derived class)
I declared the classes in the following way now:
class CXiG1View;
class CPrompt : public CXCommandPrompt
{
public:
CPrompt()
{
CWnd *pParent;
.
:
.
};
class CXiG1View : public CFormView
{
.
:
.
What am I missing out here?
|
|
|
|
|
There seems to be nothing wrong with the declaration you posted. Perhaps there's a typo or a syntax error (missing semicolon or something) somewhere else in your file ? I would check the lines that the compiler is suggesting, and the lines above/below them for typos/errors.
Unfortunately I can't find the error for you, you just need to go through the file with a magnifying glass.
To avoid similar problems in the future, I would suggest you (or your company, whichever) to familiarize yourselves with the excellent "Visual Assist X" tool from Whole Tomato Software. It simplifies and helps coding. And A LOT that is
For a quick link, go here.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Thanks for all your help Antti! You have really been very helpful.
You can't imagine how tired I am; I'm having memory blocks [or loss, I don't know anymore!] due to the excessively coffee drank till now. I have been up for 21 hours now, non stop, working on this [new] project that just came up and, to complicate things even more, i've done MFC programming for only a month -- we're short on staff.
But thanks to you I have managed to finally put up all the pieces together (the custom controls I have been working on) and link/attach them to the CFormView-derived class.
Finally! Thank you very much Antti; I can finally go to bed (with some valuable lessons learned on the way -- hmm not too bad! )
David
PS: That tool you've mentioned before seems to be very interesting -- am going to give it a try tomorrow.
|
|
|
|
|
Hello,
I have been working on a project that interops between C# in .NET and unmanaged C++. Here's the jist: my main is in C++, and in it, i create an instance of an object made in C#. The C# is supposed to connect to the database, sort through the results and put the information into a bunch of arrays which are sent back to the C++ porition. While i got the two projects to connect and communicate somewhat, I am now having some issues with datatypes...or so i think.
Here's what i've got in C++:
...
double vd[100];
int vi[100];
string vs[100];
//send arrays to Read() method in C#
spConnNET->Read(vi, vd, vs);
The Read() method in C# looks like this:
...
public void Read(int[] intArray, double[] doubleArray, string[] stringArray)
{
while(reader.NextResult())
{
//THere will be other stuff here
reader.Read();
}
}//end Read()
when i try to compile in C++, this is the error i'm getting:
error C2664: 'DBConnection3::IConnection::Read' : cannot convert parameter 1 from 'int [100]' to 'SAFEARRAY *'
"SAFEARRAY"??!?! what the heck is that?? I thought it was "int, double, string"??
EDIT: I have tried looking up SAFEARRAY and whether it can be converted into an int/double/string and vice versa, but I don't fundamentally understand why this type conversion is taking place, what it means, what can be done...etc...
my apologies in advance for my newbie-ness...I would really appreciate some advice!
|
|
|
|
|
What is the fastest way to find whether a given file exists in my hard disk (any drive). I have only file name. It can be in any folder.
Thanks in advance.
|
|
|
|
|
|
|
This is evil. Are you sure you can't get a path, or at least some restrictions on where the file can be? Can you rethink the design? Sometimes you have to do something evil, but you should seriously consider if there is some other option before doing this.
I think you have to search every direcotry, one at a time, which as you can guess is not fast. Standard visit every node in a tree algorithm, see any textbook. Filesystems do not normally catch all the filenames on disk. (some will cache directory trees)
If you are getting data for a specific a user, then you should restrict your search to "My Documents" for that user, which will be much faster. (but you still need to look on floppys, USB keys, and other devices, or at least make is possible)
You might also be able to store something in the registry.
|
|
|
|
|
After a night of sleep I recalled that on unix there is often two command line tools that do this: locate and find. Locate builds a database (generally once a week), and searches the database (fast, but it won't find files after the last datebase update), and find searches the filesystem.
Either might be a starting place for what you want. (though others have since posted methods that I did not recall existing...) In particular locate might be better if you expect to do this often and can live with sometimes missing files created since the last database rebuild. FreeBSD might have BSD versions that you could copy. (but check, they might just use a GPL version)
|
|
|
|
|
|
Take a look at _taccess or _access in MSDN.
|
|
|
|
|
If your program will run on a system with IIS and some other widgets installed, you might be able to look into querying the indexing service.
See the MDSN topic "Indexing Service"
|
|
|
|
|
Hai,
Thanks a lot.I have another question.
in win32 I'm using GetDC() for drawing.For some reason I could'nt use WM_PAINT.
Now what happens is that my drawing gets erased when another window moves over or when I minimise or move my window.Can anyone suggest?
Thanks again in advance.
|
|
|
|
|
You need to redraw after all those situations (covering, minimizing etc..).. Why couldn't you use your drawing routine in the WM_PAINT handler?
Rob
Whoever said nothing's impossible never tried slamming a revolving door!
|
|
|
|
|
I'm new to Windows programming (not C/C++) and I'm having a hard time with all of the different string facilities. For example, I wanted to do a simple registry read, so I tried:
LPCTSTR strEntry = _T("SOFTWARE\\Microsoft\\...path...");
LPTSTR val;
ULONG max_size = 1024;
if ((retval = rc->QueryStringValue(strEntry,val,&max_size)) != ERROR_SUCCESS) { /* an error occurred */ ... }
Which dies. Apparently LPTSTR needs to be allocated, but I don't need an array of them (as one might with chars) so that wouldn't help.
I found a bunch of documentation on converting strings of various types, but I'd like to allocate one.
Thanks for the help.
|
|
|
|
|
You have to allocate memory for LPTSTR data types. LPTSTR is a pointer of type TCHAR, which in turn is a wchar_t. What is it exactly that you are trying to accomplish?
Maybe by declaring:
TCHAR val[SomeNumberHere];
might help you. I am not sure what you want to do.
// Afterall, I realized that even my comment lines have bugs
If the sun were to blow up, it would take us 7-8 minutes to realize it.
|
|
|
|
|
LPTSTR is a pointer to a string, so if you don't initialize it, it doesn't mean anything. Just saying
LPTSTR val;
is not enough, because then it would get allocated and point to some random memory location. You then must specify where it points to so that in your call to QueryStringValue() it has a referenced location to store the string.
One way to do this might be
LPCTSTR strEntry = _T("SOFTWARE\\Microsoft\\...path...");
TCHAR val[1024];
ULONG max_size = 1024;
if((retval = rc->QueryStringValue(strEntry, val &max_size)) != ERROR_SUCCESS
{
}
in this you are allocating an array to hold the string, then, you can assign it to a CString.
CString str = val;
Essentially the TCHAR array is a buffer of known length max_size. You use this buffer to collect the value string. Also, it should be noted that in the above example, you can use a CString instead of the LPCTSTR.
-- Adam
"If you can't beat your computer in chess, try kickboxing"
|
|
|
|
|
The trick here is to 'understand' what these Windows types are. If you searched through the Windows headers, you'd find the answers. But to make your job a little easier, here's a quickie for starters.
LPCTSTR == const TCHAR* == const char*
LPTSTR == TCHAR* == char* If you'd needed to create a string, the idea would be to use an LPTSTR and the new-operator to allocate memory for your string.
The idea is behind the ability to use the same variable types regardless of whether Unicode or ASCII/MBCS is in effect. For example, the following would use pure-Windows methods to initialize, utilize and destroy a string of characters, regardless of used character set:
_TCHAR* strName = new _TCHAR[20];
ZeroMemory(strName, SIZEOF(TCHAR) * 20);
_tcsncpy( strName, _T("My name is"), _tcsclen(_T("My name is")) );
delete strName; As you can see, programming while taking the character set in mind is a tad more difficult than standard C++.
For your code sample, the problem is that LPTSTR val would map to char* val , and you, in there, pass an uninitialized pointer to the function. No wonder it crashes
To play safe, use the new-operator to initialize say 50-60 characters, and pass this pointer to the function. Should work smoothly.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Thanks. That was a great help and I was able to get it working.
In what header should I be able to find the typedefs? I looked at "Windows Data Types" and now that I know, I can see how I could have determined that it was a char* (with _UNICODE not defined), but I would love to know where most things are going to be defined.
|
|
|
|
|
Most of the character mappings can be found from 'winnt.h' file.
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
If you want to know where something is defined, right click on it and select "Go to definition" from the popup menu.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it!
|
|
|
|
|
Couple of links:
The complete guide to C++ strings, part I[^]
The complete guide to C++ strings, part II[^]
Basically, LPxSTR is a typedef for xCHAR*, i.e. LPTSTR is a typedef for TCHAR* , LPSTR for CHAR*, and LPWSTR for WCHAR*. If it has a C in it, it's a const : LPCSTR is const CHAR* .
So what are CHAR, WCHAR and TCHAR? CHAR is simply a typedef for char. Don't know why they did that. WCHAR is a typedef for wchar_t which on earlier compilers is a typedef for unsigned short .
TCHAR is where it gets interesting. The meaning of TCHAR depends on whether UNICODE is defined or not. If UNICODE is not defined, TCHAR is CHAR. If UNICODE is defined, TCHAR is WCHAR. With the addition of suitable macros (such as the _T you use) a program can be mostly adapted between ANSI and UNICODE builds with few source code changes.
Anyway, after all that, LPTSTR is equivalent to WCHAR* in UNICODE builds and char* in ANSI builds. Use whatever memory allocation seems appropriate.
Stability. What an interesting concept. -- Chris Maunder
|
|
|
|
|