Поддержка модальных и немодальных диалогов в элементах управления ActiveX - PullRequest
0 голосов
/ 17 мая 2019

Я хочу создать элемент управления ActiveX, поддерживающий модальные и немодальные диалоги, которые можно использовать на нескольких вкладках IE9 ~ IE11 одновременно.Это означает, что всплывающее диалоговое окно элемента управления ActiveX на текущей вкладке IE не помешает нам перейти на другие вкладки IE, и эти диалоги появляются только на текущей вкладке IE.Сначала я создал приложение библиотеки динамических ссылок (DLL) ATL с именем AtlActiveX, используя ATL / C ++ от Visual Studio 2010. Затем добавьте элемент управления ActiveX с именем AtlActiveXCtl, указав параметр Разрешить слияние кода прокси / заглушки и параметров IObjectWithSite (поддержка объектов IE).,Затем добавьте ресурс диалога с именем IDD_DIALOG1.Если не упомянуто здесь, другие параметры остаются по умолчанию.Так как окна / диалоги должны поддерживаться, переменная-член m_bWindowOnly должна быть назначена в конструкторе CAtlActiveXCtl.После этого добавьте обработчик сообщения для сообщения WM_CREATE, отображая диалоговые окна в функции OnCreate.Полный код AtlActiveXCtl.h прилагается ниже.

Я ссылался на другой вопрос Отображение диалогового окна режима с ActiveX в StackOverflow.Три всплывающих диалога проверяются в функции OnCreate ().

#pragma once
#include "resource.h"
#include <atlctl.h>
#include "AtlActiveX_i.h"

using namespace ATL;

// Modeless dialog
class CModelessDialog : public CDialogImpl<CModelessDialog>
{
public:
    enum { IDD = IDD_DIALOG1 };
    BEGIN_MSG_MAP(CModelessDialog)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
        MESSAGE_HANDLER(WM_CLOSE, OnClose)
    END_MSG_MAP()

    LRESULT OnInitDialog(UINT, WPARAM, LPARAM, BOOL &)
    {
        return 0;
    }

    LRESULT OnClose(UINT, WPARAM, LPARAM, BOOL &)
    {
        DestroyWindow();
        return 0;
    }
};

// CAtlActiveXCtl
class ATL_NO_VTABLE CAtlActiveXCtl :
    public CComObjectRootEx<CComSingleThreadModel>,
    public IDispatchImpl<IAtlActiveXCtl, &IID_IAtlActiveXCtl, &LIBID_AtlActiveXLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
    public IOleControlImpl<CAtlActiveXCtl>,
    public IOleObjectImpl<CAtlActiveXCtl>,
    public IOleInPlaceActiveObjectImpl<CAtlActiveXCtl>,
    public IViewObjectExImpl<CAtlActiveXCtl>,
    public IOleInPlaceObjectWindowlessImpl<CAtlActiveXCtl>,
    public ISupportErrorInfo,
    public IObjectWithSiteImpl<CAtlActiveXCtl>,
    public IQuickActivateImpl<CAtlActiveXCtl>,
    public IDataObjectImpl<CAtlActiveXCtl>,
    public IProvideClassInfo2Impl<&CLSID_AtlActiveXCtl, NULL, &LIBID_AtlActiveXLib>,
    public CComCoClass<CAtlActiveXCtl, &CLSID_AtlActiveXCtl>,
    public CComControl<CAtlActiveXCtl>
{
public:
    CAtlActiveXCtl()
    {
        m_bWindowOnly = 1;
    }

DECLARE_OLEMISC_STATUS(OLEMISC_RECOMPOSEONRESIZE |
    OLEMISC_CANTLINKINSIDE |
    OLEMISC_INSIDEOUT |
    OLEMISC_ACTIVATEWHENVISIBLE |
    OLEMISC_SETCLIENTSITEFIRST
)

DECLARE_REGISTRY_RESOURCEID(IDR_ATLACTIVEXCTL)

BEGIN_COM_MAP(CAtlActiveXCtl)
    COM_INTERFACE_ENTRY(IAtlActiveXCtl)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IViewObjectEx)
    COM_INTERFACE_ENTRY(IViewObject2)
    COM_INTERFACE_ENTRY(IViewObject)
    COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
    COM_INTERFACE_ENTRY(IOleInPlaceObject)
    COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
    COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
    COM_INTERFACE_ENTRY(IOleControl)
    COM_INTERFACE_ENTRY(IOleObject)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
    COM_INTERFACE_ENTRY(IQuickActivate)
    COM_INTERFACE_ENTRY(IDataObject)
    COM_INTERFACE_ENTRY(IProvideClassInfo)
    COM_INTERFACE_ENTRY(IProvideClassInfo2)
    COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()

