Aggiunta di un evento (Esercitazione di ATL, parte 5)

In questo passaggio si aggiungerà un ClickIn oggetto e un ClickOut evento al controllo ATL. Verrà generato l'evento ClickIn se l'utente fa clic all'interno del poligono e verrà attivato ClickOut se l'utente fa clic all'esterno. Le attività per aggiungere un evento sono le seguenti:

  • Aggiunta dei ClickIn metodi e ClickOut

  • Generazione della libreria dei tipi

  • Implementazione delle interfacce punto di Connessione ion

Aggiunta dei metodi ClickIn e ClickOut

Dopo aver creato il controllo ATL nel passaggio 2, è stata selezionata la casella di controllo punti di Connessione ion. L'interfaccia _IPolyCtlEvents è stata creata nel file Polygon.idl. Si noti che il nome dell'interfaccia inizia con un carattere di sottolineatura. Si tratta di una convenzione per indicare che l'interfaccia è un'interfaccia interna. Pertanto, i programmi che consentono di esplorare gli oggetti COM possono scegliere di non visualizzare l'interfaccia all'utente. Si noti anche che selezionando Connessione punti di Connessione ion è stata aggiunta la riga seguente nel file Polygon.idl per indicare che _IPolyCtlEvents è l'interfaccia di origine predefinita:

[default, source] dispinterface _IPolyCtlEvents;

L'attributo di origine indica che il controllo è l'origine delle notifiche, quindi chiamerà questa interfaccia nel contenitore.

Aggiungere ora i ClickIn metodi e ClickOut all'interfaccia _IPolyCtlEvents .

Per aggiungere i metodi ClickIn e ClickOut

  1. In Esplora soluzioni aprire Polygon.idl e aggiungere il codice methods: seguente in nella dispInterface_IPolyCtlEvents dichiarazione della libreria PolygonLib:

    [id(1), helpstring("method ClickIn")] void ClickIn([in] LONG x,[in] LONG y);
    [id(2), helpstring("method ClickOut")] void ClickOut([in] LONG x,[in] LONG y);
    

I ClickIn metodi e ClickOut accettano le coordinate x e y del punto selezionato come parametri.

Generazione della libreria dei tipi

Generare la libreria dei tipi a questo punto, perché il progetto lo userà per ottenere le informazioni necessarie per costruire un'interfaccia del punto di connessione e un'interfaccia del contenitore del punto di connessione per il controllo.

Per generare la libreria dei tipi

  1. Ricompilare il progetto.

    -oppure-

  2. Fare clic con il pulsante destro del mouse sul file Polygon.idl in Esplora soluzioni e scegliere Compila dal menu di scelta rapida.

Verrà creato il file Polygon.tlb, ovvero la libreria dei tipi. Il file Polygon.tlb non è visibile da Esplora soluzioni, perché è un file binario e non può essere visualizzato o modificato direttamente.

Implementazione delle interfacce punto di Connessione ion

Implementare un'interfaccia del punto di connessione e un'interfaccia del contenitore del punto di connessione per il controllo. In COM gli eventi vengono implementati tramite il meccanismo dei punti di connessione. Per ricevere eventi da un oggetto COM, un contenitore stabilisce una connessione consultiva al punto di connessione implementato dall'oggetto COM. Poiché un oggetto COM può avere più punti di connessione, l'oggetto COM implementa anche un'interfaccia contenitore del punto di connessione. Tramite questa interfaccia, il contenitore può determinare quali punti di connessione sono supportati.

L'interfaccia che implementa un punto di connessione è denominata IConnectionPointe l'interfaccia che implementa un contenitore di punti di connessione è denominata IConnectionPointContainer.

Per implementare IConnectionPoint, si userà la Procedura guidata Implementa punto di Connessione ion. Questa procedura guidata genera l'interfaccia IConnectionPoint leggendo la libreria dei tipi e implementando una funzione per ogni evento che può essere generato.

