Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. ATL / WTL / STL
  4. non dialog object sink advise causing assert to be thrown during advise initialisation

non dialog object sink advise causing assert to be thrown during advise initialisation

Scheduled Pinned Locked Moved ATL / WTL / STL
c++comhardware
5 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    TClarke
    wrote on last edited by
    #1

    Hi all, I have an ATL control based on CComCompositeControl. In the control's dialog box I have a web browser, from which I am sinking events. I also have another COM object which is not on the dialog box from which I'm sinking events. I'm getting an assert thrown as my control initialises in AtlAdviseSinkMap. In this ATL method there is a loop which goes over all the ids of the sink entries and calls:

    	HWND h = pT->GetDlgItem(pEntries->nControlID);
    	ATLASSERT(h != NULL);
    

    While this works perfectly for the embedded web browser, the other object not on the dialog box causes an exception. Is there a setting I can use to inform the initialisation that it is not a dialog object and that this is not appropriate but without the assert being thrown. Many thanks

    Cheers Tom Philosophy: The art of never getting beyond the concept of life. Religion: Morality taking credit for the work of luck.

    J 1 Reply Last reply
    0
    • T TClarke

      Hi all, I have an ATL control based on CComCompositeControl. In the control's dialog box I have a web browser, from which I am sinking events. I also have another COM object which is not on the dialog box from which I'm sinking events. I'm getting an assert thrown as my control initialises in AtlAdviseSinkMap. In this ATL method there is a loop which goes over all the ids of the sink entries and calls:

      	HWND h = pT->GetDlgItem(pEntries->nControlID);
      	ATLASSERT(h != NULL);
      

      While this works perfectly for the embedded web browser, the other object not on the dialog box causes an exception. Is there a setting I can use to inform the initialisation that it is not a dialog object and that this is not appropriate but without the assert being thrown. Many thanks

      Cheers Tom Philosophy: The art of never getting beyond the concept of life. Religion: Morality taking credit for the work of luck.

      J Offline
      J Offline
      Jonathan Davies
      wrote on last edited by
      #2

      You must have added that setting somehow. Just taking some example code from an ATL object of mine that sinks events from a non control as a guide I have: a typedef to make things readable:

      const UINT ID_QUEUEDEVENTS = 1;

      typedef IDispEventImpl<ID_QUEUEDEVENTS, CMSMQEventControl, &DIID__IQueueMonitorEvents ,&LIBID_MSMQEVENTTEST2Lib ,1,0> IQueueMonitorEventSink ;

      Then the beginning of class which inherits (the typedef):

      public IQueueMonitorEventSink,

      Then a sink map for the events:

      BEGIN_SINK_MAP(CMSMQEventControl)
      // Sinks map entries required by IMSMQEventControlImpl
      SINK_ENTRY_EX(ID_QUEUEDEVENTS , DIID__IQueueMonitorEvents, 1, QueuedMessage) // Received a message
      SINK_ENTRY_EX(ID_QUEUEDEVENTS , DIID__IQueueMonitorEvents, 2, QueuedError) // Received an error
      END_SINK_MAP()

      Do you have something different?

      T 1 Reply Last reply
      0
      • J Jonathan Davies

        You must have added that setting somehow. Just taking some example code from an ATL object of mine that sinks events from a non control as a guide I have: a typedef to make things readable:

        const UINT ID_QUEUEDEVENTS = 1;

        typedef IDispEventImpl<ID_QUEUEDEVENTS, CMSMQEventControl, &DIID__IQueueMonitorEvents ,&LIBID_MSMQEVENTTEST2Lib ,1,0> IQueueMonitorEventSink ;

        Then the beginning of class which inherits (the typedef):

        public IQueueMonitorEventSink,

        Then a sink map for the events:

        BEGIN_SINK_MAP(CMSMQEventControl)
        // Sinks map entries required by IMSMQEventControlImpl
        SINK_ENTRY_EX(ID_QUEUEDEVENTS , DIID__IQueueMonitorEvents, 1, QueuedMessage) // Received a message
        SINK_ENTRY_EX(ID_QUEUEDEVENTS , DIID__IQueueMonitorEvents, 2, QueuedError) // Received an error
        END_SINK_MAP()

        Do you have something different?

        T Offline
        T Offline
        TClarke
        wrote on last edited by
        #3

        Hi, thanks for the response. I have something very similar. In my class declaration I have:

        public IDispEventSimpleImpl<0, COfficeDlgX, &__uuidof(_IOfficeAutomaterEvents)>,
        public IDispEventImpl<IDC_WB,COfficeDlgX>,

        In my class I then create a typedef for calling the advise method.

        typedef IDispEventSimpleImpl<0, COfficeDlgX, &__uuidof(_IOfficeAutomaterEvents)> OfficeAutomaterEventsImpl;

        Then I generate the sink map:

        BEGIN_SINK_MAP(COfficeDlgX)
        SINK_ENTRY(IDC_WB, 259, DocumentCompleteWb)
        SINK_ENTRY(IDC_WB, 252, NavigateComplete2Wb)
        SINK_ENTRY(IDC_WB, 250, BeforeNavigate2Wb)
        SINK_ENTRY_INFO(0, __uuidof(_IOfficeAutomaterEvents), 1, &COfficeDlgX::__OnDocumentClosed, &OnMenuItemClickedInfo)
        SINK_ENTRY_INFO(0, __uuidof(_IOfficeAutomaterEvents), 2, &COfficeDlgX::__OnMenuItemClicked, &OnMenuItemClickedInfo)
        END_SINK_MAP()

        in my code, when I create an instance of IOfficeAutomater I call:

        hr = OfficeAutomaterEventsImpl::DispEventAdvise((IUnknown*)m_spOfficeAutomater, &__uuidof(_IOfficeAutomaterEvents));

        IDC_WB is the dialog id of my WebBrowser. I don't have to call DispEventAdvise for the web browser control myself as the framework does it for me. It does it by using the id to get to the control. Herein lies the problem. Somehow, the framework now thinks all the sink entry ids refer to an item on the dialog box. The system therefore runs through all the sink entry id and calls GetDlgItem with them. When it uses the id of my non dialog item ie 0, it of course comes back NULL. This value runs through an assert and hey presto I get a message box up telling me something's wrong. On one hand it's only an assert and so it won't come up in the release build and it in no way affects whether my app works or not but it does seem very messy. What would be ideal is having two sink maps. One for dialog items and the other for anything else.

        Cheers Tom Philosophy: The art of never getting beyond the concept of life. Religion: Morality taking credit for the work of luck.

        J 1 Reply Last reply
        0
        • T TClarke

          Hi, thanks for the response. I have something very similar. In my class declaration I have:

          public IDispEventSimpleImpl<0, COfficeDlgX, &__uuidof(_IOfficeAutomaterEvents)>,
          public IDispEventImpl<IDC_WB,COfficeDlgX>,

          In my class I then create a typedef for calling the advise method.

          typedef IDispEventSimpleImpl<0, COfficeDlgX, &__uuidof(_IOfficeAutomaterEvents)> OfficeAutomaterEventsImpl;

          Then I generate the sink map:

          BEGIN_SINK_MAP(COfficeDlgX)
          SINK_ENTRY(IDC_WB, 259, DocumentCompleteWb)
          SINK_ENTRY(IDC_WB, 252, NavigateComplete2Wb)
          SINK_ENTRY(IDC_WB, 250, BeforeNavigate2Wb)
          SINK_ENTRY_INFO(0, __uuidof(_IOfficeAutomaterEvents), 1, &COfficeDlgX::__OnDocumentClosed, &OnMenuItemClickedInfo)
          SINK_ENTRY_INFO(0, __uuidof(_IOfficeAutomaterEvents), 2, &COfficeDlgX::__OnMenuItemClicked, &OnMenuItemClickedInfo)
          END_SINK_MAP()

          in my code, when I create an instance of IOfficeAutomater I call:

          hr = OfficeAutomaterEventsImpl::DispEventAdvise((IUnknown*)m_spOfficeAutomater, &__uuidof(_IOfficeAutomaterEvents));

          IDC_WB is the dialog id of my WebBrowser. I don't have to call DispEventAdvise for the web browser control myself as the framework does it for me. It does it by using the id to get to the control. Herein lies the problem. Somehow, the framework now thinks all the sink entry ids refer to an item on the dialog box. The system therefore runs through all the sink entry id and calls GetDlgItem with them. When it uses the id of my non dialog item ie 0, it of course comes back NULL. This value runs through an assert and hey presto I get a message box up telling me something's wrong. On one hand it's only an assert and so it won't come up in the release build and it in no way affects whether my app works or not but it does seem very messy. What would be ideal is having two sink maps. One for dialog items and the other for anything else.

          Cheers Tom Philosophy: The art of never getting beyond the concept of life. Religion: Morality taking credit for the work of luck.

          J Offline
          J Offline
          Jonathan Davies
          wrote on last edited by
          #4

          Looking at my ATL Internals (B.Rector & C.Sells) they say: Easiest way...event sinks...derive ... from IDispEventImpl... ... when the event source is a contained control and the event recipient is a composite control, the identifier is the contained control's child window identifier. When your class is a composite control, you should use the AtlAdviseSinkMap function to establish and remove connections...of the contained controls listed in the sink map...Using CWindow::GetDlgItem method, AtlAdviseSinkMap navigates to a child window handle... When your class isn't a composite control you must explicitly call the DispEventAdvise method of each of your IDispEventSimpleImpl ... base classes to connect. You seem to have the correct use of IDispEventImpl and IDispEventSimpleImpl. It also seems use of AtlAdviseSinkMap is out due to its requirement of "contained controls listed in the sink map" as one of your mapped controls isn't contained - as you say. So it seems you can't prevent AtlAdviseSinkMap calling GetDlgItem. All it would seem you can do is not use AtlAdviseSinkMap but do it manually by using GetDlgItem etc on one and "explicitly call the DispEventAdvise" of the other (or both).

          T 1 Reply Last reply
          0
          • J Jonathan Davies

            Looking at my ATL Internals (B.Rector & C.Sells) they say: Easiest way...event sinks...derive ... from IDispEventImpl... ... when the event source is a contained control and the event recipient is a composite control, the identifier is the contained control's child window identifier. When your class is a composite control, you should use the AtlAdviseSinkMap function to establish and remove connections...of the contained controls listed in the sink map...Using CWindow::GetDlgItem method, AtlAdviseSinkMap navigates to a child window handle... When your class isn't a composite control you must explicitly call the DispEventAdvise method of each of your IDispEventSimpleImpl ... base classes to connect. You seem to have the correct use of IDispEventImpl and IDispEventSimpleImpl. It also seems use of AtlAdviseSinkMap is out due to its requirement of "contained controls listed in the sink map" as one of your mapped controls isn't contained - as you say. So it seems you can't prevent AtlAdviseSinkMap calling GetDlgItem. All it would seem you can do is not use AtlAdviseSinkMap but do it manually by using GetDlgItem etc on one and "explicitly call the DispEventAdvise" of the other (or both).

            T Offline
            T Offline
            TClarke
            wrote on last edited by
            #5

            Thanks for your advice. It's much appreciated. I now know I'm not just being goofy about things too. Which is always good :)

            Cheers Tom Philosophy: The art of never getting beyond the concept of life. Religion: Morality taking credit for the work of luck.

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups