Archive for the ‘C++’ Category

Dangerous MakeLower

Thursday, May 2nd, 2013

Got weird crashes at customers with foreign languages? Microsoft’s MFC’s MakeLower could be the culprit. Seems to be poorly written because it can crash if it doesn’t like the string. I could even reproduce it here by switching the Windows-Locale for non-unicode apps the Japanese and process some strings contains German umlauts. Bottom-line? Don’t use, write your own… :-(

Using Visual Studio 2012… Safely…

Thursday, January 10th, 2013

Microsoft Visual Studio 2012 isn’t so bad. ;-) I actually even like new dark looks. But (for C++) you shouldn’t use the default settings, our you’ll get problems with your older customers.

 

1. Making it run with XP

Go to “configuration properties > general” and switch the “Platform toolset” to “Visual Studio 2012 – Windows XP (v110_xp)”.

 

2. Making it run on older systems

This caused me hours of work. By default VS2012 will “optimize” fp-operations. But it doesn’t work on all systems. Don’t know if it’s the older processors but I had at least 2 customers where a simple statement as “myfpvar=1″ caused the program to terminate without error message. To fix this go to “C++> Code generation” and set “Enable enhanced instruction set” to “No Enhanced Instructions (/arch:IA32)”.

Weird TextOut Unicode problems

Friday, October 26th, 2012

After porting Easy2Sync for Files to Unicode I experienced some really weird problems with some foreign characters. Unicode in general worked, Japanese characters were displayed nicely (not that I could read them). But Cyrillic characters failed when printed with TextOut and were displayed as small black rectangles.

Even weirder: Adding just 1 Japanese character to a string with Cyrillic characters caused the entire string to be printed right.

It seems that TextOut is only 50% Unicode compatible (of course Microsoft doesn’t mention this). So one has to use DrawText instead, which doesn’t seem to have these limitations. Since DrawText behaves differently regarding the position and background drawing, here’s a wrapper which fixes this and makes it behave like ExtTextOut:

void FixedExtTextOut (CDC *pDC, int x, int y, UINT nOptions, LPCRECT lpRect, LPCTSTR lpszString, UINT nCount, LPINT lpDxWidths)
{
 CRect rr(x, y, lpRect->right, lpRect->bottom);

 pDC->FillSolidRect(lpRect, pDC->GetBkColor());
 pDC->DrawText(lpszString, nCount, &rr, 0);
}

You’re not gonna catch this…

Thursday, June 14th, 2012

You're not gonna catch this... (LIttle League baseball, May 2009 - 03 by Ed Yourdon; CC BY-SA 2.0)

C++ exceptions can be surprising. This works easily:

try
{
throw(1);
}
catch(…) //Catch all
{
//caught
}

But if you replace “throw(1);” with “throw;”, it suddenly doesn’t work anymore. Code compiles, exception is thrown, but it’s not caught. The program is terminated

MFC: Redirecting OnMouseWheel messages to the window under cursor

Wednesday, June 6th, 2012

By default MFC applies the MouseWheel message to the window that has the focus. Even though most users expect it to apply to the window under the cursor. (And even Microsoft’s style guide recommends that.)

To fix this, override the program’s PreTranslateMessage  function and add this:

 if (pMsg->message==WM_MOUSEWHEEL)
 {
    CPoint point;
    GetCursorPos (&point);

    HWND hWnd = ::WindowFromPoint (point);

    if (hWnd && pMsg->hwnd!=hWnd)
    {
       ::PostMessage(hWnd, pMsg->message, pMsg->wParam, pMsg->lParam);
       return(true);
    }
 }

Please note that you have to add this  before calling the default implementation of PreTranslateMessage.

Turning off floating point exceptions against crashes

Friday, June 1st, 2012

It sounds quite mad, but either of these lines can crash a program: (C++, Visual Studio 2005)

long x = long(my_float_var);
float f = exp(my_float_var);

If the number is too large/small, the program is terminated. (No, try/catch doesn’t help.) And to make it even stranger, this happens only on some computers. And of course it happened on the customer’s computer and not on mine…

To fix this, it helps to turn off the floating point exceptions:
control87(_EM_INVALID|_EM_DENORMAL|_EM_ZERODIVIDE|_EM_OVERFLOW|_EM_UNDERFLOW|_EM_INEXACT, _MCW_EM);

Of course the problem of the large number still exists, but now the program at least continues to run, and I have a chance to handle it.

EnumResourceNames + RT_STRING

Friday, May 4th, 2012

It sounds pretty straightforward to enumerate the resources  in a file. But it turned out to be rather a lot of work (and waste of time), since the MS doesn’t tell you, that it doesn’t enumerate the strings, but blocks of strings in a binary format that you have to process yourself.

Here’s how to do it:

BOOL CALLBACK EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG_PTR lParam)
{
 switch ((int)lpszType)
 {
 case RT_STRING:
 {
 HRSRC hRes = FindResourceEx(hModule, RT_STRING, MAKEINTRESOURCE(lpszName), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));

 if (hRes)
 {
 HGLOBAL hGlo = LoadResource(hModule, hRes);
 LPCWSTR lpStr = (LPCWSTR)LockResource(hGlo);
 DWORD dwsize = SizeofResource(hModule, hRes);

 long count=0;
 for (int i=0; i < (int)dwsize; i++)
 {
 count++;
 if (count>=16)
 break;

 if (lpStr[i])
 {
 WORD *pString = lpStr+i+1;
 long lString = lpStr[i];

 //Process string here

 i += lpStr[i];
 }
 }
 }
 }
 break;
 }

 return(TRUE);
}

EnumResourceNames(hModule, RT_STRING, &EnumResNameProc, NULL);

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.

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.