Solved

CButton

Posted on 2001-09-12
21
873 Views
Last Modified: 2013-11-20
I have my own Button class derived from CButton. When I press mouse button on the button, move mouse out of button and relies mouse button windows sends ON_BN_CLICK message( or something like that ). What can I do to fix that( I need that windows will send this message when I press and relies mouse button over the button only)?
0
Comment
Question by:kamarey
  • 11
  • 9
21 Comments
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
kamarey,

You can get the rectangle of the button (GetWindowRect( LPRECT lpRect ))  and check where the mouse is when the button is released.  

My 2 cents...
0
 
LVL 2

Author Comment

by:kamarey
Comment Utility
I know where the mouse is. The problem is: what should I do after that?

if (mouse_over_the_button &&
    mouse_button_pressed &&
    mouse_button_was_pressed_over_the_button)
{
    ?????????
}

and where I should place this code: OnLButtonDown, OnMouseMove or in some other function?
0
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
Create a handler for the WM_LBUTTONUP message by starting the ClassWizard (Ctrl - W) and then adding a handler for the message tothe CMyDerivedButton class.  

>>The problem is: what should I do after that?
What is you want to do when the user clicks the button?

btw all you need is
if (mouse_over_the_button)
{
   ?????????
}
since hte message will only be generated if the button was clicked

My 2 cents...
0
 
LVL 2

Author Comment

by:kamarey
Comment Utility
Which message should I post in the handle WM_LBUTTONUP;

If there where in the class CButton a member like m_pButtonFunc(for example), I where call this function from the handle WM_LBUTTONUP. But I don't know if there is a such member.

P.S. I don't understand the words such hte and btw.
0
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
hte = the (bad typing)
btw = by the way

you don't need to post any messages.

Do the following
1.) start the ClassWizard (Ctrl - W)
2.) in 'Class Name' select you CButtn subclass
3.) in the 'Message' list box select WM_LBUTTONUP
4.) press the 'Add Function' button
5.) press the 'Edit Code' button
6.) Enter the following code
void CMyButton::OnLButtonUp(UINT nFlags, CPoint point)
{
   CRect aRect;
   /* get the size of the buttons rect */
   this->GetWindowRect(&aRect);
   /* you have normalize the point with respsect to the button */
   ClientToScreen(&point);
   
   if (aRect.PtInRect(point))
   {
      /* your code here */
      MessageBox("button clicked", "my msg");
   }
     
   CButton::OnLButtonUp(nFlags, point);
}

My 2 cents...
0
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
One you do that you have to replace the CButton with your button class.

7.) if you have not already done so create a member variable in the view or dialog that contains your button by once again activating the Class Wizard (Ctrl - W)
8.) select the 'Member Variables' tab
9.) in the Control ID's list select your button control
10.) select 'Add Variable'
11.) name the variable what you want but select 'Control' for the category type (m_wndButton for name example)
12.) Click Ok to create the variable
13.) Click ok to close the Class Wizard dialog
14.) inside the header file for the view/dialog that holds your button include your header file for your button subbclass
#include "MyButton.h"
15.) replace the default windows declarration of your button object
CButton m_wndButton /* old */
CMyButton m_wndButton /* new */

This should be all you need to do if you need more instructions let me know. The previous post describes how to catch the left button up message in your subclass and see if the mouse was over the button. This post shows you how to replace the default class for the control with your own sub class.

My 2 cents...
0
 
LVL 2

Author Comment

by:kamarey
Comment Utility
I think that we are talking about two different things. Here is the problem:
I have a dialog window (class CTestDlg::public CDialog)
This window contains a button (class CColorButton::public CButton)
I have created this variable of type CColorButton in the class CTestDlg using ClassWizard
I have created the function that will be called when the button will be pressed (void CTestDlg::OnButton())
In class CColorButton I have handle WM_MOUSEMOVE
If I compile the program now it will work (void CTestDlg::OnButton() will be called if I press a mouse button over the button and relise it withuot moving over the button)
Now the problem:
This function will be called also if I press a mouse button over the button, move mouse pointer outside the button and relise a mouse button (it shouldn't so, the function shouldn't be called if a mouse button was relised outside the button).

So I need something that:
void CColorButton::OnLButtonUp(UINT nFlags, CPoint point)
{
     CRect rect;
     GetClientRect(rect);

     if (rect.PtInRect(point))
        MessageBox("button clicked", "my msg");

     CButton::OnLButtonUp(nFlags, point);
}
but instead of function MessageBox I need to call CTestDlg::OnButton().
0
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
>>I think that we are talking about two different things.
I understand what you want
>>but instead of function MessageBox I need to call CTestDlg::OnButton().
If you follow the second set of instructions your effect will be achieved. You do not need to call CTestDlg::Onbutton. In fact you do not need that function at all. Only the WM_LBUTTONUP hanlder in the CColorButton class. Instead of a variable for the button create a control. Then replace the VC++ default control type of CButton in the CtestDlg.h header file with your custom button class (CColorButton) as I have described above. Be sure to include your ColorButton header file in the TestDlg's header file also. Please try it and you will see that it works.  This is the standard way to embed your own custom controls on a dialog (or even a view in the future)


My 2 cents....

There are two sets of action you must take.


0
 
LVL 2

Author Comment

by:kamarey
Comment Utility
I did as you wrote and it didn't chagne anything.
May be I will e-mail you the source code.
0
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
email the code to Da'mon.Ferguson@Motorola.com and be sure to delete the Debug and Release directories before you zip the file.

