Forum Chat


Mar23,13:31 Johan Marechal
Wees gegroet
Sep20,17:50 Vicente Duque
Kim, Martin, Others :...
Jul07,11:10 Johan Marechal
PGP 9
Jul05,21:13 martin
Fastest in the bush
Jul05,07:48 martin
Spamdexing
Jun28,21:16 martin
New domain / new blog!
Jun28,21:11 martin
On posting etiquette

VC++ 6 items

Comment on this article

Visual Studio
  ClassView, Intellisense and #ifdef/#ifndef

Linking
 
unresolved external _main

MFC
 
MFC in ATL
  Userdefined messages

ATL
  InlineIsEqualGUID
 Using SAFEARRAY in IDL

ActiveX
  Centura 1.5.x

STL
  tellg


Visual Studio

ClassView, Intelli(non)sense and #ifdef/#ifndef

There are several ways of making sure a header file isn't read more than once. The way I just chose screws up both intellisense and the classview pane; all classes simply disappear. There's a knowledgebase article (Q190965) that sheds some light on some very weird implementation issues with intellisense that seems to explain it. What it boils down to is that any #ifdef and #ifndef are checked in the header files, then the environment goes out to check if the macro in the #ifdef/#ifndef is in your project settings. If not, the #ifdef/#ifndef is regarded as true and everything from there to the matching #else or #endif is included both for intellisense and for the classview, but everything after the #else is ignored (the text from the article says a lot: "If the macro is undefined in the project, IntelliSense displays information for the first function, regardless of whether #ifdef or #ifndef is used.") Now get this straight: I'm not being sloppy is saying "the #ifdef/#ifndef is regarded as true"... that's exactly what happens and it's by design. Oh, my gawd... nobody even tried to interpret #ifndef as the opposite of #ifdef! But #else flips the meaning. What an interesting interpretation of logic this one is. So, in this example, the class disappears from classview and intellisense:

// myClass.h
//
#ifdef MYCLASS_H
#pragma message("--* myClass.h already included")
#else
#define MYCLASS_H
... here's the core of the file
#endif

...but this works:

// myClass.h
//
#ifndef MYCLASS_H
#define MYCLASS_H
... here's the core of the file
#else
#pragma message("--* myClass.h already included")
#endif

I'm usually impressed with mickeysoft. Right now I'm not. That I only discovered this little "feature" after fixing up 100+ header files according to the first pattern above, may have something to do with it.

Linking problems

unresolved external _main

This can happen when compiling for Unicode MinDependency. Solution: in settings for Unicode MinDependency, remove the commandline switch "/D ATL_MIN_CRT".

MFC

MFC support for ATL .EXE projects

To add MFC support in ATL EXE projects, check out the following knowledgebase articles: Q181505, Q173974, Q166480. The following is the essential text from Q181505 and seems to work (note my change; there's a pretty daft error in the original text and if not changed, you'll get 'CoInitializeSecurity undefined' errors during compile):

  1. Open the ATL project with Visual C++.
  2. On the Project menu, click Settings.
  3. Under the General tab, set the Microsoft Foundation Classes field to "Use MFC in a Shared DLL" or "Use MFC in a Static Library". Click OK.
  4. Open the project StdAfx.h header file. Add the following line after "#define STRICT" after #define _ATL_APARTMENT_TREADED (or similar) and before include <atlbase.h>, then save and close the file:
          #include <afxdisp.h> 
  5. Open the project .rc source file in text mode for editing:
    1. On the File menu, click Open.
    2. Highlight the <projectname>.rc file.
    3. Set the Open As field to "Text", then click Open.
    4. Click OK on any resulting message boxes.
  6. Replace all occurrences of Winres.h with Afxres.h in the .rc file, then save and close the file.
  7. Delete the <projectname>.clw file if it already exists.
  8. Invoke ClassWizard by clicking ClassWizard on the View menu. Click Yes when prompted to rebuild the ClassWizard database, and then click OK on the next dialog box.

MFC class files added with ClassView or ClassWizard should now build without errors.

User-defined messages

Handlers declared using:

ON_MESSAGE(WM_USER_SOMETHING, OnSomething)

get a prototype of:

afx_msg LRESULT OnSomething(WPARAM, LPARAM);

The returned LRESULT is returned to the called through SendMessage (and presumably lost through PostMessage), so by convention, return 0 if there's no particular reason to return something else.

ATL

InlineIsEqualGUID ambiguous

If you get loads of "InlineIsEqualGUID is ambiguous" errors, you've got a problem with the atlbase.h header file coming from the VC include libs, and the guiddefs.h file coming from the platform sdk. Then some namespace confusion, and you're on a roll. Fix: change the include <atlbase.h> in the stdafx.h to point to the platform sdk version, like:

// #include <atlbase.h>   drop this one, replace with:
#include </program files/microsoft platform sdk/include/atl30/atlbase.h>

See Q243298 for more details.

Using SAFEARRAY's in IDL

When you want to use SAFEARRAYs in IDL, and you add them using the "Add Method..." wizard, things go wrong. For example, adding a prototype like:

SomeFunc([in] LONG lX, [in,out] SAFEARRAY(BSTR)* psaNames)

...results in the correct IDL syntax (same as above) but results in truncated function declarations and definitions in the class header and cpp files (or sometimes simply wrong prototypes like SAFEARRAY(BSTR)*... that simply don't work outside IDL files). You need to dress those up as follows (adding the red parts in this particular example):

HRESULT SomeFunc(/*[in]*/ LONG lX, /*[in,out]*/ SAFEARRAY** ppsaNames);

ActiveX

Centura 1.5.x

If your ActiveX object doesn't have a "MiscStatus" set, and set right, in the registry, Centura goes really weird. No errors, but doesn't do anything with the control. To know what the flags in MiscStatus mean, check out the OLEMISC structure. For reasonable examples, check out this:

.
.
ForceRemove 'Control'
ForceRemove 'Insertable'
ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 104'
'MiscStatus' = s '0'
{
  '1' = s '132497'
}
'TypeLib' = s '{00500881-B651-11D4-9DF6-006097BAB7CE}'
.
. 

That magic number '132497' is suitable for a full control, invisible at runtime. For a runtime visible control, it can be '131473'. Instead of figuring out this by hand, create a new ATL object with the desired properties, then go read the wizard produced *.rgs file.

STL

tellg

Bad code:

std::ifstream is;
char* buf[1024];
is.open("test");
while(!is.eof()) {
  std::streampos pos = is.tellg();
  is.getline(buf, 1024);
}

The "funny" thing is that if the file contains any linefeeds where there should be CR/FL pairs and it is opened in (default) text mode, the tellg() call screws up the next read position! Amazing, but true. One would have expected something called "tell..." to not change what it's telling you about, but not so. If you want to avoid obscure bugs, don't rely on the files always having correct CR/LF pairs, but open the stream in binary mode, like so:

is.open("test", std::ios::binary);

Of course, you then have to strip the CR's and LF's from the returned strings yourself. This is how I do it:

for (int i = strlen(m_buf) - 1; i >= 0; i--)
{
  if (m_buf[i] != 0x0A && m_buf[i] != 0x0D) break;
  m_buf[i] = '\0';
}

Comment on this article

TOP