BEGIN_PROP_MAP(CAtlActiveXCtl)
    PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
    PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
    // Example entries
    // PROP_ENTRY_TYPE("Property Name", dispid, clsid, vtType)
    // PROP_PAGE(CLSID_StockColorPage)
END_PROP_MAP()

BEGIN_MSG_MAP(CAtlActiveXCtl)
    CHAIN_MSG_MAP(CComControl<CAtlActiveXCtl>)
    DEFAULT_REFLECTION_HANDLER()
    MESSAGE_HANDLER(WM_CREATE, OnCreate)
END_MSG_MAP()
// Handler prototypes:
//  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);

// ISupportsErrorInfo
    STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid)
    {
        static const IID* const arr[] =
        {
            &IID_IAtlActiveXCtl,
        };

        for (int i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
        {
            if (InlineIsEqualGUID(*arr[i], riid))
                return S_OK;
        }
        return S_FALSE;
    }

// IViewObjectEx
    DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)

// IAtlActiveXCtl
public:
    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        IOleInPlaceFrame *pOleInPlaceFrame = NULL;
        IOleInPlaceUIWindow *pOleInPlaceUIwindow = NULL;
        IOleInPlaceSite *pOleInPlaceSite = NULL;

        OLEINPLACEFRAMEINFO oleInPlaceFrameInfo;
        oleInPlaceFrameInfo.cb = sizeof(oleInPlaceFrameInfo);
        HRESULT hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (LPVOID *)&pOleInPlaceSite);
        if (hr != S_OK)
            return S_OK;

        RECT rc1, rc2;
        hr = pOleInPlaceSite->GetWindowContext(&pOleInPlaceFrame, &pOleInPlaceUIwindow, &rc1, &rc2, &oleInPlaceFrameInfo);
        {
            HWND hWndTop = NULL;
            pOleInPlaceSite->GetWindow(&hWndTop);

            pOleInPlaceFrame->EnableModeless(TRUE);
            ::EnableWindow(hWndTop, FALSE);

            //[1] Message box, cannot switch tab page
            MessageBox(L"Hello, world!", L"MSG", MB_OK);

            //[2] Modal dialog, cannot switch tab page
            CSimpleDialog<IDD_DIALOG1> dlg;
            dlg.DoModal(hWndTop);

            //[3] Modeless dialog, can switch tab page, but always stays on top of IE browser
            CModelessDialog *pDlg = new CModelessDialog;
            pDlg->Create(hWndTop);
            pDlg->ShowWindow(SW_SHOWNORMAL);

            pOleInPlaceFrame->EnableModeless(FALSE);
            ::EnableWindow(hWndTop, TRUE);
        }

        return 0;
    }

    HRESULT OnDraw(ATL_DRAWINFO& di)
    {
        RECT& rc = *(RECT*)di.prcBounds;

        // Set Clip region to the rectangle specified by di.prcBounds
        HRGN hRgnOld = NULL;
        if (GetClipRgn(di.hdcDraw, hRgnOld) != 1)
            hRgnOld = NULL;

        bool bSelectOldRgn = false;
        HRGN hRgnNew = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
        if (hRgnNew != NULL)
            bSelectOldRgn = (SelectClipRgn(di.hdcDraw, hRgnNew) != ERROR);

        Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
        SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
        LPCTSTR pszText = _T("AtlActiveXCtl");
        TextOut(di.hdcDraw,
            (rc.left + rc.right) / 2,
            (rc.top + rc.bottom) / 2,
            pszText,
            lstrlen(pszText));

        if (bSelectOldRgn)
            SelectClipRgn(di.hdcDraw, hRgnOld);

        return S_OK;
    }

    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }
};

OBJECT_ENTRY_AUTO(__uuidof(AtlActiveXCtl), CAtlActiveXCtl)

Модальные и немодальные диалоги должны поддерживаться в элементах управления ActiveX на вкладках IE11, как и в простых приложениях с графическим интерфейсом Win32.Может кто-нибудь любезно помочь мне решить эту проблему?

...