Click here to Skip to main content
Click here to Skip to main content

Create your own controls - the art of subclassing

By , 25 Oct 2001
 
  • Download source files - 18 Kb
  • Introduction

    There are many windows common controls that you as a programmer can use to provide an interface to an application. Everything from lists to buttons to progress controls are available. Even so, there will often come a time when the standard selection of controls - diverse as they are - are just not enough. Welcome to the gentle art of subclassing controls.

    Subclassing a window control is not the same as subclassing a C++ class. Subclassing a control means you replace some or all of the message handlers of a window with your own. You effectively hijack the control and make it behave the way you want, not the way Windows wants. This allows you to take a control that is almost, but not quite, what you want, and make it perfect. There are two types of subclassing: instance subclassing and global subclassing. Instance subclassing is when you subclass a single instance of a window. Global subclassing subclasses all windows of a particular type with your own version. We'll only discuss single instance here.

    It's important to remember the distinction between an object derived from CWnd and the window itself (a HWND). You C++ CWnd-derived object contains a member variable that points to a HWND, and contains functions that the HWND message pump calls when processing messages (eg WM_PAINT, WM_MOUSEMOVE). When you subclass a window with your C++ object, you are attaching that HWND to your C++ object and setting that objects callback functions as the one the message pump for that HWND will invoke.

    Subclassing is easy. First you create a class that will handle all the windows messages you are interested in, and then you physically subclass an exising window and make it behave the way your new class dictates. The window becomes possessed, in a way. For this example we'll subclass a button control and make it do things it never knew it was capable of.

    A New Class

    To subclass a control we need to create a new class that handles all the windows messages we are interested in. Since we are lazy it's best to minimise the number of messages you actually have to deal with, and the best way of doing this is by deriving your class from the control class you are subclassing. In our case CButton.

    Lets assume we want to do something bizarre like make the button glow bright yellow everytime the mouse moves over it. Stranger things have been done. First thing we do is use ClassWizard to create a new class derived from CButton called CMyButton.

    Adding a new class

    Deriving from CButton within the MFC framework has a lot of advantages, with the biggest one being we don't actually have to add a single line of code for our class to be a fully functioning windows control. If we wished we could move onto the next step and subclass a button control with our new class and we would have a perfectly functioning, though somewhat boring, button control. This is becuase MFC implements default handlers for all it's messages, so we can simply pick the ones we are interested in, and ignore the others.

    However for this example we have loftier plans for our control - making it bright yellow.

    To check if the mouse is over the control we will set a variable m_bOverControl to TRUE when the mouse enters the control, and then check periodically (using a timer) to keep track of when the mouse leaves the control. Unfortunately for us there is no OnMouseEnter and OnMouseLeave function that can be used across platforms, so we have to make do with using OnMouseMove. If, on a timer tick, we find the mouse is no longer in the control we turn off the timer and redraw the control.

    Use ClassWizard to add a WM_MOUSEMOVE and WM_TIMER message handlers mapped to OnMouseMove and OnTimer respectively.

    Adding message handlers

    ClassWizard will add the following code to your new button class:

    BEGIN_MESSAGE_MAP(CMyButton, CButton)
        //{{AFX_MSG_MAP(CMyButton)
        ON_WM_MOUSEMOVE()
        ON_WM_TIMER()
        //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CMyButton message handlers
    
    void CMyButton::OnMouseMove(UINT nFlags, CPoint point) 
    {
        // TODO: Add your message handler code here and/or call default
    	
        CButton::OnMouseMove(nFlags, point);
    }
    
    void CMyButton::OnTimer(UINT nIDEvent) 
    {
        // TODO: Add your message handler code here and/or call default
    	
        CButton::OnTimer(nIDEvent);
    }
    

    The message map entries (in the BEGIN_MESSAGE_MAP section) map the windows message to the function. ON_WM_MOUSEMOVE maps WM_MOUSEMOVE to your OnMouseMove function, and ON_WM_TIMER maps WM_TIMER to OnTimer. These macros are defined in the MFC source, but they are not required reading. For this excercise simply have faith that they do their job.

    Assuming we have declared two variables m_bOverControl and m_nTimerID of type BOOL and UINT respectively, and initialised them in the constructor, our message handlers will be as follows

    void CMyButton::OnMouseMove(UINT nFlags, CPoint point) 
    {
        if (!m_bOverControl)                    // Cursor has just moved over control
        {
            TRACE0("Entering control\n");
    
            m_bOverControl = TRUE;              // Set flag telling us the mouse is in
            Invalidate();                       // Force a redraw
    
            SetTimer(m_nTimerID, 100, NULL);    // Keep checking back every 1/10 sec
        }
    	
        CButton::OnMouseMove(nFlags, point);    // drop through to default handler
    }
    
    void CMyButton::OnTimer(UINT nIDEvent) 
    {
        // Where is the mouse?
        CPoint p(GetMessagePos());
        ScreenToClient(&p);
    
        // Get the bounds of the control (just the client area)
        CRect rect;
        GetClientRect(rect);
    
        // Check the mouse is inside the control
        if (!rect.PtInRect(p))
        {
            TRACE0("Leaving control\n");
    
            // if not then stop looking...
            m_bOverControl = FALSE;
            KillTimer(m_nTimerID);
    
            // ...and redraw the control
            Invalidate();
        }
    	
        // drop through to default handler
        CButton::OnTimer(nIDEvent);
    }

    The final piece of our new class is drawing, and for this we don't handle a message, but rather override the CWnd::DrawItem virtual function. This function is only called for owner-drawn controls, and does not have a default implementation that can be called (it ASSERT's if you try). This function is designed to be overriden and used by derived classes only.

    Adding DrawItem override

    Use the ClassWizard to add a DrawItem override and add in the following code

    void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
    {
        CDC* pDC   = CDC::FromHandle(lpDrawItemStruct->hDC);
        CRect rect = lpDrawItemStruct->rcItem;
        UINT state = lpDrawItemStruct->itemState;
    
        CString strText;
        GetWindowText(strText);
    
        // draw the control edges (DrawFrameControl is handy!)
        if (state & ODS_SELECTED)
            pDC->DrawFrameControl(rect, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED);
        else
            pDC->DrawFrameControl(rect, DFC_BUTTON, DFCS_BUTTONPUSH);
    
        // Deflate the drawing rect by the size of the button's edges
        rect.DeflateRect( CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE)));
        
        // Fill the interior color if necessary
        if (m_bOverControl)
            pDC->FillSolidRect(rect, RGB(255, 255, 0)); // yellow
    
        // Draw the text
        if (!strText.IsEmpty())
        {
            CSize Extent = pDC->GetTextExtent(strText);
            CPoint pt( rect.CenterPoint().x - Extent.cx/2, 
            rect.CenterPoint().y - Extent.cy/2 );
    
            if (state & ODS_SELECTED) 
                pt.Offset(1,1);
    
            int nMode = pDC->SetBkMode(TRANSPARENT);
    
            if (state & ODS_DISABLED)
                pDC->DrawState(pt, Extent, strText, DSS_DISABLED, TRUE, 0, (HBRUSH)NULL);
            else
                pDC->TextOut(pt.x, pt.y, strText);
    
            pDC->SetBkMode(nMode);
        }
    }

    Everything is now in place - but there is one last step. The DrawItem function requires that the control be owner drawn. This can be achieved in the dialog resource editor by checking the appropriate box - but a far nicer way is to have the class itself set the style of the window it is subclassing automatically in order to make the class a true "drop-in" replacement for CButton. To do this we override a final function: PreSubclassWindow.

    This function is called by SubclassWindow, which in turn is called by either CWnd::Create or DDX_Control, meaning that if you created an instance of you new class either dynamically or by using a dialog template, PreSubclassWindow will still be called. PreSubclassWindow will be called after the window you are subclassing has been created, but before it becomes visible after you subclass it. In other words - a perfect time to perform initialisation that requires the window to be present.

    An important note here: if you create a control using a dialog resource, then your subclassed control will not see the WM_CREATE message, hance we cannot use OnCreate for our initialisation, since it won't be called in all cases.

    Use ClassWizard to override PreSubclassWindow and add the following code

    void CMyButton::PreSubclassWindow() 
    {
        CButton::PreSubclassWindow();
    
        ModifyStyle(0, BS_OWNERDRAW);	// make the button owner drawn
    }
    

    Congratulations - you now have a Cbutton derived class!

    The Subclass

    Using DDX to subclass a window at creation time

    In this example I'm working with a dialog on which I've placed a button control:

    a button

    We let the normal dialog creation routines create the dialog with the control, and use the DDX_... routines to subclass the control with our new class. To do this simply use ClassWizard to add a member variable to you dialog class attached to your button control (in my case it's ID is IDC_BUTTON1), and choose the variable as a Control type, with class name CMyButton.

    subclassing the control

    The ClassWizard generates a DDX_Control call in your dialog's DoDataExchange function. DDX_Control calls SubclassWindow which causes the button to use the CMyButton message handlers instead of the usual CButton handlers. The button has been hijacked and will behave from now on the way we want it to.

    Subclassing a window using a class not recognised by the ClassWizard

    If you have added a window class to your project and want to subclass a window with an object of this new class' type, but the ClassWizard isn't offering you that new object's type as an option, then you may need to rebuild the class wizard file.

    Make a backup of your projects .clw file, delete the original file, then go into Visual Studio and hit Ctrl+W. You will then be prompted for which files you want to have included in the class scan. Ensure that the new class files are included!

    Your new class should now be available as an option. If not, then you can always use the classwizard to subclass you control as a generic control (say, CButton) and then go into the header file manually and change this to the class that you want (eg CMyButton).

    Subclassing an existing window

    Using DDX is simple, but doesn't help us if we need to subclass a control that already exists. For instance, say you want to subclass the Edit control in a combobox. You need to have the combobox (and hence it's child edit window) already created before you can subclass the edit window.

    In this case you make use of the handy SubclassDlgItem or SubclassWindow functions. These two functions allow you to dynamically subclass a window - in other words, attach an object of your new window class type to an existing window.

    For example, suppose we have a dialog containing a button with ID IDC_BUTTON1. That button has already been created and we want to associate that button with an object of type CMyButton so that the button behaves in the manner we want.

    To do this we need to have an object of our new type already created. A member variable of your dialog or view class is perfect.

    CMyButton m_btnMyButton;

    Then call in your dialog's OnInitDialog (or whereever is appropriate) call

    m_btnMyButton.SubclassDlgItem(IDC_BUTTON1, this);

    Alternatively suppose you already have a pointer to a window you wish to subclass, or you are working within a CView or other CWnd derived class where the controls are created dynamically or you dont't wish to use SubclassDlgItem. Simply call

    CWnd* pWnd = GetDlgItem(IDC_BUTTON1); // or use some other method to get
                                          // a pointer to the window you wish
                                          // to subclass
    ASSERT( pWnd && pWnd->GetSafeHwnd() );
    m_btnMyButton.SubclassWindow(pWnd->GetSafeHwnd());

     

    The button drawing is very simple and does not take into account button styles such as flat buttons, or justified text, but scope is there for you to do whatever you wish. If you compile and run the accompanying code you'll see a simple button that turns bright yellow when the mouse passes over it.

    The finished product

    Notice that we only really overrode the drawing functionality, and intercepted the mouse movement functions (but passed these on to the default handler). This means that the control is still, deep down, a button. Add a button click handler to your dialog class and you'll see it will still get called.

    Conclusion

    Subclassing is not hard - you just need to choose the class you wish to subclass carefully, and be aware of what messages you need to handle. Read up on the control you are subclassing - learn about the messages it handles and also the virtual member functions of its implementation class. Once you've hooked into a control and taken over it's inner workings the sky's the limit.

    History

    26 Oct 2001 - added info in SubclassWindow and SubclassDlgItem

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    About the Author

    Chris Maunder
    Founder CodeProject
    Canada Canada
    Member
    Chris is the Co-founder, Administrator, Architect, Chief Editor and Shameless Hack who wrote and runs The Code Project. He's been programming since 1988 while pretending to be, in various guises, an astrophysicist, mathematician, physicist, hydrologist, geomorphologist, defence intelligence researcher and then, when all that got a bit rough on the nerves, a web developer. He is a Microsoft Visual C++ MVP both globally and for Canada locally.
     
    His programming experience includes C/C++, C#, SQL, MFC, ASP, ASP.NET, and far, far too much FORTRAN. He has worked on PocketPCs, AIX mainframes, Sun workstations, and a CRAY YMP C90 behemoth but finds notebooks take up less desk space.
     
    He dodges, he weaves, and he never gets enough sleep. He is kind to small animals.
     
    Chris was born and bred in Australia but splits his time between Toronto and Melbourne, depending on the weather. For relaxation he is into road cycling, snowboarding, rock climbing, and storm chasing.

    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board.
    Search this forum  
        Spacing  Noise  Layout  Per page   
    QuestionI request to plz elaborate this paragraph.membersayit2shoaib16 Oct '12 - 7:46 
    Hey Hi Every one..
    I am new to MFC and C++, so will you please elaborate the below para. It is confusing me a
    little.

    "It's important to remember the distinction between an object derived from CWnd and the window itself (a HWND). You C++ CWnd-derived object contains a member variable that points to a HWND, and contains functions that the HWND message pump calls when processing messages (eg WM_PAINT, WM_MOUSEMOVE). When you subclass a window with your C++ object, you are attaching that HWND to your C++ object and setting that objects callback functions as the one the message pump for that HWND will invoke."
     
    Thanks in advance
    GeneralMy vote of 5memberknutrl30 Jan '12 - 0:46 
    Did help me to do something similar Smile | :)
    Questionhow to add this control to CMainFrame window dynamicallymemberMember 218094024 Aug '11 - 22:47 
    Hi
    I have created Win32 application using only CWinApp and CFrameWnd classes. Then i added CMyButton control on frame window using create function as shown below. I am able to create it, but not receiving any button click messages in Frame class. Please help..
     
    CMyButton But1;
    int ID_BUT1 = 100;
    CRect rect_but1(50, 50, 150, 80);
     
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
    ON_WM_CREATE()
    ON_COMMAND(IDM_BUTTON, OnShowButton)
    ON_BN_CLICKED(ID_BUT1, OnButtonClicked)
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_USER+1, OnMessageFromButton)
     
    END_MESSAGE_MAP()
     

     
    void CMainFrame::OnShowButton()
    {
    But1.Create("Button1", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, rect_but1, this, ID_BUT1);
    }
     
    void CMainFrame::OnButtonClicked()
    {
    TRACE0("\n my button clicked..");
    }
    QuestionClass wizard restricts me on given subclassesmembernooruddinaftab9 Aug '10 - 23:10 
    dear Chris,
     
    im not able to select CButton as the base class of derived CMyButton class,
    also the UI of class wizard is different .
    im using VS 2008,
     

    regards,
     
    Nooruddinaftab
    AnswerRe: Class wizard restricts me on given subclassesmembermaecky19 Mar '11 - 23:27 
    Hi Nooruddinaftab,
     
    I have the same problem, did you or someone else figure out how to solve this?
     

    regards,
    maecky
    GeneralGood Luck..!memberankit vc11 Dec '09 - 21:36 
    Good article.. !
    And ur profile is amazing..!
    GeneralButton VariablememberAnandi.VC23 Aug '09 - 21:18 
    if i create a "m_button" variable of type CMyButton or CButton i am getting two Assertion Failures and crash.
     
    when debugged, i got the first Assert message from the following code(bold letters) :
     
    BOOL CWnd::Attach(HWND hWndNew)
    {
    	ASSERT(m_hWnd == NULL);     // only attach once, detach on destroy
    	ASSERT(FromHandlePermanent(hWndNew) == NULL);
    		// must not already be in permanent map
     
    shouldnt we create a member variable while subclassing a control ?
     
    Thanks,
    Anandi
    Questionhow to create button after buttonmemberjielun2 Oct '08 - 15:18 
    i have problem doing this..anyone can help me?i need to create a button at the form of VB2005 using C# and when i click at the button other two of the button will appear.. but not using button1.Visible = true/false;..Is like when we click at the button other two of the button is created and appear on the form..anyone pls reply me asap thax alot!!!!!
    Generalsendmessage on button clickmemberSwapna_gg8325 Apr '08 - 12:20 
    I have a button which has dual functionality based on whether it is clicked for a short duration or long duration. I have subclassed the button (MYbutton.cpp)
    where i have a ON_WM_LBUTTONDOWN() and ON_WM_LBUTTONUP(). Here are the codes:
     
    void CMyButton::OnLButtonDown(UINT nFlags, CPoint point)
    {
    dwTickCount1= GetTickCount();
    }
    void CMyButton::OnLButtonUp(UINT nFlags, CPoint point)
    {
     
    dwTickCount2= GetTickCount();
    if ((dwTickCount2 - dwTickCount1)>500)
    {
    // send message to button that it was long pressed
    }
    else
     
    //Send message to button that it was short pressed
    }
     

    Then I have a main dialogue box called Qphonedialog.cpp where there are several buttons of the type Mybutton.cpp with the functions ON_BN_CLICKED for each of the buttons of the type Mybutton.cpp
     
    The Question is How do i send short clicked or long clicked from Mybutton.cpp to the respective onbutton clicked function?
     
    I hope I made my problem clear,
    _____________________________________________
    My idea was to :
    1. Getfocus to optain handle of the button that was recently clicked.
    2. getctrlId to get the ID of the button tht was clicked.
    3. Sendmessage to the respective button
    I wonder if there is a way to do this?
    _____________________________________________________
    Thanks in advance
     
    swapna
    GeneralSubClassing all buttons of a programmemberHadi Dayvary16 Oct '07 - 1:27 
    Hi
    I have created a class that is derived from CBotton,
    But I want to change all my program buttons to CMyButton at once, I means not to do it one by one and without declaring a CMyBotton object for all buttons.
    Please help
    Thanks
    GeneralRe: SubClassing all buttons of a programmemberPrithvi Durai5 Sep '12 - 18:45 
    Perform global Subclassing, so far in the article the type of subclassing is done is instance subclassing Dynamically or Resource level. Try Global Subclassing, there is matured Subclass Class available to do that. The underlining concept is hook. Hope this helps you
    GeneralRe: SubClassing all buttons of a programmemberHadi Dayvary5 Sep '12 - 19:36 
    Hi
    Thank you about your answer, But how to do global subclassing, an API or sample can help me a lot.
    I have written a hook for keyboard some years ago but don't know about this type of hooking.
     
    If know more that would be great.
     
    Regards
    Hadi
    www.logicsims.ir

    GeneralRe: SubClassing all buttons of a programmemberPrithvi Durai5 Sep '12 - 22:47 
    
    Refer below articles for more information on global subclassing, I have linked both inproc and outproc global subclassing which includes sample  
     
    1. Within Process Subclass Hooking
    http://www.codeproject.com/Articles/5185/Windows-subclassing-and-hooking-with-C-classes
     
    2. Cross Process Subclass Hooking
    http://www.venkydude.com/articles/subclass.htm
     
    From your requirement, I understand that the inproc global subclassing should be enough. Once subclassed you have to do the same same thing as you do for single control or item. If you want to subclass only particular type of control then you can use ClassName to verify the control type and then add for subclassing. 
     
    I hope this answers all your queries.
     
    

    GeneralRe: SubClassing all buttons of a programmemberHadi Dayvary5 Sep '12 - 23:30 
    Thank you so much.
    I will read them all.
     
    Regards
    Hadi
    www.logicsims.ir

    QuestionSubclassing a combobox and listboxmembergajendrakashyap27 Dec '06 - 4:08 
    Hi Chris,
    I'm a beginner with MFC programming. Thats a nice article by you. Of all the articles I read none could solve my problem.
     
    I've a modeless child dialog on which I display the combobox and listboxes. This modeless dialog is displayed on a parent window created by the MFC app wizard.
     
    I'm not able to successfully paint the widgets with colors I want when they are ownerdrawn in this case. Cry | :((
    Can you provide some help .. guidance ?

     
    Thanks,
    Gajendra
    GeneralA better(?) solution for mouse leave/enter listeningmemberRuis Ngetal16 Nov '05 - 8:33 
    I think looking periodically for timer is ugly and uses unnecessary resources,
    especially when you have, say, 1000 buttons of this type (rare case though).
     
    By using SetCapture() and ReleaseCapture() you can "grab" all mouse messages and
    see if it has left the button.
     
    see:
    http://msdn.microsoft.com/library/default.asp?url=/library/enus/vclib/html/_mfc_cwnd.3a3a.setcapture.asp
     
    //------------------------------------------------------------
    void CColorButton::OnMouseMove(UINT nFlags, CPoint point)
    //------------------------------------------------------------
    {
          SetCapture();
    #ifdef _DEBUG
          CString strText;
          GetWindowText(strText);
    #endif
          if(!m_bMouseOver){                              // mouse entered
                TRACE1("Cursor entered \'%s\' button.\n",strText.GetBuffer(1));
                m_bMouseOver = true;
                      Invalidate();
          }else{                                                // mouse moves above button
                CRect rect;
                GetClientRect(&rect);
                if(!rect.PtInRect(point)){            // mouse left button
                      TRACE1("Cursor left \'%s\' button.\n",strText.GetBuffer(1));
                      m_bMouseOver = false;
                      ReleaseCapture();
                      Invalidate();
                }
          }
          CButton::OnMouseMove(nFlags, point);
    }
     
    I hope i could help someone.

    GeneralRe: A better(?) solution for mouse leave/enter listeningmemberIgen18 Aug '06 - 22:43 
    Hi! I don't know what's happening here, but if I use the timer version, then it's working. If I'am using your solution then i've got the same asserts when debuging as Anonymus. And it's not showing in Release mode.
    GeneralRe: A better(?) solution for mouse leave/enter listeningmemberIgen19 Aug '06 - 19:22 
    OK! I think I got something. There's a limitiation in using the OnMouseMove in the Control, becouse it only activates when the mouse pointer IS over the Control. So when U try to use this, than U have to develop it with the Timer. It's clear and safe method, 'couse if U think a litle about it the mouse pointer read also developd with a timer in all Win. AND U use maximum 2 timers at a time, 'couse when U over the timer starts, and ends when U not. If I'am right than with the mouse reading timer the maximum is 2 timer (for a short time), 'couse it can happen that the mouse is over another Control, when the one (where it was before) is not stoped the timer alredy. IF i'am right.
     
    The Set/ReleaseCapture is only useable to 1 Control, becouse only 1 Control can Capture at a time and it's for not let any other Control capture mouse events. So I think the solution is U have to develop hovering outside the Control, or U can use the Timer solution. IF I'am right.
     
    Oh! The Asserts is becouse the Control Create method. Like in the 2 issue of this series I unfortunatly used the wrong variable and I Created the Control that's already created in the Dialog resource Smile | :)
    GeneralRe: A better(?) solution for mouse leave/enter listeningmemberi_a_z20 Sep '06 - 0:41 
    forget timers and mouse capturing, check this -> _TrackMouseEvent
    GeneralRe: A better(?) solution for mouse leave/enter listeningmemberlaxmangehlot27 Mar '07 - 3:26 
    Here is the code:
    Note THAT TIMER EVENT IS REMOVE.
     
    BEGIN_MESSAGE_MAP(CNewButton, CButton)
    //{{AFX_MSG_MAP(CNewButton)
    ON_WM_MOUSEMOVE()
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
    //ON_WM_TIMER()
    //}}AFX_MSG_MAP
    END_MESSAGE_MAP()
     
    /////////////////////////////////////////////////////////////////////////////
    // CNewButton message handlers
     
    void CNewButton::OnMouseLeave()
    {
    // after MouseLeave no tracking is done.
    // When the mouse leaves the window this function
    // is fired.
    // Your extra coding on mouse leave goes here....
     
    m_bOverControl = false;
    Invalidate(); // Force a redraw
    }
     

    void CNewButton::OnMouseMove(UINT nFlags, CPoint point)
    {
    if (!m_bOverControl) // Cursor has just moved over control
    {
    TRACE0("Entering control\n");
     
    m_bOverControl = TRUE; // Set flag telling us the mouse is in
    Invalidate(); // Force a redraw
     
    //SetTimer(m_nTimerID, 100, NULL); // Keep checking back every 1/10 sec
     
    // Do not track if already tracking
     
    TRACKMOUSEEVENT tme;
    tme.cbSize = sizeof(tme);
    tme.dwFlags = TME_LEAVE;
    tme.hwndTrack = m_hWnd;
    tme.dwHoverTime = HOVER_DEFAULT;
    //if(GetCapture() == this)
    ::_TrackMouseEvent(&tme);
    m_bOverControl = true;
    }
    // Your extra coding on mouse move goes here....

    CButton::OnMouseMove(nFlags, point);
    }
    GeneralDebugging probssussAnonymous10 Oct '05 - 2:55 
    hi Chris,
    I tried to debug the same what u did,but it gives debugging problem.Whenever i tried the control goes to wincore.cpp file and shows breakpoint in the following line Sleepy | :zzz:
     
    BOOL CWnd::Attach(HWND hWndNew)
    {
    ASSERT(m_hWnd == NULL); // only attach once, detach on destroy
    ASSERT(FromHandlePermanent(hWndNew) == NULL);

     
    another thing i can't understand about initialization of m_bOverControl & m_pTimerID member variable in constructor.So u please help me so that i can get the output rightSmile | :)
    AnswerRe: Debugging probsmemberzhankehua18 Aug '06 - 19:23 
    i am form china.you can download the source code.the source code is right.
    because the variable must be initialized so initialization of m_bOverControl & m_pTimerID member variable in constructor to give them a initial state.
     
    I am from china

    GeneralRe: Debugging probsmemberLeonhardt Wille5 Dec '06 - 3:00 
    Hi Chris,
    I also have the same problem.
    I'm trying to subclass a CTreeView's CTreeCtrl window with my own TreeCtrl derivate, to customize drawing of the tree items without having to use a totally custom-built tree ctrl.
    When I call CTreeView::SubclassWindow in the OnInitialUpdate, I have the same problem as the Anonymous in the previous post.
    FromHandlePermanent doesn't return NULL as assumed by AttachWindow, as the window handle of the CTreeView is already contained in the permanent handle map (LookupPermanent returns valid handle). The question is, where do I have to place the SubclassWindow call so that the window isn't yet in the permanent map?
    Is subclassing the view the easiest way at all (for derivated CCtrlView classes)?
     
    In your sample code you only show how to subclass windows using DDX_Control, which is the easiest way when doing dialog apps. Do you have a snippet how to do it with CTreeView/CListView (or other CCtrlViews)?
     
    Thanks for your articles and for your help in advance.
    GeneralIs It possible to create controls (listbox) without the vertical scroll bar !!!memberraja_krish15 Aug '05 - 20:46 
    Hi Chris,
     
    I had been going through your articles(both MFC and Web Services), I found it very interesting and simple to understand Smile | :) . I have a doubt...Is it possible to disable the default vertical scrollbar from a listbox so that the custom scrollbar which I have created could be incorporated ??? I dont want this to be done in MFC (client requirement Cry | :(( ).....Any help regarding this is highly appreciated.
     

     
    With Thanks and Regards,
    Raja
    Programmer,
    Ventech Solutions (India) Pvt. Ltd.
    Chennai.
    India.
    Questionstrange behavior?memberC.T.Wu13 Mar '05 - 16:14 
    Remove the 175 line of SubclassDemoDlg.cpp:// MessageBox("Button Clicked!");
    Add a button to the dialog
    Mouse click quickly, compare the subclass button and the new button,
    the subclass button update blunted.Why?Confused | :confused:
     
    Thanks..

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Permalink | Advertise | Privacy | Mobile
    Web03 | 2.6.130523.1 | Last Updated 26 Oct 2001
    Article Copyright 2000 by Chris Maunder
    Everything else Copyright © CodeProject, 1999-2013
    Terms of Use
    Layout: fixed | fluid