Monday, March 31, 2008

How do I fix the problem where tooltips appear under the taskbar?

There is a bug in several versions of Windows that causes notification area tooltips to appear under the taskbar, obscuring them from view. The problem can be reproduced by the following procedure: open the start menu, select All Programs, right click on any program, press Open. This problem is documented in Microsoft's Knowledge Base, MS KB 912650. It seems that Microsoft has not had the time to make a patch to fix this bug yet. Their recommendation is to log off and log back on (terrible solution). You can use the following code as a hack in your programs until a bugfix is released.
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
char class[32];

GetClassName(hwnd, class, sizeof(class)/sizeof(char));
if(strcmp(class, "tooltips_class32") == 0)
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE);
return TRUE;
}
Then after showing a notification area tooltip, call
EnumWindows(&EnumWindowsProc, 0);
This code scans through all top-level desktop windows, checks if they are tooltip windows, and sets the tooltips to be always on top.

Sunday, March 30, 2008

Why are tabstops not working in my modeless dialog box?

The Microsoft Knowledge base has an article explaining this issue MS KB 71450. I do not know why they didn't decide to put tab functionality in the default dialog procedure. Instead you must keep track of which dialog box is active and call IsDialogMessage inside your message pump to process tab messages.
while(GetMessage(&msg, NULL, 0, 0))
{
if(!hDlgCurrent || !IsDialogMessage(hDlgCurrent, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

How do I get rid of the ding that occurs when pressing enter on a TreeView control?

This can be easily fixed by overriding the default behavior of the WM_CHAR message. First subclass the control's window procedure using SetWindowLongPtr, then inside the new procedure use the following.
switch(message)
{
...
case WM_CHAR:
return 0;
...
}

Friday, March 28, 2008

Why do ToolTip balloons flash or flicker sometimes?

Balloon style ToolTips may flicker if the mouse moves over the little pointed corner of the balloon. This is because the mouse is no longer hovering over the main window - it is hovering over the ToolTip itself. To prevent this behavior, you can use the TTF_TRANSPARENT flag in the uFlags parameter of the TOOLINFO structure. This flag will cause mouse events to be passed to the underlaying window as if the ToolTip was transparent.

Thursday, March 27, 2008

Why can't I access the pages of my Property Sheet until they have been viewed?

The property sheet control is implemented so that it does not waste time loading pages that are not going to be used. It takes the approach of loading each page when the user clicks on the tab for that page. Therefore, if you make a call to PropSheet_IndexToHwnd prior to having that page viewed, the function will return NULL. However, it is possible to tell the control to load pages upon initialization. You can do this by setting the flag PSP_PREMATURE in the dwFlags parameter of each PROPSHEETPAGE structure for pages that you want loaded at initialization.

Wednesday, March 26, 2008

How do I make my HTML Help (.CHM) file look like Windows help files?

If you haven't made HTML Help files before, you will want to obtain Microsoft's HTML Help Workshop, which is a free download from MSDN. When you make a .chm (compiled HTML) help file using the default settings, it will look just like how that HTML would display in Internet Explorer. But if you open up Help Topics in Notepad, you can see that Microsoft uses different fonts. By right clicking and selecting "View Source" you can see that they are actually including a CSS stylesheet from a file called ntshared.chm, which can be found in "C:\Windows\Help". You could link directly to the same file from your help file, but that may be unsafe. Future versions of Windows may move the location of that file, so it will be safer to compile that stylesheet directly into your help file. You can do this using the following steps.
1. Copy C:\Windows\Help\ntshared.chm to the Desktop.
2. Open Microsoft HTML Help Workshop and select Decompile from the File menu.
3. Specify that you want to decompile the copy of ntshared.chm on the Desktop.
4. Copy coUA.css and coUAprint.css from the Desktop to the same directory as your HTML files.
5. Add the CSS link tags to each of your HTML files

<LINK REL="stylesheet" MEDIA="screen" TYPE="text/css"
HREF="coUA.css">
<LINK REL="stylesheet" MEDIA="print" TYPE="text/css"
HREF="coUAprint.css">
Now your help file will have a look that is consistent with Microsoft's own help files.

Tuesday, March 25, 2008

Why can I only access a file when running in the debugger?

If you are using relative paths such as in
FILE *file;
file = fopen("data.xml", "r");
the working directory may be the problem. The debugger may be setting up the working directory differently than Windows sets it when you execute the program. Windows will set the working directory to be the same as the directory of the executable, unless if it is launched by a shortcut. A shortcut will set the working directory according to its "Start in" parameter. If this parameter is empty, Windows will set the working directory to be the current user's home folder (under Documents and Settings in Windows XP).

Monday, March 24, 2008

How do I detect multiple instances of my program?

The best way to do this in Windows is to use mutex objects. Mutex objects are used to keep track of which thread currently owns a particular resource. The name comes from the fact that they are used in coordinating mutually exclusive access to shared resources. Basically, you create a mutex object upon the first instantiation of your program and then check for that object every time the program is executed. If the object is found, you know that this must be a second (or higher) instantiation. In this case, you may want to set the previous instance to be the foreground window and abort the current process.
char szClassName[] = "Program Name";
HWND hWndPrev;
HANDLE hMutex;
hMutex = CreateMutex(NULL, TRUE, szClassName);
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
hWndPrev = FindWindow(szClassName, NULL);
if(hWndPrev != NULL)
SetForegroundWindow(hWndPrev);
return FALSE; // this instance exits
}

Sunday, March 23, 2008

How can I avoid flickering that occurs when using a custom paint routine with a common control?

Common controls sometimes draw to the screen without sending a WM_PAINT message. An example is expanding items in a TreeView control. This can cause flickering if you are using a custom painting routine. To solve this problem you can surround the call with WM_SETREDRAW switches, which disable any drawing to the window.
SendMessage(hwndTV, WM_SETREDRAW, FALSE, 0);
TreeView_Expand(hwndTV, hItem, TVE_EXPAND);
SendMessage(hwndTV, WM_SETREDRAW, TRUE, 0);

Why don't expando buttons show up on a TreeView item after adding a child item?

This can be caused by having TVIF_CHILDREN set when calling TreeView_InsertItem. Removing this flag should solve the problem.

Why does right clicking on my notification icon sometimes bring up the Windows taskbar menu as an overlapped double menu?

This seems to be a bug in Windows XP. It is easily avoided by launching the popup menu upon receiving WM_RBUTTONUP instead of WM_RBUTTONDOWN.

How do I make popup menus for notification (system tray) icons disappear after clicking elsewhere?

This is a common problem with notification icon menus. When you right click on a notification icon, a popup menu appears. When you click somewhere else, such as on the desktop, the menu remains. This can be really frustrating. Microsoft has a knowledge base article on this: MS KB Q135788. The solution is to surround TrackPopupMenu with calls to SetForegoundWindow and SendMessage.
SetForegroundWindow(hDlg);
TrackPopupMenu(hSubMenu, TPM_RIGHTBUTTON, pt.x, pt.y,
0, hDlg, NULL);
PostMessage(hDlg, WM_NULL, 0, 0);
After fixing this, be careful that your menu is attached to the WM_RBUTTONUP message and not the WM_RBUTTONDOWN message. Using the latter will cause occasional double popup menus where the Windows taskbar menu will overlap your program's menu (see the next post).

Why do fread and _read return EOF before the end of my file?

There must be a problem in Microsoft's implementation of these functions. I had problems reading bitmap files, but everything worked fine after switching to CreateFile and ReadFile.

Why is MonthCal_HitTest not working?

It seems that Visual Studio 9 has a problem in comctl32.lib with MonthCal_HitTest. You can copy an older version along with its header file to the appropriate directories as a work-around until Microsoft fixes the problem.

Why isn't my TreeView showing drag images?

TreeView controls refuse to display drag images unless if they have been assigned a normal image list. This can be done with the macro TreeView_SetImageList.
HIMAGELIST TreeView_SetImageList(
HWND hwndTV, // handle to treeview
HIMAGELIST himl, // handle to image list containing icons
INT iImage // set this to TVSIL_NORMAL
);
If you don't want to see the icons in the TreeView, you can use blank icons in the image list. However, this still leaves you with a big empty space. You can shrink this space by reducing the dimensions specified for the icons in the image list, but this has the unfortunate side effect of shrinking the size of the expando buttons correspondingly.

How do I call the default dialog box window procedure?

In your dialog box window procedure,
INT_PTR CALLBACK DialogProc(          
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
you should return FALSE in order to have the default dialog box window procedure executed.

How do I load a bitmap object from a BMP file in memory?

Let's say you have a BMP file loaded into memory with handle file and you want to make a bitmap object that can be drawn to the device hdc. This function will do that for you.

HBITMAP LoadBitmapFromMemory(HDC hdc, const char *file)
{
HBITMAP ret;
BITMAPINFO *info;
BITMAPFILEHEADER *header;

header = (BITMAPFILEHEADER*)file;
if(header->bfType != 'MB') // code for bmp
return NULL;
info = (BITMAPINFO*)(file+sizeof(BITMAPFILEHEADER));
ret = CreateDIBitmap(hdc, &(info->bmiHeader), CBM_INIT,
file+header->bfOffBits, info, DIB_RGB_COLORS);
return ret;
}

How do I find the path of my exe file?

You can use GetModuleFileNameEx.
DWORD WINAPI GetModuleFileNameEx(
HANDLE hProcess, // handle to a process
HMODULE hModule, // handle to a module
LPTSTR lpFilename, // receives file path
DWORD nSize // length of lpFilename
);
This will load the path of the currently running exe file into a buffer named path.
#include <psapi.h>
char path[MAXPATH];
GetModuleFileNameEx(GetCurrentProcess(), NULL, path, MAXPATH);

Categories

Processes
How do I wait for a process to terminate?

How do I detect multiple instances of my program?

How do I find the path of my exe file?


Windows Shell
How do I find the path of the temp directory?

How do I fix the problem where tooltips appear under the taskbar?

How do I make my HTML Help (.CHM) file look like Windows help files?

Why does right clicking on my notification icon sometimes bring up the Windows taskbar menu as an overlapped double menu?

How do I make popup menus for notification (system tray) icons disappear after clicking elsewhere?


File System
Why can I only access a file when running in the debugger?

Why do fread and _read return EOF before the end of my file?


Dialog Boxes
Why does ShowWindow cause a flicker?

How do I disable font anti-aliasing (font smoothing) for a window?

Why are tabstops not working in my modeless dialog box?

How do I call the default dialog box window procedure?


GDI
How do I load a bitmap object from a BMP file in memory?


Common Controls
How Do I Create a Window with Visual Styles?

Why is my message box invisible until I press the ALT key?

How do I get rid of the ding that occurs when pressing enter on a TreeView control?

Why do ToolTip balloons flash or flicker sometimes?

Why can't I access the pages of my Property Sheet until they have been viewed?

How can I avoid flickering that occurs when using a custom paint routine with a common control?

Why don't expando buttons show up on a TreeView item after adding a child item?

Why is MonthCal_HitTest not working?

Why isn't my TreeView showing drag images?


Visual Studio
How can I insert location dependent information in my debugging messages?

Why does my application fail when run on computers that don't have Visual Studio installed?

How do I send trace messages to the debug console in Visual Studio?