// AX.CPP #include #include #include #include #include "ax.h" #pragma warning (disable: 4311) #pragma warning (disable: 4312) #pragma warning (disable: 4244) #pragma warning (disable: 4800) // AXClientSite class // ------- Implement member functions AXClientSite :: AXClientSite() { refNum = 0; CalledCanInPlace = 0; InPlace = 0; } AXClientSite :: ~AXClientSite() { } // IUnknown methods STDMETHODIMP AXClientSite :: QueryInterface(REFIID iid,void**ppvObject) { *ppvObject = 0; if (iid == IID_IOleClientSite) *ppvObject = (IOleClientSite*)this; if (iid == IID_IUnknown) *ppvObject = this; if (iid == IID_IAdviseSink) *ppvObject = (IAdviseSink*)this; if (iid == IID_IDispatch) *ppvObject = (IDispatch*)this; if (ExternalPlace == false) { if (iid == IID_IOleInPlaceSite) *ppvObject = (IOleInPlaceSite*)this; if (iid == IID_IOleInPlaceFrame) *ppvObject = (IOleInPlaceFrame*)this; if (iid == IID_IOleInPlaceUIWindow) *ppvObject = (IOleInPlaceUIWindow*)this; } //* Log Call if (*ppvObject) { AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) AXClientSite :: AddRef() { refNum++; return refNum; } STDMETHODIMP_(ULONG) AXClientSite :: Release() { refNum--; return refNum; } // IOleClientSite methods STDMETHODIMP AXClientSite :: SaveObject() { return S_OK; } STDMETHODIMP AXClientSite :: GetMoniker(DWORD dwA,DWORD dwW,IMoniker**pm) { *pm = 0; return E_NOTIMPL; } STDMETHODIMP AXClientSite :: GetContainer(IOleContainer**pc) { *pc = 0; return E_FAIL; } STDMETHODIMP AXClientSite :: ShowObject() { return S_OK; } STDMETHODIMP AXClientSite :: OnShowWindow(BOOL f) { InvalidateRect(Window, 0, TRUE); InvalidateRect(Parent, 0, TRUE); return S_OK; } STDMETHODIMP AXClientSite :: RequestNewObjectLayout() { return S_OK; } STDMETHODIMP_(void) AXClientSite :: OnViewChange(DWORD dwAspect,LONG lIndex) { } STDMETHODIMP_(void) AXClientSite :: OnRename(IMoniker * pmk) { } STDMETHODIMP_(void) AXClientSite :: OnSave() { } STDMETHODIMP_(void) AXClientSite :: OnClose() { } // IOleInPlaceSite methods STDMETHODIMP AXClientSite :: GetWindow(HWND *p) { *p = Window; return S_OK; } STDMETHODIMP AXClientSite :: ContextSensitiveHelp(BOOL) { return E_NOTIMPL; } STDMETHODIMP AXClientSite :: CanInPlaceActivate() { if (InPlace) { CalledCanInPlace = true; return S_OK; } return S_FALSE; } STDMETHODIMP AXClientSite :: OnInPlaceActivate() { return S_OK; } STDMETHODIMP AXClientSite :: OnUIActivate() { return S_OK; } STDMETHODIMP AXClientSite :: GetWindowContext(IOleInPlaceFrame** ppFrame,IOleInPlaceUIWindow **ppDoc,LPRECT r1,LPRECT r2,LPOLEINPLACEFRAMEINFO o) { *ppFrame = (IOleInPlaceFrame*)this; AddRef(); *ppDoc = NULL; GetClientRect(Window,r1); GetClientRect(Window,r2); o->cb = sizeof(OLEINPLACEFRAMEINFO); o->fMDIApp = false; o->hwndFrame = Parent; o->haccel = 0; o->cAccelEntries = 0; return S_OK; } STDMETHODIMP AXClientSite :: Scroll(SIZE s) { return E_NOTIMPL; } STDMETHODIMP AXClientSite :: OnUIDeactivate(int) { return S_OK; } STDMETHODIMP AXClientSite :: OnInPlaceDeactivate() { return S_OK; } STDMETHODIMP AXClientSite :: DiscardUndoState() { return S_OK; } STDMETHODIMP AXClientSite :: DeactivateAndUndo() { return S_OK; } STDMETHODIMP AXClientSite :: OnPosRectChange(LPCRECT) { return S_OK; } // IOleInPlaceFrame methods STDMETHODIMP AXClientSite :: GetBorder(LPRECT l) { GetClientRect(Window,l); return S_OK; } STDMETHODIMP AXClientSite :: RequestBorderSpace(LPCBORDERWIDTHS b) { //return S_OK; return E_NOTIMPL; } STDMETHODIMP AXClientSite :: SetBorderSpace(LPCBORDERWIDTHS b) { return S_OK; } STDMETHODIMP AXClientSite :: SetActiveObject(IOleInPlaceActiveObject*pV,LPCOLESTR s) { ax->Pao = pV; return S_OK; } STDMETHODIMP AXClientSite :: SetStatusText(LPCOLESTR t) { return E_NOTIMPL; } STDMETHODIMP AXClientSite :: EnableModeless(BOOL f) { return E_NOTIMPL; } STDMETHODIMP AXClientSite :: TranslateAccelerator(LPMSG,WORD) { return E_NOTIMPL; } // IDispatch Methods HRESULT _stdcall AXClientSite :: GetTypeInfoCount( unsigned int * pctinfo) {return E_NOTIMPL;} HRESULT _stdcall AXClientSite :: GetTypeInfo( unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo) {return E_NOTIMPL;} HRESULT _stdcall AXClientSite :: GetIDsOfNames( REFIID riid, OLECHAR FAR* FAR*, unsigned int cNames, LCID lcid, DISPID FAR* ) {return E_NOTIMPL;} // Other Methods void AX :: Init(char* cls) { wchar_t x[1000] = {0}; MultiByteToWideChar(CP_ACP,0,cls,-1,x,1000); CLSIDFromString(x,&clsid); iid = (IID*)&IID_IOleObject; OleObject = 0; Storage = 0; View = 0; Data = 0; Unk = 0; Pao = 0; AdviseToken = 0; memset(DAdviseToken,0,sizeof(DAdviseToken)); Site.ax = this; } AX :: AX(char* cls) { Init(cls); } void AX :: Clean() { if (Site.InPlace == true) { Site.InPlace = false; IOleInPlaceObject* iib = 0; if (OleObject) OleObject->QueryInterface(IID_IOleInPlaceObject,(void**)&iib); if (iib) { iib->UIDeactivate(); iib->InPlaceDeactivate(); iib->Release(); } } if (AdviseToken && OleObject) { OleObject->Unadvise(AdviseToken); AdviseToken = 0; } if (Data) { for(int i = 0 ; i < 100 ; i++) if (DAdviseToken[i]) Data->DUnadvise(DAdviseToken[i]); memset(DAdviseToken,0,sizeof(DAdviseToken)); } if (Pao) Pao->Release(); if (Unk) Unk->Release(); if (Data) Data->Release(); if (View) View->Release(); if (Storage) Storage->Release(); if (OleObject) OleObject->Release(); Unk = 0; Data = 0; View = 0; Storage = 0; OleObject = 0; } AX :: ~AX() { Clean(); } CLSID AX :: GetCLSID() { return clsid; } HRESULT _stdcall AXClientSite :: InsertMenus(HMENU h,LPOLEMENUGROUPWIDTHS x) { /* AX * t = (AX*)ax; if (t->AddMenu) { x->width[0] = 0; x->width[2] = 0; x->width[4] = 0; //InsertMenu(h,0,MF_BYPOSITION | MF_POPUP,(int)Menu,"test"); return S_OK; } */ return E_NOTIMPL; } HRESULT _stdcall AXClientSite :: SetMenu(HMENU h,HOLEMENU hO,HWND hw) { AX * t = (AX*)ax; /* if (t->AddMenu) { if (!h && !hO) { //::SetMenu(Window,Menu); //DrawMenuBar(Window); ::SetMenu(Parent,Menu); DrawMenuBar(Parent); return S_OK; } //::SetMenu(Window,h); //DrawMenuBar(Window); //HMENU hm = GetMenu(Parent); //AppendMenu(hm,MF_POPUP | MF_MENUBREAK,(int)h,0); //::SetMenu(Parent,hm); ::SetMenu(Parent,h); DrawMenuBar(Parent); //hOleWindow = hw; //OleSetMenuDescriptor(hO,Window,hw,0,0); OleSetMenuDescriptor(hO,Parent,hw,0,0); return S_OK; } */ return E_NOTIMPL; } HRESULT _stdcall AXClientSite :: RemoveMenus(HMENU h) { AX * t = (AX*)ax; if (t->AddMenu) { if (!h) return S_OK; int c = GetMenuItemCount(h); for (int i = c ; i >= 0 ; i--) { HMENU hh = GetSubMenu(h,i); if (hh == Menu) RemoveMenu(h,i,MF_BYPOSITION); } if (h == Menu) DestroyMenu(h); //DrawMenuBar(Window); DrawMenuBar(Parent); return S_OK; } return E_NOTIMPL; } HRESULT _stdcall AXClientSite :: Invoke( DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR* pDispParams, VARIANT FAR* pVarResult, EXCEPINFO FAR* pExcepInfo, unsigned int FAR* puArgErr) { return E_NOTIMPL; } void _stdcall AXClientSite :: OnDataChange(FORMATETC *pFormatEtc,STGMEDIUM *pStgmed) { // Notify our app that a change is being requested return; } // Window Procedure for AX control LRESULT CALLBACK AXWndProc(HWND hh,UINT mm,WPARAM ww,LPARAM ll) { if (mm == WM_CREATE) { char tit[1000] = {0}; HRESULT hr; GetWindowTextA(hh,tit,1000); AX* ax; ax = new AX(tit); SetWindowLong(hh,GWL_USERDATA,(LONG)ax); ax->Site.Window = hh; ax->Site.Parent = GetParent(hh); hr = StgCreateDocfile(0,STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DIRECT | STGM_CREATE,0,&ax->Storage); ax->Site.Window = hh; REFIID rid = *ax->iid; hr = OleCreate(ax->GetCLSID(),rid,OLERENDER_DRAW,0,&ax->Site,ax->Storage,(void**)&ax->OleObject); if (!ax->OleObject) { delete ax; SetWindowLong(hh,GWL_USERDATA,0); return -1; } hr = OleSetContainedObject(ax->OleObject, TRUE); hr = ax->OleObject->Advise(&ax->Site,&ax->AdviseToken); hr = ax->OleObject->QueryInterface(IID_IViewObject,(void**)&ax->View); hr = ax->OleObject->QueryInterface(IID_IDataObject,(void**)&ax->Data); if (ax->View) hr = ax->View->SetAdvise(DVASPECT_CONTENT,0,&ax->Site); return 0; } if (mm == WM_DESTROY) { AX* ax = (AX*)GetWindowLong(hh,GWL_USERDATA); if (!ax) return 0; ax->Clean(); return true; } if (mm == AX_SETDATAADVISE) { AX* ax = (AX*)GetWindowLong(hh,GWL_USERDATA); if (!ax) return 0; // 1.Enum available FORMATETC structures // 2.Set Data Advise specified to index ww if (!ax->Data) return 0; IEnumFORMATETC* ief = 0; int i = 0; FORMATETC fe; ax->Data->EnumFormatEtc((LPARAM)ll,&ief); if (!ief) return 0; for(;;) { HRESULT hr = ief->Next(1,&fe,0); if (hr != S_OK) break; if (ww == i) break; i++; } ief->Release(); if (ww == -1) return i; if (ax->Data) ax->Data->DAdvise(&fe,0,&ax->Site,&ax->DAdviseToken[ww]); return true; } if (mm == AX_GETAXINTERFACE) { AX* ax = (AX*)GetWindowLong(hh,GWL_USERDATA); return (LONG)ax; } if (mm == AX_QUERYINTERFACE) { char* p = (char*)ww; AX* ax = (AX*)GetWindowLong(hh,GWL_USERDATA); if (!ax) return 0; return ax->OleObject->QueryInterface((REFIID)*p,(void**)ll); } if (mm == WM_LBUTTONDBLCLK) { PostMessage(hh,AX_INPLACE,1,0); return 0; } if (mm == AX_INPLACE) { AX* ax = (AX*)GetWindowLong(hh,GWL_USERDATA); if (!ax) return 0; if (!ax->OleObject) return 0; RECT rect; HRESULT hr; ::GetClientRect(hh,&rect); if (ax->Site.InPlace == false && ww == 1) // Activate In Place { ax->Site.InPlace = true; ax->Site.ExternalPlace = ll; hr = ax->OleObject->DoVerb(OLEIVERB_INPLACEACTIVATE,0,&ax->Site,0,hh,&rect); InvalidateRect(hh,0,true); return 1; } if (ax->Site.InPlace == true && ww == 0) // Deactivate { ax->Site.InPlace = false; IOleInPlaceObject* iib; ax->OleObject->QueryInterface(IID_IOleInPlaceObject,(void**)&iib); if (iib) { iib->UIDeactivate(); iib->InPlaceDeactivate(); iib->Release(); InvalidateRect(hh,0,true); return 1; } } return 0; } if (mm == WM_SIZE) { AX* ax = (AX*)GetWindowLong(hh,GWL_USERDATA); if (!ax) return 0; if (!ax->OleObject) return 0; DefWindowProc(hh,mm,ww,ll); if (ax->Site.InPlace == true) { SendMessage(hh,AX_INPLACE,0,0); InvalidateRect(hh,0,true); SendMessage(hh,AX_INPLACE,1,0); } IOleInPlaceObject* pl; ax->OleObject->QueryInterface(IID_IOleInPlaceObject,(void**)&pl); if (!pl) return 0; RECT r; GetClientRect(ax->Site.Window,&r); pl->SetObjectRects(&r,&r); pl->Release(); return 0; } return DefWindowProc(hh,mm,ww,ll); } // Registration function ATOM AXRegister() { WNDCLASSEXA wC = {0}; wC.cbSize = sizeof(wC); wC.style = CS_GLOBALCLASS | CS_DBLCLKS; wC.lpfnWndProc = AXWndProc; wC.cbWndExtra = 4; wC.hInstance = GetModuleHandle(0); wC.lpszClassName = "AX"; return RegisterClassExA(&wC); }