C

Balloon Tooltips
Win32 c win32
Published: 2008-06-12
Balloon Tooltips

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...
Custom-Drawn Win32 Tooltips
Win32 c win32
Published: 2007-08-29
Custom-Drawn Win32 Tooltips

Like many common controls, the tooltip control supports custom drawing for maximum flexibility. This is a quick tutorial on how to use the tooltip custom draw facility.

First, start with the following scratch program (which is a slightly modified version of Raymond Chen’s scratch program):

 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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#define STRICT
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <tchar.h>

#define WND_CLASS_NAME TEXT("Scratch")

HINSTANCE g_hinst;

BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
    return TRUE;
}

void OnDestroy(HWND hwnd)
{
    PostQuitMessage(0);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT uiMsg, WPARAM wParam,
                         LPARAM lParam)
{
    switch (uiMsg)
    {
    HANDLE_MSG(hwnd, WM_CREATE, OnCreate);
    HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy);
    }

    return DefWindowProc(hwnd, uiMsg, wParam, lParam);
}

BOOL RegisterWindowClass()
{
    WNDCLASS wc;
    ATOM atom;

    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = g_hinst;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = WND_CLASS_NAME;

    atom = RegisterClass(&wc);
    return (atom != 0);
}

int WINAPI _tWinMain(HINSTANCE hinst, HINSTANCE hinstPrev,
                     LPTSTR lpCmdLine, int nCmdShow)
{
    INITCOMMONCONTROLSEX icc;
    int ret = EXIT_FAILURE;

    g_hinst = hinst;

    // We will need the tooltip common control
    icc.dwSize = sizeof(icc);
    icc.dwICC = ICC_WIN95_CLASSES;
    if (InitCommonControlsEx(&icc))
    {
        if (RegisterWindowClass())
        {
            HWND hwnd = CreateWindow
                (
                WND_CLASS_NAME,
                TEXT("Scratch"),
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT, CW_USEDEFAULT,
                CW_USEDEFAULT, CW_USEDEFAULT,
                NULL,
                NULL,
                hinst,
                );
            if (hwnd != NULL)
            {
                MSG msg;

                (void) ShowWindow(hwnd, nCmdShow);
                while (GetMessage(&msg, NULL, 0, 0)) {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                }

                ret = EXIT_SUCCESS;
            }
        }
    }

    return ret;
}

Next, we’ll add a tooltip to this window. We’re not going to do anything fancy like tooltip multiplexing so we’ll use TTF_SUBCLASS.

Read more...
Debugging Crashes in Windows Applications: The Null Pointer Dereference
Win32 c debugging win32
Published: 2007-04-25
Debugging Crashes in Windows Applications: The Null Pointer Dereference

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...
Beware File Open/Save Dialogs: They May Change The Current Directory
Win32 c mfc win32
Published: 2005-09-08
Beware File Open/Save Dialogs: They May Change The Current Directory

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).

Of course, it is best to eliminate any such current working directory assumptions from your application completely.

Read more...
Be Careful With Bitfields
C++ c win32
Published: 2005-09-07
Be Careful With Bitfields

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?

Read more...
In-Memory Decompression of gzip using Zlib
Compression c gzip zlib
Published: 2004-09-01
In-Memory Decompression of gzip using Zlib

At work I recently was given the task to support gzip-based HTTP response compression in a C++ MFC application. For a while I was convinced that there was no way to support in-memory decompression of gzip-compressed data using zlib, and so I wrote the gzipped data to a temporary file and then used the gzopen()/gzread()-family of functions in zlib to read it back (as described in the zlib manual).

I spent a lot of time looking at the zlib code to try to see why the in-memory streaming decompression function inflate() wasn’t working for gzip-compressed data and determined that zlib wasn’t recognizing the gzip headers. The inflate() function had code which purported to understand the headers, but it wasn’t being enabled due to reasons unknown. After some more sleuthing, I noticed the gzopen()/gzread() functions implemented their own gzip header detection and passed only the raw data to inflate(). Once I noticed this, I threw my hands up in disgust and said it couldn’t be done.

Read more...