In the Windows XP login screen, the password text box will warn you with a balloon tooltip if you accidentally turn Caps Lock on. The balloon tooltip appears to be a Windows tooltip common control with the TTS_BALLOON style.
To replicate this functionality, I decided to write a function called ShowMsgBalloon() which, given a control and the various balloon tooltip parameters, creates and shows the balloon tooltip below the control.
Read more...
Let’s say you have the following function:
1 2 3 4 void AppendChar(std::string& s, char ch) { s += ch; } What happens if this function is exported as an ordinal function from a DLL (not an inlined piece of code inside a header) and you call it from an EXE?
It works most of the time. When it doesn’t, it corrupts your heap and causes a spectacular mess.
In Windows you must free memory with the same allocator that allocated it.
Read more...
To convert a HFONT to a LOGFONT, use the GDI function GetObject(), as in:
1 2 3 LOGFONT lf; int ret = GetObject(hfont, sizeof(lf), &lf); // Be sure to check the return value of GetObject The code is trivial but the function took me forever to find.
Microsoft has created a new, lightweight C++ XML processing library called XmlLite. It includes a streaming XML writing class patterned after .NET’s System.Xml.XmlWriter.
This library makes the IXmlWriter in Implementing IXmlWriter Series obsolete for Windows developers.
While Windows supports dozens or even hundreds of languages, its localization APIs require quite a bit of getting used to. Below is how I solved some common problems related to formatting and parsing a number for a specific locale.
Formatting a Number for a Locale The function GetNumberFormat() formats a number for a particular locale. Its simplest usage looks something like:
1 2 3 4 5 6 7 8 9 10 11 12 13 #define ARRAYSIZE(x) ( sizeof(x) / sizeof(x[0]) ) TCHAR buf[80]; int ret = GetNumberFormat ( LOCALE_USER_DEFAULT, // locale 0, // dwFlags TEXT("1234567.
Read more...
Windows Vista developers beware: Vista does not perform file virtualization on the creation of shell links. Consider the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 // Creates a shell link (a.k.a. shortcut) located at swzLinkFile that points to // szTargetFile with a description of szDescription.
Read more...
Windows C++ developers remain all too familiar with the standard Windows crash dialog. This post is an attempt to teach developers how to understand the data the crash dialog reports to diagnose difficult issues. A basic understanding of assembly language is assumed; for more background on these topics please read Matt Pietrek’s “Under The Hood” articles in the Microsoft Systems Journal February 1998 and June 1998 issues.
To begin with, let’s write an application that crashes with a null pointer dereference:
Read more...
Apparently Microsoft has an API for just about everything. Today I read about Microsoft’s Delta Compression Application Programming Interface, an API for creating and applying binary diffs. This API looks ideal for building an application’s incremental online update facility.
The Win32 shell lightweight utility API (shlwapi.dll) is a cornucopia of useful functions. It appears to be Microsoft’s “dumping ground” for functions without a better home. (I believe Microsoft internal DLL ownership also played a part.) Had I known about shlwapi years ago, it would have saved me considerable programming effort.
Particularly useful are SHCreateStreamOnFile, the path family of functions (e.g. PathCombine), and the registry family of functions (e.g. SHRegGetPath).
Read more...
This is covered by any halfway-decent C++ book, but I believe it deserves reiteration: Use the RAII idiom. I don’t think I could explain RAII any better than HackCraft does in The RAII Programming Idiom.
Let me demonstrate how to use RAII with a semi-contrived example. Here’s the pre-RAII code:
1 2 3 4 5 6 7 8 9 HMODULE hm = LoadLibrary(_T("user32.dll")); if (hm != NULL) { FARPROC proc = GetProcAddress(hm, "MessageBoxW"); if (proc !
Read more...
On some Windows operating systems (primarily Windows 95, 98, and ME), GetOpenFileName() and GetSaveFileName() (and wrappers of these functions such as MFC’s CFileDialog) will permanently change the process’s current working directory unless the OFN_NOCHANGEDIR option is specified. As you can imagine, this can easily break your application if you ever rely on the current working directory being set to a particular value (such as if you open files using relative paths).
Read more...
Consider the following piece of code (adapted from a real-world bug):
1 2 3 4 5 6 7 BOOL IsDirectory(LPCTSTR strPathName) { DWORD dwAtts = GetFileAttributes(strPathName); if (dwAtts == INVALID_FILE_ATTRIBUTES) return FALSE; return (dwAtts == FILE_ATTRIBUTE_DIRECTORY); } This function will work most of the time, but every now and again it will run across a directory which it will claim isn’t one. Why?
The problem is caused because dwAtts is a bitfield (see the GetFileAttributes() documentation).
Read more...