Hottest Forum Q&A on CodeGuru - week of March 1st, 2004
Introduction:
Lots of hot topics are covered in the Discussion Forums on CodeGuru. If you missed the forums this week, you missed some interesting ways to solve a problem. Some of the hot topics this week include:
- Why does my automation control does not work properly?
- Why do I get the error: Can't open afxhelp.hm?
- Why do my Overloading -> and * operator not work properly?
- How can I textout the value of a pointer of an array?
|
Johndc has some problems with his automation control. It worked before adding a simple resource to the project. But now, it does not! Do you know what the problem can be?
I have a problem with my automation program. I created a new MFC DLL by using the VS6 MFC AppWizard (DLL) and started building my automation control. I tested my program by loading my automation and everything was working fine. Then, I added a resource to my project and my automation control has not been working since. I did some research and found that the link file myprogram.res had changed size to less than before. I opened the old one and compared it with the new file that was created when I compiled and found that a type "TYPELIB" was missing. Can anyone tell me what that "TYPELIB" type is and why my automation control does not work anymore? BTW, the DLL gets registered fine. It's just when I try to use it it will the error with "Could not load the selected Type Library"... appear.
This is a very interesting question. How can this happen that a simple resource causes such a problem? Sam Hobbs suggests the following:
"I think you need to add a class. I don't know what you need to do to make the class support Automation, but you need to do that somehow. However you do it, you should use ClassWizard to create the class. Then, use the Automation tab of the ClassWizard to add properties and/or methods. I am nearly certain that the type library will be created automatically when you do that."
|
d0153030 is working on project that works perfectly. But, he still gets one error.
I am getting the following error while compiling the project. Still, the program is executing fine. No problem. (Why) and how can I remove this error:
--------------Configuration: Project - Win32 Debug--------------- Making help file... hlp\Project.hpj(1) : error: Microsoft (R) Help Compiler HCRTF 4.03.0002 Copyright (c) Microsoft Corp 1990 - 1995. All rights reserved. project.hpj HC5011: Error: Project.hpj : Cannot open the file "afxhelp.hm." Project.exe - 2 error(s), 0 warning(s)
Well, that requires the afxhelp.hm file to be included. It is generated by app wizard hpj (help project file) that contains an include statement that should be a fully qualified path, not just a filename.
If this is generated without a full path, you probably have a problem with a Registry entry.
You have two choices:
- One is to correct the problem manually by editing the #include line.
Help Workshop does not use the INCLUDE environment variable to search for files. You have to specify the full path. It should look like this:
#include <C:\Microsoft Visual Studio\VC98\MFC\include\afxhelp.hm>
unless you have changed install defaults. - A second choice would be checking the Registry:
HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\General
This contains a MFCPath32Bit key with the value set to a MFC folder path, something like this:
C:\Program Files\Microsoft Visual Studio\VC98\MFC
Note: If you have changed the install defaults, you would have to adjust path the appropriately; otherwise, it will not work!
|
iangoldby does have some problems with overloading of the -> and * pointer. Take a look at his interesting problem.
I have a strange problem with overloading the -> and * operators. I'm trying to do this to make dereferencing a pointer to the class intrinsically safe. I think the problem is the same in both cases, so I'll describe the * operator: In myreal.h:
const CMyReal& operator * (void);
and in myreal.cpp
const CMyReal& CMyReal::operator * (void)
{
if (this)
return *this;
else
return CMyReal::Bad;
}
where CMyReal::Bad is a static object representing Not-A-Number. Now, when I write:
CMyReal *myreal = NULL; float x = (myreal->operator *()).value();
it calls my overloaded operator function and I get Not-A-Number, as expected. But if I write the following code:
float x = (*myreal).value();
It doesn't call the overloaded operator function but tries to dereference the NULL pointer directly and I get an access violation error. Similarly, (myreal->operator ->())->value() is okay, but myreal->value() fails with an access violation. Any idea what I am doing wrong?
Unfortunately, your override of operator * in your CMyReal class only affects the use of a * when you have an object of the CMyReal type. You are trying to use it on a pointer to a CMyReal, which is not the same type.
As soon as you introduce a raw pointer, you aren't going to be able to override the operator * and get a dereference of the raw pointer to call your overridden routine.
I don't know whether this is at all useful to you, but you could wrap the pointer inside of a class—something like this:
class CMyRealPtr
{
private:
static CMyReal Bad;
CMyReal* m_ptr;
public:
CMyRealPtr( CMyReal* ptr = NULL ) : m_ptr( ptr ) {}
const CMyReal& operator*()
{
if ( m_ptr )
return *m_ptr;
return Bad;
}
};
CMyReal CMyRealPtr::Bad( -1 );
int main()
{
CMyRealPtr myreal = NULL;
float x = (myreal.operator *()).value();
float y = (*myreal).value();
return 0;
}
Now, the pointer is not a raw pointer anymore, but instead is an object. The explicit call to operator * and the dereference of the myreal object both call the operator* member of CMyRealPtr.
Thanks to jwbarton for his beautiful explanation.
|
lwong is curious about the usage of a pointer of an array with the TextOut function.
How do I textout the value of a pointer of an array?
You need a pointer to a char array and x and y values that represent the upper left corner of where the text will be displayed.
CClientDC dc(this); char *Text=new char[128]; strcpy(Text,"Test string"); dc.TextOut(10,10,Text,strlen(Text)); delete []Text;
The above would display the 'Test string' string 10 pixels from the top and 10 pixels from the left of the client area defined by the DC.
CClientDC dc(this); CRect WndRect; GetClientRect(&WndRect); char* Text=new char[128]; strcpy(Text,"Test string"); CFont NewFont; NewFont.CreatePointFont(100,"Courier New",&DC); CFont * OldFont=dc.SelectObject(&NewFont); CSize TextSize=dc.GetTextExtent(Text,strlen(Text)); CPoint TextPoint; TextPoint.cx=(WndRect.CenterPoint().x-(TextSize.cx/2)); TextPoint.cy=(WndRect.CenterPoint().y-(TextSize.cy/2)); dc.TextOut(TextPoint.cx,TextPoint.cy,Text,strlen(Text)); dc.SelectObject(OldFont); delete []Text;
The above would display the string 'Test string' in the center of the client area in a Courier New font with a point size of 10.
Unfortunately, the pointer of an array is not of the char type; instead, it is a float. How do you convert between them? And, what about CClientDC dc(this)? Does that lead to flickering?
Take a look at the full thread to get the answer.

Thread:
Comments
Can we create editable list control in MFC?
Posted by ketu0001 on 10/22/2007 04:18am