Wednesday, June 12, 2013

Simple C++ command-line parser for Windows

Because Windows doesn't have this built-in. Supports quotes. Remember that the first argument returned by GetCommandLine is the application itself.
// Where "tstring" is a typedef for basic_string of TCHAR
void ParseCommandLine (const TCHAR* args, OUT vector<tstring>& list)
{
  bool inQuotes = false;
 
  for (const TCHAR* p = args; *p;) {
    while (isspace(*p))
      p++;
    if (*p == '\0')
      return;

    // Scan to the end of the argument
    PCTSTR start;
    for (start = p; *p != '\0' && (inQuotes || !isspace(*p)); p++)
      if (*p == '"')
        inQuotes = !inQuotes;

    // Strip quotes if they are along the outside (e.g. the quotes are 
    // preserved for --out:"some thing" but stripped from "--out:some thing")
    if (*start == '"' && p[-1] == '"')
      list.push_back(tstring(start + 1, p - start - 2));
    else
      list.push_back(tstring(start, p - start));
   }
}
Usage:
vector<tstring> list;
ParseCommandLine(GetCommandLine(), list);

Friday, June 07, 2013

CImageList reduces 24-bit bitmaps to 16 colors

Lots of people have complained that their 256-color bitmaps are reduced to 16 colors in an ImageList. But the same thing happened to me with a true-color bitmap. The solution is the same; create the image list and load bitmap as separate steps:
// Create the full-color image list
// cx, cy = your icon width & height
// You could also use ILC_COLOR24 rather than ILC_COLOR32
CImageList imgl;
imgl.Create(cx, cy, ILC_MASK | ILC_COLOR32, 0, 0);

CBitmap bmp;
// Load your imagelist bitmap (bmp) here, however 
//   you feel like (e.g. CBitmap::LoadBitmap)

COLORREF rgbTransparentColor;
// Set up your transparent color as appropriate

// Add the bitmap into the image list
imgl.Add(&bmp, rgbTransparentColor);
Another thing that was a "gotcha" for me: CImageList actually modifies any bitmap you add to it, changing all "transparent color" pixels to black.

Finally a third "gotcha" is that you must use the ILC_MASK flag when you create the image list. Without this flag, the image list still changes all "transparent color" pixels to black (which is a preparation step for using mask-based transparency), but doesn't actually generate the mask, which causes ILD_TRANSPARENT and ILD_NORMAL modes to not work.

Monday, June 03, 2013

WinCE: unresolved external symbol ___security_cookie

In case it helps anyone else, I was getting tons of linker errors such as these on a TREQ (x86) unit, in LIBCMT and also in my own code:
LIBCMT.lib(ehprolg3.obj) : error LNK2001: unresolved external symbol ___security_cookie
LIBCMT.lib(exsup4.obj) : error LNK2001: unresolved external symbol ___security_cookie
LIBCMT.lib(sehprolg4.obj) : error LNK2001: unresolved external symbol ___security_cookie
LIBCMT.lib(ehprolg3.obj) : error LNK2001: unresolved external symbol @__security_check_cookie@4
LIBCMT.lib(exsup4.obj) : error LNK2001: unresolved external symbol @__security_check_cookie@4
LIBCMT.lib(sehprolg4.obj) : error LNK2001: unresolved external symbol @__security_check_cookie@4
atls.lib(atlbase.obj) : error LNK2001: unresolved external symbol _atexit
atls.lib(atlcommodule.obj) : error LNK2001: unresolved external symbol _atexit
It didn't make any sense because I had another project that linked fine, and I even changed the two projects until they were almost identical, and still: one project linked OK, the other gave dozens of linker errors.

The solution was: in project options under "General", change "Use of MFC" from "Use MFC in a Static Library" to "Use Standard Windows Libraries".

The working project was *actually using MFC* while the nonworking project was not. Somehow, linking to MFC without using it causes linker errors.