• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1743
  • Last Modified:

Programming in Visual C++ for Mouse Events

I have a dialog based application with a lot of command buttons, and other miscellaneous controls (combo boxes, etc.), and I want to be able to hover the mouse over any button, and 1) highlight it, and 2) display help text for any of the controls.

I figured the way to do this would be to use the WM_MOUSEMOVE message. I tried this, and this gives me coordinates for anywhere in the dialog, except over the controls. (I'm assuming that the controls are intercepting the WM_MOUSEMOVE message.)

I was planning to use the coordinates to tell me when I was over each command button, and was planning to then implement code to do the highlighting, and bubble help.  

What is the best way to implement what I'm trying to do ?
0
wannabeguru
Asked:
wannabeguru
  • 3
  • 3
1 Solution
 
FAQCommented:
As far as I know, you can't do that, the windows common controls are derived from one generic class and are self contained, think of them as separate windows that happen to interact with your program.
0
 
abancroftCommented:
For the 'help text' you could use a tooltip.

I can explain how to do it in MFC. Is that any use?

What do you mean by 'Highlight it'?
0
 
wannabeguruAuthor Commented:
To abancroft:
 
  If you're good at tool tips, that would definitely help.  I'll explain a little more about my application.

 I have several command buttons, that have bitmaps associated with them.  The CBitmapButton class is really handy for "static", "pressed", "disabled" and "focused" states, but I want to change the bitmap on the button when I hover the mouse over it, and then once I click the button, I want to change the bitmap to a 3rd state, that remains until I click a different button.  Note how the palette buttons work in the "Paint" application.  

The only way I could figure out how to do this was to make static controls, and then write code to change the bitmaps on the fly, using the WM_MOUSEMOVE, and WM_LBUTTONDOWN messages.  I've got this working pretty good now by writing a fair amount of code, but I wonder if there's a more elegant way.  

Now, I also want to display tool tips over each of these static controls (which look just like bitmapped command buttons) to describe what each button does.  I know how to do tooltips over a CButton command button, but I've run into difficulty using the CStatic controls. The only way I've come up with so far, is to provide a tooltip for the entire dialog, and just change the tooltip text when the mouse is over one of my buttons.  I would rather just pass a pointer to the CStatic control, like I can do with a CButton object, but this doesn't seem to work.  CButton must automatically handle the TTN_NEEDTEXT message, and CStatic does not.  

Do you know how to do tooltips over static controls ?  I've been looking through the MSDN CD and found some examples for similar stuff, but not for exactly what I'm doing.

0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
abancroftCommented:
Sounds like you know what you're doing....

Here's how I do tooltips:
1. In OnInitDialog(), call EnableToolTips().
2. Handle the TTN_NEEDTEXT message:
  ON_NOTIFY_EX( TTN_NEEDTEXT, 0, ToolTip)
  :
  :
BOOL CMyDlg::ToolTip(UINT id, NMHDR * pTTTStruct, LRESULT * pResult)
{
  TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pTTTStruct;
  UINT nID = pTTTStruct->idFrom;

  // idFrom is actually the HWND of the tool
  if (pTTT->uFlags & TTF_IDISHWND)
    nID = ::GetDlgCtrlID((HWND)nID);

  if (nID)
  {
    pTTT->lpszText = MAKEINTRESOURCE(nID);
    pTTT->hinst = AfxGetResourceHandle();
  }

  return(TRUE);
}

This will try and use the string resource with the same id as the control. If no such resource exists, no tool tip. I haven't tried this for static controls, but unless MFC filters them it should work.

Sounds like you need radio buttons that act like & look like bitmap buttons. Is that correct?
0
 
wannabeguruAuthor Commented:
Your statement is correct.  I want the functionality of a radio button, i.e. mutual exclusion, but in addition I want to change the bitmap on the button just by having the mouse over the button (unless the button is already selected, in which case the mouse over the button has no effect).

With regard to your sample code, how do I make the string resource with the same ID as the control ?  That may be my problem.  I saw the same sample code in the MSDN CD, and I tried it, but no tool tip showed up.  I used the AddTool method:

m_ToolTip.AddTool(&m_Btn1, "Button 1");

where "m_Btn1" is a CStatic member variable associated with my static control.  (I added the member using CLass Wizard.)  This exact code works if "m_Btn1" is for a CButton control, but not for a CStatic control.
 
0
 
abancroftCommented:
For the bitmap radio buttons:
1. Create radio buttons in the dialog resource editor. As normal, use the 'Group' style to create a radio button group (so only 1 can be chosen at a time).
2. For each radio button, apply the 'Push-Like' and 'Bitmap' styles.
3. Use the class wizard to add an 'int' member variable and link it to the radio button group (I'll call it m_nRadio)
4. Add an int to hold the id of the radio button that the mouse is over(I'll call it m_nHover). In the constructor, initialise to -1.

Now you need to set the bitmaps at the appropriate points. One method is:
1. Create appropriate bitmap resources - the exact number is dependent on your requirements.
2. For each bitmap resource, add a CBitmap member to the dialog: load each CBitmap member with the corresponding resource in OnInitDialog().
3. Create a function (e.g. DrawRadioImages()) that'll send BM_SETIMAGE messages to each radio button. This'll need to take into account the m_nRadio & m_nHover variables.
4. Call this function at the end of DoDataExchange().
5. Add an ON_CONTROL_RANGE(BN_CLICKED, ...) handler for the range of radio button ids. In the handler, just call UpdateData(TRUE).

Now you just need to handle the hovering image (this is pseudo code):
CDlg::OnMouseMove(...)
{
  if (mouse is over radio button)
  {
    m_nHover = radio button id;
    DrawRadioImages();
  }
  else if (-1!=m_nHover)
  {
    // Not over any radio, but was in last mouse move message, so clear hover image
    m_nHover = -1;
    DrawRadioImages();
  }
}

You could also use image lists or arrays of CBitmap objects in place of the individual bitmaps.

Or use a CToolBarCtrl instead of radio buttons.

To make a string resource with the same id as a control, just insert a 'String Table' in resource view. Then add a string with the same id as the control (e.g. IDC_RADIO1).

I haven't used the AddTool() method: the one I described works for static controls though. Using resources also allows you to localise the tool tip text.
0
 
wannabeguruAuthor Commented:
I didn't realize that radio buttons could be used with bitmaps.  I'll try that.  Thanks for your help !
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now