Archive for C / C++

Convert Guid To String

Having been pampered by C#, where Guid to string is so trivial, I had to return to an older c++ project and achieve the same thing. Just how hard can it be ? I mean, there’s even a StringFromCLISD function. True, no example of how to use it on MSDN and as with so many API calls the returned information is always in exactly the wrong format  - in this case OleStr. But we can fix that can’t we: Read more

strcpy_s / wcscpy_s – DONT DO IT!

The good old strcpy never checked the destination buffer size. And today that is considered a Bad Thing – and I think I agree. Indeed, later versions of Visual Studio will refuse to compile this (and related) functions unless you add a predefined _CRT_SECURE_NO_WARNINGS.

So, in theory, the introduction of strcpy_s which DOES check buffer size is a Good Thing. Or so you would think. But what happens if the destination buffer _is_ too small ? Read more

Mixed C++ and C# Projects – Post Build Events

I suspect nobody at at Microsoft deals with projects which contain a mix of C++ and C# code (typically this might be a C++ DLL called from a C# .NET UI). If they did, they’d very quickly realise the stupidity of not copying the C++ project output into the C# project’s output directory.

You might expect that adding the C++ project to the C# project as a dependency would make it plain to the Visual Studio IDE that perhaps it really ought to consider ensuring the latest C++ DLL appears in teh C# project’s target directory. But no, it does nothing (and is why I’ve tagged this as a Visual Studio Bug).

You can of course create a post build event in the C# project to copy the C++ DLL into the target directory. But if you modify the C++ DLL, the C# project doesn’t think it needs to build, ergo, does not run build events. Understandable – but annoying.

One “fix” would be to have the C++ project, as part of its post build, write to a skeleton .cs file that does nothing but is part of the C# project. Then the C# project THINKS its been modified and runs its post build where you then copy the C++ DLL across.

Not brilliant.But the skeleton file will then have a later date/time than the last C# project build date time and the C# project will build again – very quickly too since almost nothing has changed.

But that suggested another solution of sorts. Create a file – any file – lets say a text file. Set its date/time to way into the future, like 2050 or something, make it write-protected and add it to the C# solution with the properties of “build action = none” and “do not copy” to output. The project now has a file that is always dated after the last build so always builds, always runs the post-build event in which you can always ensure the latest C++ DLL gets copied to the target directory.

With luck, the only thing you need to remember is to restore the file date/time whenever the text file is re-created when restoring from, say, subversion.

 

C++ : Difference between ‘new’ and direct instantiation. Gotcha !

Seems a common question,

CMyClass *pMyClass = new CMyClass();

verses

CMyClass myClass;

Well one obvious difference is you use the ‘->’ operator to access pMyClass but use ‘.’ for myClass. But I guess you already new that. And, of course, you’ll need to remember to delete pMyClass when you finished with it whereas with myClass it is automatically deleted when it goes out of scope. But you probably knew that as well – and I bet forgot it a few times too :) And real anoraks know one gets allocated on the heap and one on the stack but that’s too much information.

What if CMyClass’ constructor required a string ?

CMyClass *pMyClass = new CMyClass( _T(“Yawn!”) );

verses

CMyClass myClass( _T(“Yawn”) );

Again, no difference.

Now for the gotcha. Lets use the class in a real function:

void MyFunction(LPCWSTR wszWideCharString)

{

CMyClass myClass(CW2CT(wszWideCharString));

myClass.DoSomeCleverStuff();
}

[If you are wondering, CW2CT is a macro to convert from wide string to 'T' string]

Suddenly, it appears you cant access any functions or variables in myClass ! WTF !?

myClass.DoSomeCleverFunction() fails to compile as “expression must have class type”.

Have you sussed it yet ? Well, the macro is defined/implemented as a class which has an implicit conversion to an LPCTSTR, but the compiler doesn’t know about this conversion (how _would_ it know) and so the compiler interprets

CMyClass myClass(CW2CT(wszWideCharString))

as, in fact,  a function prototype !

In this instance, you can force the conversion to take place by casting the CW2CT :

CMyClass myClass( (LPCTSTR)CW2CT(wszWideCharString));

Now it works as expected.

So the motto is : when instantiating a class whose constructor has one or more parameters you should avoid using any macros in the constructor unless you can gaurentee their implementation wont confuse the compiler – specifically your own macros are fine but avoid third party ones.

 

 

MFC form view projects – start maximised.

This bug is still in VS2012 just as it was in VS2008.

Create an MFC application, single document, using CFormView and tick the box that should configure your app to start maximised.

You can use this as a basis for a random number generator – it may start physically maximised, it may not, though it always _thinks_ its maximised.

To overcome this bug you must NOT tick that start-maximised check box when creating the project. Instead, you need to override the main frame’s ActivateView and replace

CFrameWnd::ActivateFrame(nCmdShow);

with

CFrameWnd::ActivateFrame(SW_MAXIMIZE);

Simples !

——–

To override ActivateView :

If using ye olde Visual-C 6, just use class wizard. So easy. Otherwise:

Open the header file, position the cursor exactly in the class name itself (CMainFrame), then either:

(<VS2012) Click on the little box on the RHS of the header on the properties panel and scroll down to ActivateFrame which would be great if you could just double-click it instead of fiddle with stupid combo box drop down.

(VS2012) Stare at the properties panel, wonder why its blank, swear profusely, swear some more, wait 30 seconds for whatever background process is running to do its job, a-ha!, properties suddenly appear, now click on the little box on the RHS of the header on the properties panel and scroll down to ActivateFrame which would be great if you could just double-click it instead of fiddle with stupid combo box drop down.