Dialog Context Sensitive Help, MFC 6.0
-
Hi, I currently have a Dialog based application written in Visual C++ 6.0 SP2 using MFC 6.0 in the Visual Studio 6.0. I am currently on Windows 98 but the app needs to work under Windows NT 4+, and Windows 2000 as well. On the dialog box I have implemented 'F1' help. I did override OnHelpInfo() so that I could specify which control to get help for (standard windows operation is to get help on the 'dialog', not each control). Now I am trying to implement 'Shift+F1' help. When the user clicks on the '?' in the title bar, or presses 'Shift+F1' the cursor changes to the 'Help cursor' and they should get help for the next item they click. In this app the cursor does change properly, but I am having trouble catching the info about the control they click. If I go to my override of OnHelpInfo(), this function does get run but the dwContextId member of the HELPINFO structure is NULL. I checked out the MSDN help and according to technical note 028, the application should post a message WM_HELPHITTEST, when the user clicks the control with the 'Help Cursor', to the CWnd which was clicked, and then to its parent, etc. I have included that message in my Message Map and it does not appear to have been posted because my dialog box is not catching that message. Any thoughts on how I can identify on which control the user wants help? Any info will be appreciated Jeff
-
Hi, I currently have a Dialog based application written in Visual C++ 6.0 SP2 using MFC 6.0 in the Visual Studio 6.0. I am currently on Windows 98 but the app needs to work under Windows NT 4+, and Windows 2000 as well. On the dialog box I have implemented 'F1' help. I did override OnHelpInfo() so that I could specify which control to get help for (standard windows operation is to get help on the 'dialog', not each control). Now I am trying to implement 'Shift+F1' help. When the user clicks on the '?' in the title bar, or presses 'Shift+F1' the cursor changes to the 'Help cursor' and they should get help for the next item they click. In this app the cursor does change properly, but I am having trouble catching the info about the control they click. If I go to my override of OnHelpInfo(), this function does get run but the dwContextId member of the HELPINFO structure is NULL. I checked out the MSDN help and according to technical note 028, the application should post a message WM_HELPHITTEST, when the user clicks the control with the 'Help Cursor', to the CWnd which was clicked, and then to its parent, etc. I have included that message in my Message Map and it does not appear to have been posted because my dialog box is not catching that message. Any thoughts on how I can identify on which control the user wants help? Any info will be appreciated Jeff
I had to hack on the fnction to get at the control identifier. Also the data means different things at different times. I tried to accomodate all the cases I have observed in my dialog based programs. I use tabs instead of spaces, so deal with it... Here is code snippet from function: //- ----------------------------------------------------------------- //- help file functions BOOL CGCDialog::OnHelpInfo( HELPINFO* pHelpInfo ){ // pretend we handled request if help file does not exist if( !DoesAppHelpFileExist() ){ return TRUE; } if( pHelpInfo && (pHelpInfo->cbSize >= sizeof(HELPINFO)) ){ switch( pHelpInfo->iContextType ){ // menu item handlers case HELPINFO_MENUITEM:{ // menu item help LPARAM lParam = HID_BASE_COMMAND + pHelpInfo->iCtrlId; AfxGetApp()->WinHelp(lParam); return TRUE; }break; // most all other windows case HELPINFO_WINDOW:{ if( -1 == pHelpInfo->iCtrlId ){ // clicked somewhere in dialog box client area CDialog::OnHelpInfo(pHelpInfo); } else if( this != GetActiveWindow() ){ // probably invoke help topic for dialog // or help context for message box, if set CDialog::OnHelpInfo(pHelpInfo); } else if( IsControlWithoutHelp(pHelpInfo->iCtrlId) ){ pHelpInfo->iCtrlId = -1; CDialog::OnHelpInfo(pHelpInfo); } else { // avoid trying to get context sensitive help on // controls with values less than 100, since they // are probably generic controls like OK and Cancel anyway. // talk about them in dialog's main help instead if( pHelpInfo->iCtrlId >= 100 ){ LPARAM lParam = HID_BASE_CONTROL + pHelpInfo->iCtrlId; AfxGetApp()->WinHelp(lParam); return TRUE; } // probably invoke help topic for dialog return CDialog::OnHelpInfo(pHelpInfo); } }break; // not menu or window, though I rarely ever see this... default:{ // probably invoke help topic for dialog return CDialog::OnHelpInfo(pHelpInfo); }break; } } // pass it on if all else fails // probably invoke help topic for dialog return CDialog::OnHelpInfo(pHelpInfo); }
-
I had to hack on the fnction to get at the control identifier. Also the data means different things at different times. I tried to accomodate all the cases I have observed in my dialog based programs. I use tabs instead of spaces, so deal with it... Here is code snippet from function: //- ----------------------------------------------------------------- //- help file functions BOOL CGCDialog::OnHelpInfo( HELPINFO* pHelpInfo ){ // pretend we handled request if help file does not exist if( !DoesAppHelpFileExist() ){ return TRUE; } if( pHelpInfo && (pHelpInfo->cbSize >= sizeof(HELPINFO)) ){ switch( pHelpInfo->iContextType ){ // menu item handlers case HELPINFO_MENUITEM:{ // menu item help LPARAM lParam = HID_BASE_COMMAND + pHelpInfo->iCtrlId; AfxGetApp()->WinHelp(lParam); return TRUE; }break; // most all other windows case HELPINFO_WINDOW:{ if( -1 == pHelpInfo->iCtrlId ){ // clicked somewhere in dialog box client area CDialog::OnHelpInfo(pHelpInfo); } else if( this != GetActiveWindow() ){ // probably invoke help topic for dialog // or help context for message box, if set CDialog::OnHelpInfo(pHelpInfo); } else if( IsControlWithoutHelp(pHelpInfo->iCtrlId) ){ pHelpInfo->iCtrlId = -1; CDialog::OnHelpInfo(pHelpInfo); } else { // avoid trying to get context sensitive help on // controls with values less than 100, since they // are probably generic controls like OK and Cancel anyway. // talk about them in dialog's main help instead if( pHelpInfo->iCtrlId >= 100 ){ LPARAM lParam = HID_BASE_CONTROL + pHelpInfo->iCtrlId; AfxGetApp()->WinHelp(lParam); return TRUE; } // probably invoke help topic for dialog return CDialog::OnHelpInfo(pHelpInfo); } }break; // not menu or window, though I rarely ever see this... default:{ // probably invoke help topic for dialog return CDialog::OnHelpInfo(pHelpInfo); }break; } } // pass it on if all else fails // probably invoke help topic for dialog return CDialog::OnHelpInfo(pHelpInfo); }
Thanks Blake, I have no idea why I didn't think of looking at all the members of HELPINFO to find the iCtrlId item. That is exactly what I need, and it works for F1 help as well, so I can trash my previous work around. Just in case anyone is interested, Brad Robinson replied to my post in the CodeGuru Visual C++ forum with a different solution, he suggested grabbing the Window Handle member of HELPINFO (hItemHandle) and then translating that to a Control ID. That works as well. Thanks for the assist Jeff