Click here to Skip to main content
11,711,750 members (80,215 online)
Click here to Skip to main content

How to use an ATL-control with MFC

, 11 Dec 2000 213.5K 2K 75
Rate this:
Please Sign up or sign in to vote.
A step by step tutorial explaining how to use an ATL-control with MFC
  • Download the demo application - 46 Kb
  • Introduction

    This article shows you how can use an ATL-control with MFC. I've received a lot of e-mail with the question how you can use the FileMonitor-control with MFC. The example I'm using is a simple MFC-dialog based program that notifies the user when there are files created, modified or deleted in the temporary-file directory.

    Step 1: Create a MFC-dialog program.

    • Create a new project. Select MFC(exe) program in the AppWizard. Accept all the defaults. It's not necessary to select automation.

    Step 2: Add a sink-object.

    To receive events from an ATL-control you have to create an ATL-object that links with the control. This object is called a sink-object.

    • Select Insert / Insert New ATL Object.
    • Click 'Yes' on the following question:

      AddATLtoMFC.JPG (22397 bytes)

    • Select a single object

      ATLSimpleObject.JPG (58674 bytes)

    • Use FileMonitorSink as Short Name of the object. Don't change the other fields.

      ATLObjectWizard1.JPG (68460 bytes)

      Accept the default in the Attributes tab.

      ATLObjectWizard2.JPG (61288 bytes)

    Step 3: Change the OBJECT-map.

    • Because you don't want to let other applications create your sink-object, you have to change the OBJECT-map in the TempMonitor.cpp as follows:
      BEGIN_OBJECT_MAP(ObjectMap)<BR>      
      OBJECT_ENTRY_NON_CREATEABLE(CFileMonitorSink)<BR>END_OBJECT_MAP()

    Step 4: Import the type-library of FileMonitor

    By importing the type-library (the .tlb file), the content of the type-library is converted to C++ classes, mostly describing the interfaces. This makes it easy for us to use the interfaces of the FileMonitor-control.

    • Add the following code to stdafx.h
      #import  "..\\FileMonitor\\FileMonitor.tlb"  named_guids

    For more information on #import see your MSDN library. If you don't want to use namespaces you could add the parameter no_namespace to the statement. I like the use of namespaces, so I don't use no_namespaces.

    Step 5: Finishing the code for the FileMonitorSink object.

    Select the headerfile of the FileMonitorSink. In our example this is FileMonitorSink.h

    • Derive your class from
      public IDispEventImpl<1, CFileMonitorSink, 
                    &FILEMONITOR::DIID__IWatchEvents, &FILEMONITOR::LIBID_FILEMONITOR, 1, 0>

      The first parameter is an ID. You use this also in the SINK-map.

    • Add the following to the COM-map
      COM_INTERFACE_ENTRY_IID(FILEMONITOR::DIID__IWatchEvents, IDispatch)
    • Create a Sink map
      BEGIN_SINK_MAP(CFileMonitorSink)
         SINK_ENTRY_EX(1, FILEMONITOR::DIID__IWatchEvents, 1, OnNotify)<BR>END_SINK_MAP()

      The Filemonitor sends an event Notify with a BSTR parameter and an integer parameter. The first parameter is the ID we've used in the IDispEventImpl. The third parameter is the DISDIP of the method in the interface IWatchEvents.

    • Add the OnNotify() method to your class
      void __stdcall OnNotify(BSTR sPathName, short nType)
      {
          AFX_MANAGE_STATE(AfxGetAppModuleState())
          MessageBox(NULL, _T("File notification"), _T("FileMonitorApp"), MB_OK);
      } 

      Note the use of AFX_MANAGE_STATE macro. You have to use this in every method of this class. See for more information about this in step 7. At the moment we use a MessageBox to notify us when the sink-interface receives an event. At a later time we will change that code.

    Step 6: Change the Application.

    Select the headerfile which define the dialog. In our example this is TempMonitorDlg.h.

    • Add a member which contains a pointer to the IWatch interface of the FileMonitor control
      CComPtr<FILEMONITOR::IWatch> m_FileMonitor;
    • Add a member which is a COM-object of the sink interface.
      CComObject<CFileMonitorSink>  *m_FileMonitorSink;
    • Add the following code to the OnInitDialog-method
      m_FileMonitor.CoCreateInstance(__uuidof(FILEMONITOR::Watch), NULL, CLSCTX_INPROC_SERVER);
      CComObject<CFileMonitorSink>::CreateInstance(&m_FileMonitorSink);

    Step 7: Link the Sink-interface to the FileMonitor-control.

    Before we can receive events from the FileMonitor, we've to link the Sink-interface to the FileMonitor-control. This is also called Advising. Because we've implemented IDispEventImpl in the sink object, we can use the method DispEventAdvise.

    • Add a member to CFileMonitorSink class to hold the IUnknown interface of FileMonitor
      CComPtr<IUnknown> m_Object;
    • Add a method Start to the IFileMonitorSink interface as follows:

    StartMethod.JPG (53493 bytes)

    The first parameter is the object we want to advise. The second parameter will notify us if the advise succeeded or not. This method will be used to advise the FileMonitor.

    This is the code for the Start-method:

    STDMETHODIMP CFileMonitorSink::Start(IUnknown *pSinkThisObject, VARIANT_BOOL *succeeded)
    {
        AFX_MANAGE_STATE(AfxGetAppModuleState())
    
        if ( DispEventAdvise(pSinkThisObject)  == S_OK)
        {
            m_Object = pSinkThisObject;
            *succeeded = VARIANT_TRUE;
        }
        else
        {
            *succeeded = VARIANT_FALSE;
        }
        return S_OK;
    } 

    A Note about the AFX_MANAGE_STATE() macro. Visual C++ generates the wrong code for it. You have to change   AFX_MANAGE_STATE(AfxGetStaticModuleState()) to the code above. This is a bug in Visual C++. Check this every time you add a method to an ATL-object in a MFC application. You can read more about this in the Q231592 article of Microsoft.

    • Add a method Stop to the IFileMonitorSink interface as follows:

      StopMethod.JPG (42132 bytes)

      This method will be used to unadvise the FileMonitor.
      This is the code for the method:
      STDMETHODIMP CFileMonitorSink::Stop()
      {
          AFX_MANAGE_STATE(AfxGetAppModuleState())
      
          if ( m_Object )
          {
              DispEventUnadvise(m_Object);
          }
          return S_OK;
      }

    Step 8: Start the sinking of the FileMonitor events.

    • Change the OnInitDialog method after the creation of the sink-object.
      VARIANT_BOOL succeeded;
      m_FileMonitorSink->Start(m_FileMonitor, &succeeded);
    • Handle the WM_DESTROY-message as follows:
      void CTempMonitorDlg::OnDestroy() 
      {
         CDialog::OnDestroy();
         m_FileMonitorSink->Stop();     
      }

    Step 9: Add the code for monitoring the temporary file directory.

    • Add the following code to the OnInitDialog() after the call of the Start() method
      // Monitor the temporaryfile directory
      TCHAR tszBuf[MAX_PATH];
      if (0 == GetTempPath(MAX_PATH, tszBuf))         // This should never fail
      {
          MessageBox("Unable to locate the temporaryfile directory !");
      }
      else
      {
          m_FileMonitor->AddPath(tszBuf);
          m_FileMonitor->Start = VARIANT_TRUE;
      }

    Step 10: Compile and run the first test.

    • When the program is running, then try to change, delete or create a file in the temporary directory. On my system this was the C:\Windows\Temp. You should see the messagebox, when you do this.

    Step 11: Finishing our application.

    Note : If you find another way which is better than this, please notify me. I've created this example with lots of information I've find on the internet and in the "Professional ATL COM" Programming book.

    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

    Share

    About the Author

    Franky Braem
    Web Developer
    Belgium Belgium
    Programmer since 1991 using C/C++/Visual Basic and Java. Playing with wxWindows at home.

    You may also be interested in...

    Comments and Discussions

     
    QuestionHow to track whether the application is renamed/deleted/created through this MFC application Pin
    Member 927486411-Sep-12 18:05
    memberMember 927486411-Sep-12 18:05 
    QuestionThrough this MFC application how to track whether the application is renamed/deleted/created Pin
    Member 927486411-Sep-12 18:04
    memberMember 927486411-Sep-12 18:04 
    QuestionError while creating a plugin for windows media player. Pin
    amiya das4-Jan-08 2:15
    memberamiya das4-Jan-08 2:15 
    GeneralError In VC 2005 Pin
    Gaurang Shah 03310-Aug-07 2:43
    memberGaurang Shah 03310-Aug-07 2:43 
    GeneralFilemonitor.tlb Pin
    RussyB10-Mar-04 10:29
    memberRussyB10-Mar-04 10:29 
    GeneralRe: Filemonitor.tlb Pin
    *Dreamz19-Apr-04 23:38
    member*Dreamz19-Apr-04 23:38 
    GeneralRe: Filemonitor.tlb Pin
    lilesh14-Nov-05 0:50
    memberlilesh14-Nov-05 0:50 
    QuestionWhat about ATL/MCF 7.0 ? Pin
    amosl5-Feb-03 11:39
    memberamosl5-Feb-03 11:39 
    GeneralUnhandled exception in TempMonitor.Exe: 0xC0000005: Access Violation Pin
    Hazem Nasereddin15-Jan-03 3:22
    memberHazem Nasereddin15-Jan-03 3:22 
    GeneralDo u have any idea about ...... Pin
    Saeed A. Siddiqui7-Nov-02 22:44
    memberSaeed A. Siddiqui7-Nov-02 22:44 
    GeneralFatal Error while linking. Pin
    Sat_hsk15-Jul-02 19:55
    memberSat_hsk15-Jul-02 19:55 
    Generalredefine label for menu or messagebox Pin
    ltthoi15-May-02 15:25
    memberltthoi15-May-02 15:25 
    GeneralDeriving IDispEventImpl Question Pin
    llangolas16-Nov-01 1:23
    memberllangolas16-Nov-01 1:23 
    Generalfatal error occurred when running the program Pin
    Anonymous8-Nov-01 10:05
    memberAnonymous8-Nov-01 10:05 
    GeneralRe: fatal error occurred when running the program Pin
    Carlos Antollini8-Nov-01 10:10
    memberCarlos Antollini8-Nov-01 10:10 
    GeneralRe: fatal error occurred when running the program Pin
    Anonymous8-Nov-01 10:15
    memberAnonymous8-Nov-01 10:15 
    GeneralRe: fatal error occurred when running the program Pin
    Carlos Antollini8-Nov-01 10:29
    memberCarlos Antollini8-Nov-01 10:29 
    GeneralRe: fatal error occurred when running the program Pin
    Carlos Antollini8-Nov-01 10:37
    memberCarlos Antollini8-Nov-01 10:37 
    GeneralRe: fatal error occurred when running the program Pin
    Anonymous8-Nov-01 10:39
    memberAnonymous8-Nov-01 10:39 
    GeneralRe: fatal error occurred when running the program Pin
    Hazem Nasereddin15-Jan-03 3:20
    memberHazem Nasereddin15-Jan-03 3:20 
    GeneralConnection made, but not getting to handler Pin
    Dave Curry26-Jun-01 13:41
    memberDave Curry26-Jun-01 13:41 
    GeneralIDispEventImpl Problems Pin
    Anonymous22-Jun-01 10:41
    memberAnonymous22-Jun-01 10:41 
    GeneralProblem adapting your example Pin
    Dave Curry12-Jun-01 13:16
    memberDave Curry12-Jun-01 13:16 
    GeneralNeed help (3 Errors) Pin
    Ryan8-Jun-01 8:25
    memberRyan8-Jun-01 8:25 
    GeneralRe: Need help (3 Errors) Pin
    Carlos Antollini8-Jun-01 9:30
    memberCarlos Antollini8-Jun-01 9:30 
    GeneralRe: Need help (3 Errors) Pin
    Ryan14-Jun-01 11:02
    memberRyan14-Jun-01 11:02 
    GeneralRe: Need help (3 Errors) Pin
    Carlos Antollini14-Jun-01 11:49
    memberCarlos Antollini14-Jun-01 11:49 
    GeneralRe: Need help (3 Errors) Pin
    GANsJob24-Sep-06 20:45
    memberGANsJob24-Sep-06 20:45 
    QuestionHow to do this with a dynamically created control? Pin
    Mike Ryan5-Mar-01 8:45
    memberMike Ryan5-Mar-01 8:45 
    AnswerRe: How to do this with a dynamically created control? Pin
    F Braem6-Mar-01 3:34
    memberF Braem6-Mar-01 3:34 
    GeneralRe: How to do this with a dynamically created control? Pin
    Mike Ryan6-Mar-01 6:28
    memberMike Ryan6-Mar-01 6:28 
    GeneralDialog ... Pin
    Hadi_Rezaie15-Feb-01 6:43
    memberHadi_Rezaie15-Feb-01 6:43 
    GeneralWhere do I get FileMonitor.tlb file Pin
    Anonymous3-Jan-01 10:18
    memberAnonymous3-Jan-01 10:18 
    GeneralRe: Where do I get FileMonitor.tlb file Pin
    F Braem29-Jan-01 21:55
    memberF Braem29-Jan-01 21:55 
    GeneralRe: Where do I get FileMonitor.tlb file Pin
    Anonymous21-Feb-01 20:54
    memberAnonymous21-Feb-01 20:54 
    GeneralIt is ! Pin
    F Braem6-Mar-01 3:41
    memberF Braem6-Mar-01 3:41 
    GeneralRe: It is ! Pin
    Jay Wheeler8-May-01 10:28
    memberJay Wheeler8-May-01 10:28 
    GeneralRe: It is ! Pin
    F Braem8-May-01 21:42
    memberF Braem8-May-01 21:42 
    GeneralRe: It is ! Pin
    Hazem Nasereddin14-Jan-03 23:51
    memberHazem Nasereddin14-Jan-03 23:51 
    GeneralRe: It is ! Pin
    Anonymous16-Jan-03 10:56
    sussAnonymous16-Jan-03 10:56 
    GeneralRe: Where do I get FileMonitor.tlb file Pin
    lilyshining21-Mar-03 13:49
    memberlilyshining21-Mar-03 13:49 
    GeneralRe: Where do I get FileMonitor.tlb file Pin
    iklef30-Jul-03 3:19
    memberiklef30-Jul-03 3:19 
    GeneralWhere do I get FileMonitor.tlb file Pin
    Anonymous3-Jan-01 10:17
    memberAnonymous3-Jan-01 10:17 
    GeneralLink to homepage misspelt Pin
    Anonymous11-Dec-00 22:35
    memberAnonymous11-Dec-00 22:35 

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

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Terms of Use | Mobile
    Web04 | 2.8.150819.1 | Last Updated 12 Dec 2000
    Article Copyright 2000 by Franky Braem
    Everything else Copyright © CodeProject, 1999-2015
    Layout: fixed | fluid