Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Add a Help Button to a MessageBox

0.00/5 (No votes)
23 May 2000 1  
How to add a help button to a MessageBox and associate it with a context-sensitive help ID

Sample Image - mbhelp.gif

Introduction

If you look up the AfxMessageBox function in the MFC documentation, you see that it has the following declarations:


int AfxMessageBox( LPCTSTR lpszText, UINT nType = MB_OK, UINT nIDHelp = 0 );

int AFXAPI AfxMessageBox( UINT nIDPrompt, UINT nType = MB_OK, UINT nIDHelp = (UINT) -1 );

You will note that there is a help context ID number passed to the function. The problem is that there is no way to display a help button on the dialog, so the user has no idea that help on the message is available. They can only press F1 to get the help, which is not intuitive, even for advanced users.

The only way to get a Help button on a message box is with a call to ::MessageBoxIndirect. However this requires you to fill out a structure every time you want to use a message box (some UI designers would have no problem with this because it would prevent programmers from putting so many message boxes in their applications, and use of message boxes is considered bad UI design by many). You must also provide a callback function to process the help button command.

An Improved AfxMessageBox Function

I created a new version of AfxMessageBox, which makes a call to ::MessageBoxIndirect. If the help context number is non-zero, a help button is added to the message box. If the help context number is 0, no help button is added.

Note that the first parameter is a handle to the parent window. This allows the compiler to distinguish my AfxMessageBox function from the standard MFC AfxMessageBox function. I have also found that there are times when you explicitly want to provide a handle of the parent window to the message box (such as when invoking from a modeless dialog box). Of course, you can always pass NULL for the handle.

My version of AfxMessageBox also uses the application title as a caption, just like the MFC AfxMessageBox (you have to specify a caption in your call to ::MessageBox in the Windows API). However, you could easily change the function to provide a different caption.


// this version accepts a resource string identifier

UINT AfxMessageBox(HWND hWnd, UINT nIDText, UINT nType, UINT nIDHelp = 0)
{
	CString s;
	s.LoadString(nIDText);
	return AfxMessageBox(hWnd, s, nType, nIDHelp);
}

// this version accepts a text string

UINT AfxMessageBox(HWND hWnd, LPCTSTR szText, UINT nType, UINT nIDHelp = 0)
{
	MSGBOXPARAMS mbp;

	memset(&mbp, 0, sizeof mbp);

	mbp.cbSize = sizeof MSGBOXPARAMS; 
	mbp.hwndOwner = hWnd; 
	mbp.hInstance = AfxGetInstanceHandle(); 
	mbp.lpszText = szText; 

	// if you wanted to specify a different caption, here is where you do it

	mbp.lpszCaption = AfxGetAppName(); 

	// if Help ID is not 0, then add a help button

	if (nIDHelp != 0)
	{
		mbp.dwStyle = nType | MB_HELP; 
	}
	else
	{
		mbp.dwStyle = nType; 
	}

	//  mbp.lpszIcon = ; // note, you could provide your own custom ICON here!


	mbp.dwContextHelpId = nIDHelp; 
	mbp.lpfnMsgBoxCallback = &MsgBoxCallback; 
	mbp.dwLanguageId = 0x0409;
	
	return ::MessageBoxIndirect(&mbp); 
}

The Callback Function -- How to Invoke Help

When the user clicks the Help button, a callback function is invoked, receiving information about the help context number. We must provide the callback function. In the callback function, we simply call CWinApp::WinHelp specifying the correct help context ID.


VOID CALLBACK MsgBoxCallback(LPHELPINFO lpHelpInfo)
{
	AfxGetApp()->WinHelp(lpHelpInfo->dwContextId);
} 


Specifying the Help File

The help file that is invoked for this implementation of AfxMessageBox is specified by the m_pszHelpFilePath member of your CWinApp-derived application class. This member is given a value by default, but it is always best to explicitly specify the location of your help file in your applications OnInitInstance member function. Even this isn't simple because m_pszHelpFilePath is just a pointer. You must explicitly provide the buffer space for the string (refer to MFC documentation of CWinApp::m_pszHelpFilePath for an example of how to do this).

As a final note, adding the Help button to your message boxes is the easy part. The challenge is creating help topics for each message, and implementing the correct context numbers for each message box. Hopefully, the increased user satisfaction, and decreased technical support requirements will make it worth the effort.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here