Archive for the ‘programming’ Category

Useful function: EnableWindowsDependingOn

Monday, March 21st, 2011

One of my favorite internal functions. It helps my manage my app’s GUI. Checkboxes that cause their sub-elements to be greyed out when not checked can be easily handled by this:

bool EnableWindowsDependingOn (CWnd *pParent, DWORD DependingOnThisCheckbox, DWORD Value1, ...)
{
 va_list marker;

 bool bState = (((CButton*)pParent->GetDlgItem(DependingOnThisCheckbox))->GetCheck()!=0);

 DWORD i=Value1;
 va_start (marker, Value1);
 while (i != 0)
 {
 if (i<=0xffff)
 {
 if (pParent->GetDlgItem(i))
 pParent->GetDlgItem(i)->EnableWindow (bState);
 }
 else
 ((CWnd*)i)->EnableWindow (bState);

 i = va_arg (marker, long);
 }
 va_end (marker);

 return (bState);
}

It accepts the “this-pointer” of your CDialog and the id of the master checkbox. Then you can append any number of sub-element ids or pointers. And finally a NULL. Example:
EnableWindowsDependingOn (this, IDC_CHECK1, IDC_EDIT1, IDC_EDIT2, NULL);

This would enable the two edit boxes if the checkbox is enabled.

Win+Tab in Debugging

Friday, December 31st, 2010

Placing a breakpoint can be dangerous. In some code sections, like drawing a menu, Windows doesn’t like to be interrupted. The debugger will stop your application, but your app will remain on-screen and Alt+Tab and all other options of changing the current application are blocked.

Except, if you’re using Windows 7.

For some reason the 3d-flipping mode with Win+Tab still works. And allows you to switch to the debugger.

Devloping asp.NET websites in 3 simple steps…

Tuesday, December 7th, 2010

Step 1: Waste hours researching to find out how to do something trivial. (Like renaming the insert link)

Step 2: Curse Microsoft

Step 3: Throw out the MS way and program it yourself.

Repeat for every trivial issue.

Visual Studio 2005: Speeding up compiles

Tuesday, October 19th, 2010

There’s a hidden switch in Visual Studio 2005 while doubles compile speed.

I know, it sounds ridiculous.  But I’ve tested it. It’s MUCH faster now. The switch works by enabling multi-core processing. I have no idea why Microsoft has hidden this, instead of making it a big, obvious feature.

Anyways. You can enable it by adding /MP to the “Additional options” in “Configuration properties > C/C++ > Commandline”.

(Found it at 1 and 2)

Dangerous CFile::GetStatus

Friday, October 1st, 2010

The third (and I hope final) dangerous posting.

This code looks harmless enough:

CFileStatus rStatus;
CFile::GetStatus (MyFilename, rStatus);

And it will work most of the time. But CFileStatus uses CTime, which is limited to dates after 1.1.1970. If you apply this code to a file with a file-modification date of e.g. 1.1.1960, GetStatus will raise an exception. (Which it isn’t documented to to.) And if you don’t catch that, it will terminate your program.

Dangerous printf

Friday, September 17th, 2010

It took quite some time until I found this bug. Here’s a simplified version of what caused it:

char dir[2048];
GetCurrentDirectory(2048, dir);
printf(CString("Current dir is:")+dir));

That’s doesn’t look bad, does it? And (like in the great programmer quotes), it works on my computer. But it doesn’t work if the customer’s current folder is something like “%&§something”, because it contains %s.

So don’t throw any external data at the first parameter of printf, sprintf, etc; instead put it into the following parameters.

printf(“Current dir is: %s”, dir);

Dangerous COleDateTime::ParseDateTime

Friday, August 20th, 2010

COleDateTime::ParseDateTime is a handy function to parse a date string into a COleDateTime (and then SYSTEMTIME and then CTime).

The problem is that the expected date format depends on the user’s system settings. If you’re parsing a string that is always in the same format (from a file or from the internet), then parsing might work on your computer, but fail on the customer’s computer (in another country).

Solution: Use the locale ID parameter to force the parsing language.

CMap: Mapping CString to CStringArray

Monday, August 9th, 2010

Just a simple MFC trick. To map from CString to CStringArray use:

CMap<CString, LPCTSTR, CStringArrayX, CStringArrayX&>

where CStringArrayX is defined as:

class CStringArrayX : public CStringArray
{
 public:
 CStringArrayX() {}
 CStringArrayX(const CStringArrayX &qSource);
 CStringArrayX &operator = (const CStringArrayX &qSource);
};
CStringArrayX::CStringArrayX (const CStringArrayX &qSource)
{
 SetSize (qSource.GetSize());

 for (long c=qSource.GetSize()-1; c>=0; c--)
   (*this)[c]=qSource[c];
}
CStringArrayX &CStringArrayX::operator = (const CStringArrayX &qSource)
{
 SetSize (qSource.GetSize());
 for (long c=qSource.GetSize()-1; c>=0; c--)
   (*this)[c]=qSource[c];
 return (*this);
}

Hopefully this post keeps some people from searching as long as I did… 😉

Silencing command line builds

Monday, August 2nd, 2010

My builds have become more and more complex. Especially when releasing a new version it wasn’t always easy to tell at first glance whether all build steps succeeded. Some tools (I’m not telling names, here) are quite verbose and “pollute” the build log with things that I don’t really care about.

Here’s a simple freeware tool that I wrote to fix this: SilentCommandline.exe. It works as a DOS pipe with filter functions that can be configured in two external text files.

Using SilentCommandline:

Simply append it to your build batch files:

yourbuildcommand.exe |SilentCommandline.exe

It will take all output of  yourbuildcommand.exe, check if you want to see it and print it to stdout. To configure what you want to see, create 2 text files in the same folder where you keep SilentComandline.exe and name them silentlines.txt and silentlinesre.txt.

Config files:

The first one is simple. On string per line. If one of the strings equals a line from your build output, then this line will not be printed. You can use that for static texts that are always the same. Example:

Succeeded

The second file works basically the same, but allows you to use regular expressions in each line. Use it to handle build outputs that might change. Example:

Protected[0-9]* blocks of [0-9]* blocks total.

Download:

Here’s the download link to SilentCommandLine.exe

System requirements: Windows

Linking .lib files in C++

Thursday, July 22nd, 2010

Sooner or later you will need to link static external library files (.lib files), when developing a larger project. Microsoft C++ can do this in several ways:

  1. Link settings in the project properties
  2. Adding the file to the source file tree
  3. Using a #pragma

So far I’ve mostly used 1 & 2, because they’re the easiest and most obvious ways. Solution 2 can even be used conditionally for certain build types (by using the “exclude for this build” option).

But with the projects getting more complex, I found that solution 3 is the best and switched projects to that. The reason is that different combinations of project types (debug/release 32/64 Bit) are otherwise quite difficult  to handle.

With #pragma’s is does take some space in one your .cpp-files, but at least the different conditions are easy to understand and verify:

#ifdef _WIN64
  #ifdef _DEBUG
    #pragma comment(lib, "C:\MyPath\\MyDebug64.lib")
  #else
    #pragma comment(lib, "C:\MyPath\\MyRelease64.lib")
  #endif
#else
  #ifdef _DEBUG
    #pragma comment(lib, "C:\MyPath\\MyDebug32.lib")
  #else
    #pragma comment(lib, "C:\MyPath\\MyRelease32.lib")
  #endif
#endif