My 2 cents...
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 2

Author Comment

by:kamarey
Comment Utility
I sent it.
0
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
kamarey, I have not yet recieved your email. Try copying it out to damonkf@hotmail.com also.

thanks...
0
 

Expert Comment

by:gunn
Comment Utility
I've read the responses, and cypherljk is showing you the code that will do exactly what you want. It is a pretty basic thing. In fact, I just got finished reading a section of the book "MFC With Visual C++6 Unleashed" and the author just talked about what you are wanting to do, and using cypherljk 's exact way to deal with it.

0
 
LVL 2

Author Comment

by:kamarey
Comment Utility
I sent it again
0
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
kamarey, I just ran your code. You have done everything I said and it works fine for me.  If the mouse is still over the button when the left mouse button is released it displays the MessageBox with your message (m_stats is set to 1) and if it is not m_state is set to 0.  You can test this by setting a breakpoint (F9) in the OnLButtonUp() handler.  Then press F10 to setp through the code.

I think you may misunderstand the was MS routes the messages.

1.) The WM_LBUTTONUP message is generated when you release the left mouse button
2.) MFC asks the button if it would like to handle the msg, You have a hanlder so it is handled there
3.) if you notice the last line is this
CButton::OnLButtonUp(nFlags, point);
this passes the ButtonClicked msg up to the dialog which then has a chance to handle the msg. I would not remove this as it will cause other problems with the system not knowing that you released the mouse.
4.) If you don't want the dialog to handle this event then remove the OnButton() handlers in the Dialog.

You'll note this behaviour if you click and release while over a button if there are handlers in both CButton class and the dialog. The MessageBox in the CButton class will be displayed. If the mouse is clicked out side the box then the MessageBox in the Dialog's handler will be displayed.

Please don't hesitate to respond if there is still some clarification needed.
0
 
LVL 2

Author Comment

by:kamarey
Comment Utility
1. Remove MessageBox function from handle WM_LBUTTONUP.
   Run program and you will see that the function CTestDlg::OnButton() will be called in both cases (by the way, why it so?). If you will do the same with the button OK(for example), you will see that the dialog window will not close if you will release a mouse button outside the button.I need the same thing.

2. If I understand right I can say that a button was clicked only I perss mouse button and release mouse button over the button(It work fine with standart buttos. For example OK and CANCEL in the program). In the program I sent you the window with the first string "Red button" or "Blue button" shouldn't appear.
0
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
>> 1. Remove MessageBox function from handle WM_LBUTTONUP.
>>  Run program and you will see that the function >>CTestDlg::OnButton() will be called in both cases
Your correct the both handlers are called which is why you must remove the handlers for the buttons from the dialog class.
>>(by the way, why it so?)
CButton::OnLButtonUp(nFlags, point); calls the default MS implementation which passes the message up through the system. The msg handling sequence for windows dialogs is control object->dialog object->application object. If you had a SDI app it goes like this control->view->document->frame window->applications.

>>you will see that the dialog window will not close if >>you will release a mouse button outside the button.I >>need the same thing
If you remove the button handlers for the dialog they will not be called

>>2. Your second point
MS has already implemented this behavior for you. If you add a handler for the OnOk button event you'll notice that the function OnOk() /* default name */ isn't added to the MESSAGE_MAP.  Also note that the base class implementatin CDialog::OnOk() is called to handle this for you.  The same applies to OnCancel()

Once again got to the ClasWizard and select the handlers for your two buttons in the dialog class and remove them. If you want these handlers to persist then you can make a function CColorButton::IsClickValid() for example which returns the state of m_state. If m_state is equal to 1 the mouse was over the button when released and  if it is equal to 0 it is not.

I am posting a link to the MS doc on Command routing, hopefully this will clear things up

My 2 cents...
0
 
LVL 3

Expert Comment

by:cypherljk
Comment Utility
0
 
LVL 2

Author Comment

by:kamarey
Comment Utility
1. If I understood you right you say that, if I will remove button handles from CTestDlg, the buton of class CColorButton will work in the same way as the button of class CButton. But how I can call a function that I need after pressing the button(each button has his own function and cann't call this function from class CColorButton ).

2. If I create a button of type CButton and create handle  for this button in CTestDlg, the button works fine.
0
 
LVL 3

Accepted Solution

by:
cypherljk earned 50 total points
Comment Utility
>>But how I can call a function that I need after pressing >>the button(each button has his own function and cann't >>call this function from class CColorButton ).

What I am saying is that if you wish to have handlers in both you will follow the instructions I inserted in my previous post under item 2 (Adding the function that returns the state of the subcassed button's m_state variable. Also an alternate way to call functions in the dialog from the CButton subclass is by getting a pointer to the parent window GetParent() returns a CWnd pointer that you can use to call functions.  i.e.
CMyDialog* pParent = GetParent();
ASSERT_VALID(pParent);
pParent->FunctionToCall();

>>If I create a button of type CButton and create handle  >>for this button in CTestDlg, the button works
>>fine.
Yes, having only one handler gives you normal expected behavior, the tricky part comes if you want handlers in both the CButton subclass and the dialog

My 2 cents...
0
 
LVL 2

Author Comment

by:kamarey
Comment Utility
I understood finaly your solution of this problem. It doesn't seems to me that this is the best solution of this problem. But you answered this question and I will give you a points. Thanks.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
How to know only "File created" with EventLog 3 29
format the code in java 6 72
modThree challenge 4 64
ShiftLeft challenge 21 65
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now