Per implementare i punti di connessione

  1. In Esplora soluzioni aprire _IPolyCtlEvents_CP.h e aggiungere il codice seguente sotto l'istruzione public: nella CProxy_IPolyCtlEvents classe :

    VOID Fire_ClickIn(LONG x, LONG y)
    {
        T* pT = static_cast<T*>(this);
        int nConnectionIndex;
        CComVariant* pvars = new CComVariant[2];
        int nConnections = m_vec.GetSize();
    
        for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
        {
            pT->Lock();
            CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
            pT->Unlock();
            IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
            if (pDispatch != NULL)
            {
                pvars[1].vt = VT_I4;
                pvars[1].lVal = x;
                pvars[0].vt = VT_I4;
                pvars[0].lVal = y;
                DISPPARAMS disp = { pvars, NULL, 2, 0 };
                pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
            }
        }
        delete[] pvars;
    
    }
    VOID Fire_ClickOut(LONG x, LONG y)
    {
        T* pT = static_cast<T*>(this);
        int nConnectionIndex;
        CComVariant* pvars = new CComVariant[2];
        int nConnections = m_vec.GetSize();
    
        for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
        {
            pT->Lock();
            CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
            pT->Unlock();
            IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
            if (pDispatch != NULL)
            {
                pvars[1].vt = VT_I4;
                pvars[1].lVal = x;
                pvars[0].vt = VT_I4;
                pvars[0].lVal = y;
                DISPPARAMS disp = { pvars, NULL, 2, 0 };
                pDispatch->Invoke(0x2, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
            }
        }
        delete[] pvars;
    
    }
    

Si noterà che questo file ha una classe denominata CProxy_IPolyCtlEvents che deriva da IConnectionPointImpl. _IPolyCtlEvents_CP.h definisce ora i due metodi Fire_ClickIn e Fire_ClickOut, che accettano i due parametri di coordinate. Questi metodi vengono chiamati quando si desidera generare un evento dal controllo.

Creando il controllo con l'opzione punti di Connessione ion selezionata, il file _IPolyCtlEvents_CP.h è stato generato automaticamente. Viene inoltre aggiunto CProxy_PolyEvents e IConnectionPointContainerImpl all'elenco di ereditarietà multipla del controllo ed esposto IConnectionPointContainer aggiungendo voci appropriate alla mappa COM.

È stata completata l'implementazione del codice per supportare gli eventi. Aggiungere ora del codice per generare gli eventi nel momento appropriato. Tenere presente che si attiverà un ClickIn evento o ClickOut quando l'utente fa clic sul pulsante sinistro del mouse nel controllo. Per scoprire quando l'utente fa clic sul pulsante, aggiungere un gestore per il WM_LBUTTONDOWN messaggio.

Per aggiungere un gestore per il messaggio di WM_LBUTTONDOWN

  1. In Visualizzazione classi fare clic con il pulsante destro del mouse sulla CPolyCtl classe e scegliere Proprietà dal menu di scelta rapida.

  2. Nella finestra Proprietà fare clic sull'icona Messaggi e quindi fare clic WM_LBUTTONDOWN sull'elenco a sinistra.

  3. Nell'elenco a discesa visualizzato fare clic su <Aggiungi> OnLButtonDown. La OnLButtonDown dichiarazione del gestore verrà aggiunta a PolyCtl.h e l'implementazione del gestore verrà aggiunta a PolyCtl.cpp.

Modificare quindi il gestore.

Per modificare il metodo OnLButtonDown

  1. Modificare il codice che comprende il OnLButtonDown metodo in PolyCtl.cpp (eliminando qualsiasi codice inserito dalla procedura guidata) in modo che abbia un aspetto simile al seguente:

    LRESULT CPolyCtl::OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, 
       BOOL& /*bHandled*/)
    {
       HRGN hRgn;
       WORD xPos = LOWORD(lParam);  // horizontal position of cursor
       WORD yPos = HIWORD(lParam);  // vertical position of cursor
    
       CalcPoints(m_rcPos);
    
       // Create a region from our list of points
       hRgn = CreatePolygonRgn(&m_arrPoint[0], m_nSides, WINDING);
    
       // If the clicked point is in our polygon then fire the ClickIn
       //  event otherwise we fire the ClickOut event
       if (PtInRegion(hRgn, xPos, yPos))
          Fire_ClickIn(xPos, yPos);
       else
          Fire_ClickOut(xPos, yPos);
    
       // Delete the region that we created
       DeleteObject(hRgn);
       return 0;
    }
    

Questo codice usa i punti calcolati nella OnDraw funzione per creare un'area che rileva i clic del mouse dell'utente con la chiamata a PtInRegion.

Il parametro uMsg è l'ID del messaggio di Windows gestito. In questo modo è possibile avere una funzione che gestisce un intervallo di messaggi. I parametri wParam e lParam sono i valori standard per il messaggio gestito. Il parametro bHandled consente di specificare se la funzione ha gestito o meno il messaggio. Per impostazione predefinita, il valore è impostato su TRUE per indicare che la funzione ha gestito il messaggio, ma è possibile impostarla su FAL edizione Standard. In questo modo ATL continuerà a cercare un'altra funzione del gestore di messaggi a cui inviare il messaggio.

Compilazione e test del controllo

Provare ora gli eventi. Compilare il controllo e avviare di nuovo il contenitore di test del controllo ActiveX. Questa volta, visualizzare la finestra del registro eventi. Per instradare gli eventi alla finestra di output, fare clic su Registrazione dal menu Opzioni e selezionare Registra nella finestra di output. Inserire il controllo e provare a fare clic nella finestra. Si noti che ClickIn viene generato se si fa clic all'interno del poligono riempito e ClickOut viene generato quando si fa clic all'esterno di esso.

Successivamente, si aggiungerà una pagina delle proprietà.

Tornare al passaggio 4 | al passaggio 6

Vedi anche

Esercitazione