发文章
发文工具
撰写
网文摘手
文档
视频
思维导图
随笔
相册
原创同步助手
其他工具
图片转文字
文件清理
AI助手
留言交流
0 Members and 2 Guests are viewing this topic.
An ActiveX Control is a high powered coclass, quite different from the previous COM objects built thus far, in that they typically offer a visual aspect…. As far as COM-based technologies go, the ActiveX Control is at the top of the mountain. An ActiveX control is a graphical building block, used in the context of another application.
AtlAxCreateControlLic Creates a licensed ActiveX control, initializes it, and hosts it in the specified window.ATLAPI AtlAxCreateControlLic( LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic = NULL);ParameterslpszName A pointer to a string to be passed to the control. Must be formatted in one of the following ways: * A ProgID such as "MSCAL.Calendar.7" * A CLSID such as "{8E27C92B-1264-101C-8A2F-040224009C02}" * A URL such as "http://www.microsoft.com" * A reference to an Active document such as "file://\\Documents\MyDoc.doc"hWnd Handle to the window that the control will be attached to.pStream A pointer to a stream that is used to initialize the properties of the control. Can be NULL.ppUnkContainer The address of a pointer that will receive the IUnknown of the container. Can be NULL.bstrLic The BSTR containing the license for the control.Return Value One of the standard HRESULT values.
#define UNICODE#define _UNICODE#include <windows.h>#include <ocidl.h>#include <stdio.h>const CLSID CLSID_MSFlexGrid = {0x6262D3A0,0x531B,0x11CF,{0x91,0xF6,0xC2,0x86,0x3C,0x38,0x5E,0x30}};const IID IID_IClassFactory2 = {0xB196B28F,0xBAB4,0x101A,{0xB6,0x9C,0x00,0xAA,0x00,0x34,0x1D,0x07}};HRESULT (__stdcall* ptrDllGetClassObject) (const CLSID&, const IID&, void**); // function pointer declarationint main(){ IClassFactory2* pClassFactory=NULL; BSTR strLicenseKey=NULL; HMODULE hDll=NULL; LICINFO LicInfo; HRESULT hr; hDll=LoadLibrary(L"C:\\Windows\\system32\\MSFlxGrd.ocx"); // <<< You may need to adjust this!!!!!!! if(hDll) { ptrDllGetClassObject=(HRESULT (__stdcall*)(REFCLSID, REFIID, void**))GetProcAddress(hDll, "DllGetClassObject"); hr=ptrDllGetClassObject(CLSID_MSFlexGrid, IID_IClassFactory2, (void**)&pClassFactory); if(SUCCEEDED(hr)) { hr=pClassFactory->GetLicInfo(&LicInfo); // This code tests to see if the wprintf(L"LicInfo.fRuntimeKeyAvail = %d\n",LicInfo.fRuntimeKeyAvail); // object is amenable to giving wprintf(L"LicInfo.fLicVerified = %d\n",LicInfo.fLicVerified); // us a license key. if(LicInfo.fRuntimeKeyAvail && LicInfo.fLicVerified) { hr=pClassFactory->RequestLicKey(NULL,&strLicenseKey); if(SUCCEEDED(hr)) { wprintf(L"strLicenseKey = %s\n",strLicenseKey); SysFreeString(strLicenseKey); } else wprintf(L"pClassFactory->RequestLicKey(NULL,&strLicenseKey) Failed!\n"); } pClassFactory->Release(); } else wprintf(L"ptrDllGetClassObject() Failed!\n"); FreeLibrary(hDll); } else wprintf(L"LoadLibrary() Failed On MSFlxGrd.ocx\n"); getchar(); return 0;}
……pAtlCreateControlLicensed=(PFNATLAXCREATECONTROLLIC)GetProcAddress(hIns,"AtlAxCreateControlLic");if(pAtlCreateControlLicensed){ strProgId=SysAllocString(_T("MSFlexGridLib.MSFlexGrid")); // strProgId is a BSTR strLicense = SysAllocString(L"72E67120-5959-11cf-91F6-C2863C385E30"); // strLicense is a BSTR hr=pAtlCreateControlLicensed(strProgId,hContainer,NULL,&ppUnkContainer,strLicense); if(SUCCEEDED(hr)){ …. ….
Main.cpp // Contains WinMain() start up code, Window Procedure, And Main Window Message HandlersGridEvents.cpp // Implementation of IDispatch based CEventSink and DMSFlexGridEvents (outgoing interface)Main.h // Some function pointer declarations I need and stuff to make my message crackers workGridEvents.h // Declaration of my CEventSink Class which implements abstract base class copied from Oleview output MSFlexGrid.h // C++ translation of idl code from Oleview. This is an interface/vtable maintained by MSFlexGrid server
// Main.cpp#define UNICODE //Main.cpp - MSFlexGrid (MSFlxGrd.ocx) Demo. Link ole32.lib, oleauto32.lib, uuid.lib#define _UNICODE#include <windows.h> // This code demonstrates how to use the MSFlexGrid ActiveX Control in a Win32 SDK#include <ocidl.h> // style application without any (or at best little) help from MFC or ATL. We will#include <tchar.h> // use a few ATL functions to provide an ActiveX Control Container for us, but#include <cstdio> // other than that, it will be plain Win32 with no fancy templates or macros.#include "GridEvents.h"#include "Main.h"#include "MSFlexGrid.h"const IID LIBID_MSFlexGrid = {0x5E9E78A0,0x531B,0x11CF,{0x91,0xF6,0xC2,0x86,0x3C,0x38,0x5E,0x30}};const IID IID_MSFlexGrid = {0x5F4DF280,0x531B,0x11CF,{0x91,0xF6,0xC2,0x86,0x3C,0x38,0x5E,0x30}};const IID IID_MSFlexGridEvents = {0x609602E0,0x531B,0x11CF,{0x91,0xF6,0xC2,0x86,0x3C,0x38,0x5E,0x30}};const IID IID_IConnectionPointContainer = {0xB196B284,0xBAB4,0x101A,{0xB6,0x9C,0x00,0xAA,0x00,0x34,0x1D,0x07}};HINSTANCE hAtlIns=NULL; //I hate globals; but we'll use one here! See below.struct StartOLEProcess // The reason this strange thing - 'StartOLEProcess' is here is that in testing this{ // thing with Windows 2000/XP I was getting crashes at program termination, i.e., 'x'ing StartOLEProcess() // out to end program, caused presumably by either CoUninitialize() or FreeLibrary() not { // synchronizing well with this process's termination code. So note here that an TCHAR szBuffer[256]; // instance of StartOLEProcess named 'InitializeOLE' will be created before WinMain() CoInitialize(NULL); // even starts, and its destructor will be called after WinMain() exits. I put the GetCurrentDirectory(256,szBuffer); // CoInitialize(), LoadLibrary(), CoUninitialize(), and FreeLibrary() calls in this _tcscat(szBuffer,_T("\\Atl90.dll")); // object's Constructor and Destructor calls, and that seemed to solve the problem. One hAtlIns=LoadLibrary(szBuffer); // does what one must, I suppose! } ~StartOLEProcess() { CoUninitialize(); FreeLibrary(hAtlIns); }}InitializeOLE;long fnWndProc_OnCreate(lpWndEventArgs Wea) // WNDCLASSEX::cbWndExtra Bytes{ // IConnectionPointContainer* pConnectionPointContainer=NULL; // Offset What In The World Is Stored There??? PFNATLAXCREATECONTROLLIC pAtlCreateControlLicensed=NULL; // ================================================================================ PFNATLAXGETCONTROL pAtlAxGetControl=NULL; // 0 - 3 ppUnkContainer - pointer to IUnknown of ActiveX Control Container IConnectionPoint* pConnectionPoint=NULL; // 4 - 7 pUnkGrid - pointer to IUnknown of ActiveX Control PFNATLAXWININIT pAtlAxWinInit=NULL; // 8 - 11 pIGrid - Pointer to MSFlexGrid Interface BSTR strProgId,strLicense,strText; // 12 - 15 pConnectionPoint - Pointer to MSFlexGrid Events Connection Point IUnknown* ppUnkContainer=NULL; // 16 - 19 dwCookie - Handle to established Connection Point CEventSink* pEventSink=NULL; IMSFlexGrid* pIGrid=NULL; IUnknown* pUnkGrid=NULL; // You can think of fnWndProc_OnCreate() as the Constructor Call for the whole appli- DWORD dwCookie=0; // cation. If any COM services are used, CoInitialize() is needed. We immediately get HWND hContainer; // our HINSTANCE from the lParam of the WM_CREATE message. Then we create a 'Container' HRESULT hr; // window. This helps with positioning the ActiveX Control where you want it as is // necessary with most child window controls. COM Objects posess an entity known as Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance; // their ProgId, i.e., 'Program ID'. The MSFlexGrid ActiveX Control's ProgId is hContainer=CreateWindowEx // MSFlexGridLib.MSFlexGrid. These names can be found in the Windows Registry under ( // HKEY_Classes_Root. The native string type for COM is the BSTR type. This type of WS_EX_OVERLAPPEDWINDOW, // string is quite unlike null terminated C strings. It is byte length prefixed, twice _T("static"), // null terminated, and can contain nulls. It is allocated with the OLE String Engine _T(""), // System String Functions. This whole topic (if you are unfamiliar with it) could take WS_CHILD|WS_VISIBLE, // you quite some time to learn. Since this application is a C++ SDK style Win32 project 10, // and is not associated in any way with MFC Visual Designers, Visual Basic Visual 10, // Designers, etc., a great deal of the internal functionality of the MSFlexGrid ActiveX 282, // Control is not going to be used. For you see, ActiveX Controls, particularly of the 250, // *.ocx variety, were designed to run 'In-Place Active' within a Visual Designer, where Wea->hWnd, // the programmer using the control in a project would see a visual representation of (HMENU)ID_CONTAINER, // the control at 'design time' as it is being 'embedded' within an OLE Controller Wea->hIns, // application such as Visual Basic. In that mode there would be 'resizing handles' 0 // visible which the visual developer could use to adjust the runtime size, as well as ); // other design time characteristics. Since advanced C++ developers such as ourselves if(hAtlIns) // (that is, Real Men) can dispense with such nonesense, in this app we will just use a { // few simple Active Template Library functions (AtlAxWinInit(), AtlAxCreateControl(), pAtlAxWinInit=(PFNATLAXWININIT)GetProcAddress // AtlAxGetControl()) to create a minimal ActiveX Control Container for us. The ( // functionality for this is contained in various versions of Atl.dll such as Atl.dll, hAtlIns, // Atl71.dll, Atl80.dll, Atl90.dll, etc. Note that what you are seeing just left are "AtlAxWinInit" // function pointer calls to access those ATL functions I just mentioned because of a ); // real ugly problem with creating licensed versions of ActiveX Controls. For you see, if(pAtlAxWinInit) // to create a licensed version of a control one needs to call AtlAxCreateControlLic(), { // and this function was added to the various versions of the Atl.dll and Atl.lib after hr=pAtlAxWinInit(); // the original versions came out with Visual C++ 6.0. And I wanted this code to work if(SUCCEEDED(hr)) // with VC6. And in any case, I couldn't link with Atl.lib even if that function was { // listed there, because I also wanted this code to work with MinGW, pAtlCreateControlLicensed=(PFNATLAXCREATECONTROLLIC)GetProcAddress // and Atl.dll and Atl.lib are not part of the MinGW compiler ( // collection set of includes and libs - Hense the need for explicit hAtlIns,"AtlAxCreateControlLic" // linking to some version of Atl.dll, which you will have to ); // obtain for yourself in some way if you want to use this code. I'd if(pAtlCreateControlLicensed) // recommend Atl71.dll, Atl80.dll, or Atl90.dll. At the top of Main.h { // you'll see the function declaration typedefs for function pointer strProgId=SysAllocString(_T("MSFlexGridLib.MSFlexGrid")); // calls on the Atl functions needed. Just left the strLicense=SysAllocString(L"72E67120-5959-11cf-91F6-C2863C385E30"); // AtlAxCreateControlLic() call returns a pointer to a pointer to the hr=pAtlCreateControlLicensed // IUnknown interface of the ActiveX Control Container within Atl.dll. ( // The next function - AtlAxGetControl(), returns a pointer to the strProgId,hContainer,NULL,&ppUnkContainer,strLicense // IUnknown interface of the ActiveX Control itself hosted by the ); // 'Container' and parented by our CreateWindowEx() static control if(SUCCEEDED(hr)) // just created above. Having successfully accomplished all this, our { // next step is to do a QueryInterface on the IUnknown of the grid for the SetWindowLong(Wea->hWnd,0,(long)ppUnkContainer); // IMSFlexGrid interface on the grid. The IMSFlexGrid interface can be found in pAtlAxGetControl=(PFNATLAXGETCONTROL)GetProcAddress // MSFlexGrid.h. This file I obtained by using OLEView.exe and opening up the ( // MSFlexGrid Type Library. Then I by hand converted the MIDL (Microsoft Interface hAtlIns,"AtlAxGetControl" // Definition Language) to a proper C++ header file. It took quite a few hours! ); // What I need to do is make a 'Type Library Browser' tool like PowerBASIC supplies if(pAtlAxGetControl) // with its compilers, or the Jose Roca PowerBAIC type lib browser, so one can auto- { // generate these headers for ActiveX/COM objects. I'll get to that shortly. But hr=pAtlAxGetControl(hContainer,&pUnkGrid); // back to the code! Once we get an IMSFlexGrid pointer we can call methods on the if(SUCCEEDED(hr)) // object to set properties such as number of rows, number of columns, etc. However, { // the critical step that must happen next is that our client app (this one) must SetWindowLong(Wea->hWnd,4,(long)pUnkGrid); // provide an 'event sink' to 'sink' events fired from the MSFlexGrid control. hr=pUnkGrid->QueryInterface // ActiveX Controls in particular and COM objects in general don't communicate with ( // their controller through a Window Procedure as with custom controls. Rather, IID_MSFlexGrid,(void**)&pIGrid // they call into an event sink after being notified by the controller of the ); // address of a suitable COM interface to which they'll fire events. The specifics if(SUCCEEDED(hr)) // of this are as follows: One creates an abstract base class and inherits from SetWindowLong(Wea->hWnd,8,(long)pIGrid); // this in a class of one's choosing within the client controller class. The else // method signatures in this abstract base class are obtained from the type library. return 0; // What came out of the type lib for this app was 'DMSFlexGridEvents'. See pIGrid->SetCols(4); // GridEvents.h. In this app I made a seperate header for this 'outgoing' interface. pIGrid->SetRows(20); // I'd recommend you open up OLEView.exe and go to File >> Open Typelib and view pIGrid->SetColWidth(0,200); // MSFlxGrd.ocx. Near the bottom you'll see this... pIGrid->SetColWidth(1,1200); pIGrid->SetColWidth(2,1200); // coclass MSFlexGrid pIGrid->SetColWidth(3,1200); // { strText=SysAllocString(L"Column 1"); // [default] interface IMSFlexGrid; pIGrid->SetCol(1), pIGrid->SetRow(0); // [default, source] dispinterface DMSFlexGridEvents; pIGrid->SetText(strText); // } SysReAllocString(&strText,L"Column 2"); // pIGrid->SetCol(2), pIGrid->SetText(strText); // What that means is that the COM Class MSFlexGrid contains two interfaces, 1) a SysReAllocString(&strText,L"Column 3"); // default 'incomming' interface of the typical kind, and 2) a 'dispatch' interface pIGrid->SetCol(3), pIGrid->SetText(strText); // that is a 'source' of events fired out from the server, i.e., an 'outgoing' interface. SysFreeString(strText); // To set up the connection and inform the server of the event sink one does a Query- pIGrid->Refresh(); // Interface call on the IMSFlexGrid interface for the IConnectionPointContainer interface. hr=pUnkGrid->QueryInterface // Obtaining that one then calls IConnectionPointContainer::FindConnectionPoint() Once ( // obtaining an IConnectionPoint* as the return from that call (the last parameter is IID_IConnectionPointContainer, // where its returned - actual function returns are always HRESULTs), one can then call (void**)&pConnectionPointContainer // IConnectionPoint::Advise() and pass through to the server (the grid) the address of ); // the client sink interface. Its a bit more roundabout than just indicated, but that's if(FAILED(hr)) // the gist of it. Yes, its complicated. Note in our code below left we used the C++ return 0; // new operator to instantiate the client sink class - CEventSink. In that class we... hr=pConnectionPointContainer->FindConnectionPoint // must implement the three members of IUnknown and the four members of IDispatch. ( // We optionally can implement within that class whatever of the DMSFlexGrid IID_MSFlexGridEvents,&pConnectionPoint // event methods that we wish to take action on. In this demo app I decided to ); // only implement code for the keypress event so that you could see that the if(SUCCEEDED(hr)) // events can be made to work. If the event interface wasn't a pure IDispatch { // interface but was rather an IUnknown or dual interface it would have been pConnectionPointContainer->Release(); // necessary to at least stub out all the other event methods. But with a pure pConnectionPointContainer=NULL; // dispinterface there is no vtable access beyond the three IUnknown and four SetWindowLong(Wea->hWnd,12,(long)pConnectionPoint); // IDispatch methods. One simply receives dispid (dispatch id) values in } // IDispatch::Invoke from the server, i.e., the grid, and one does with them else // whatever one wants. A few words about interfaces and VTables. The abstract return 0; // base class eventually resolves to an array of function pointers that are pEventSink=new CEventSink; // pointers to the objects methods. In the specific case of our event sink, pEventSink->StoreGridPointer(pIGrid); // after 'new' is called, pEventSink will point to the base allocation of hr=pConnectionPoint->Advise // CEventSink class. At that address is a pointer to the DMSFlexGridEvents ( // interface/vtable. In the 11th zero based pointer offset in that VTable is (IUnknown*)pEventSink, &dwCookie // the pointer to CEventSink::KeyPress(). Again, because the events are a part ); // of a pure dispinterface, I would not have been obligated to create the CEventClass if(SUCCEEDED(hr)) // like that. I could have just included the three IUnknown functions and the four SetWindowLong(Wea->hWnd,16,(long)dwCookie); // IDispatch functions in it. Then the actual event procedures could have been simple } // external functions not part of any class, but nonetheless called from IDispatch::Invoke(). } // To understand all this you probably need to get Dale Rogerson's 'Inside COM' or Guy } // and Henry Eddon's 'Inside DCOM'. Also, on my board at http://www. can SysFreeString(strProgId); // be found a good bit about interfaces, Vtbls, pointers and such. SysFreeString(strLicense); } } } } return 0;}long fnWndProc_OnDestroy(lpWndEventArgs Wea){ IConnectionPoint* pConnectionPoint=NULL; IUnknown* ppUnkContainer=NULL; IMSFlexGrid* pIGrid=NULL; IUnknown* pUnkGrid=NULL; DWORD dwCookie=0; pConnectionPoint=(IConnectionPoint*)GetWindowLong(Wea->hWnd,12); dwCookie=(DWORD)GetWindowLong(Wea->hWnd,16); if(pConnectionPoint) { pConnectionPoint->Unadvise(dwCookie); pConnectionPoint->Release(); } pIGrid=(IMSFlexGrid*)GetWindowLong(Wea->hWnd,8); if(pIGrid) pIGrid->Release(); pUnkGrid=(IUnknown*)GetWindowLong(Wea->hWnd,4); if(pUnkGrid) pUnkGrid->Release(); ppUnkContainer=(IUnknown*)GetWindowLong(Wea->hWnd,0); if(ppUnkContainer) ppUnkContainer->Release(); PostQuitMessage(0); return 0;}LRESULT CALLBACK fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam){ WndEventArgs Wea; for(unsigned int i=0; i<dim(EventHandler); i++) { if(EventHandler[i].iMsg==msg) { Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam; return (*EventHandler[i].fnPtr)(&Wea); } } return (DefWindowProc(hwnd, msg, wParam, lParam));}int WINAPI WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow){ TCHAR szClassName[]=_T("MSFlexGrid Demo"); WNDCLASSEX wc; MSG messages; HWND hWnd; wc.lpszClassName=szClassName; wc.lpfnWndProc=fnWndProc; wc.cbSize=sizeof (WNDCLASSEX); wc.style=CS_DBLCLKS; wc.hIcon=LoadIcon(NULL,IDI_APPLICATION); wc.hInstance=hIns; wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION); wc.hCursor=LoadCursor(NULL,IDC_ARROW); wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW; wc.cbWndExtra=20; wc.lpszMenuName=NULL; wc.cbClsExtra=0; RegisterClassEx(&wc); hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,75,75,320,305,HWND_DESKTOP,0,hIns,0); ShowWindow(hWnd,iShow); while(GetMessage(&messages,NULL,0,0)) { TranslateMessage(&messages); DispatchMessage(&messages); } return messages.wParam;}
//Main.h#define dim(x) (sizeof(x) / sizeof(x[0]))typedef HRESULT (__stdcall* PFNATLAXWININIT)(void);typedef HRESULT (__stdcall* PFNATLAXCREATECONTROLLIC)(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic);typedef HRESULT (__stdcall* PFNATLAXGETCONTROL)(HWND hContainer, IUnknown** ppIUnknown);typedef struct WindowsEventArguments{ HWND hWnd; WPARAM wParam; LPARAM lParam; HINSTANCE hIns;}WndEventArgs, *lpWndEventArgs;long fnWndProc_OnCreate (lpWndEventArgs Wea);long fnWndProc_OnDestroy (lpWndEventArgs Wea);struct EVENTHANDLER{ unsigned int iMsg; long (*fnPtr)(lpWndEventArgs);};const EVENTHANDLER EventHandler[]={ {WM_CREATE, fnWndProc_OnCreate}, {WM_DESTROY, fnWndProc_OnDestroy}};#define ID_CONTAINER 1500
//GridEvents.h#ifndef GridEvents_h#define GridEvents_h#include "MSFlexGrid.h"interface DMSFlexGridEvents : IDispatch { virtual void __stdcall Click()=0; virtual void __stdcall KeyDown(short* KeyCode, short Shift)=0; virtual void __stdcall DblClick()=0; virtual void __stdcall KeyPress(short* KeyAscii)=0; virtual void __stdcall KeyUp(short* KeyCode, short Shift)=0; virtual void __stdcall MouseDown(short Button, short Shift, int x, int y)=0; virtual void __stdcall MouseMove(short Button, short Shift, int x, int y)=0; virtual void __stdcall MouseUp(short Button, short Shift, int x, int y)=0; virtual void __stdcall SelChange()=0; virtual void __stdcall RowColChange()=0; virtual void __stdcall EnterCell()=0; virtual void __stdcall LeaveCell()=0; virtual void __stdcall Scroll()=0; virtual void __stdcall Compare(long Row1, long Row2, short* Cmp)=0; virtual void __stdcall OLEStartDrag(IDispatch** Data, long* AllowedEffects)=0; virtual void __stdcall OLEGiveFeedback(long* Effect, VARIANT_BOOL* DefaultCursors)=0; virtual void __stdcall OLESetData(IDispatch** Data, short* DataFormat)=0; virtual void __stdcall OLECompleteDrag(long* Effect)=0; virtual void __stdcall OLEDragOver(IDispatch** Data, long* Effect, short* Button, short* Shift, float* x, float* y, short* State)=0; virtual void __stdcall OLEDragDrop(IDispatch** Data, long* Effect, short* Button, short* Shift, float* x, float* y)=0;};class CEventSink : public DMSFlexGridEvents //CEventSink{ public: CEventSink(); virtual ~CEventSink(); HRESULT __stdcall QueryInterface(REFIID iid, void** ppv); ULONG __stdcall AddRef(); ULONG __stdcall Release(); HRESULT __stdcall GetTypeInfoCount(UINT* pCountTypeInfo); HRESULT __stdcall GetTypeInfo(UINT iTypeInfo, LCID lcid, ITypeInfo** ppITypeInfo); HRESULT __stdcall GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId); HRESULT __stdcall Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr); void __stdcall StoreGridPointer(IMSFlexGrid* pIGrid); void __stdcall Click(){} void __stdcall KeyDown(short* KeyCode, short Shift){} void __stdcall DblClick(){} void __stdcall KeyPress(short* KeyAscii); // 0xfffffda5 // << this one implemented!!! void __stdcall KeyUp(short* KeyCode, short Shift){} void __stdcall MouseDown(short Button, short Shift, int x, int y){} void __stdcall MouseMove(short Button, short Shift, int x, int y){} void __stdcall MouseUp(short Button, short Shift, int x, int y){} void __stdcall SelChange(){} void __stdcall RowColChange(){} void __stdcall EnterCell(){} void __stdcall LeaveCell(){} void __stdcall Scroll(){} void __stdcall Compare(long Row1, long Row2, short* Cmp){} void __stdcall OLEStartDrag(IDispatch** Data, long* AllowedEffects){} void __stdcall OLEGiveFeedback(long* Effect, VARIANT_BOOL* DefaultCursors){} void __stdcall OLESetData(IDispatch** Data, short* DataFormat){} void __stdcall OLECompleteDrag(long* Effect){} void __stdcall OLEDragOver(IDispatch** Data, long* Effect, short* Button, short* Shift, float* x, float* y, short* State){} void __stdcall OLEDragDrop(IDispatch** Data, long* Effect, short* Button, short* Shift, float* x, float* y){} private: long m_cRef; ITypeInfo* m_pTypeInfo; IMSFlexGrid* pGrid;};#endif
//GridEvents.cpp#define UNICODE#define _UNICODE#include <windows.h>#include <objbase.h>#include <ocidl.h>#include <tchar.h>#include <string>#include "Main.h"#include "GridEvents.h"#include "MSFlexGrid.h"extern "C" const IID LIBID_MSFlexGrid = {0x5E9E78A0,0x531B,0x11CF,{0x91,0xF6,0xC2,0x86,0x3C,0x38,0x5E,0x30}};extern "C" const IID IID_MSFlexGridEvents = {0x609602E0,0x531B,0x11CF,{0x91,0xF6,0xC2,0x86,0x3C,0x38,0x5E,0x30}};CEventSink::CEventSink() : m_cRef(0) //CEventSink Constructor{ ITypeLib* pTypeLib=NULL; HRESULT hr; this->m_pTypeInfo=NULL; hr=LoadRegTypeLib(LIBID_MSFlexGrid,1,0,LANG_NEUTRAL,&pTypeLib); if(SUCCEEDED(hr)) { hr = pTypeLib->GetTypeInfoOfGuid(IID_MSFlexGridEvents, &m_pTypeInfo); pTypeLib->Release(); }}CEventSink::~CEventSink(){ if(this->m_pTypeInfo) this->m_pTypeInfo->Release();}HRESULT CEventSink::QueryInterface(REFIID riid, void** ppv){ if(riid == IID_IUnknown) *ppv = (IUnknown*)this; else if(riid == IID_IDispatch) *ppv = (IDispatch*)this; else if(riid == IID_MSFlexGridEvents) *ppv = (DMSFlexGridEvents*)this; else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK;}ULONG CEventSink::AddRef(){ return ++m_cRef;}ULONG CEventSink::Release(){ if(--m_cRef != 0) return m_cRef; else delete this; return 0;}HRESULT CEventSink::GetTypeInfoCount(UINT* pCountTypeInfo){ *pCountTypeInfo = 1; return S_OK;}HRESULT CEventSink::GetTypeInfo(UINT iTypeInfo, LCID lcid, ITypeInfo** ppITypeInfo){ *ppITypeInfo = NULL; if(iTypeInfo != 0) return DISP_E_BADINDEX; m_pTypeInfo->AddRef(); *ppITypeInfo = m_pTypeInfo; return S_OK;}HRESULT CEventSink::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){ if(riid != IID_NULL) return DISP_E_UNKNOWNINTERFACE; return DispGetIDsOfNames(m_pTypeInfo, rgszNames, cNames, rgDispId);}HRESULT CEventSink::Invoke(DISPID dispId, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDParms, VARIANT* pVarResult, EXCEPINFO* pErInfo, UINT* pErr){ if(riid != IID_NULL) return DISP_E_UNKNOWNINTERFACE; else { switch(dispId) { case 0xfffffda5: // KeyPress { this->KeyPress(pDParms->rgvarg[0].piVal); break; } } } return S_OK;}void CEventSink::KeyPress(short* KeyAscii){ BSTR strCellText=SysAllocString(L""); this->pGrid->GetText(&strCellText); std::wstring strMyText=strCellText; strMyText+=*KeyAscii; SysReAllocString(&strCellText,strMyText.c_str()); this->pGrid->SetText(strCellText);}void CEventSink::StoreGridPointer(IMSFlexGrid* pIGrid){ this->pGrid=pIGrid;}
//MSFlexGrid.h// Generated .IDL file (by the OLE/COM Object Viewer) typelib filename: MSFLXGRD.OCX// Forward declare all types defined in this typelib#ifndef MSFlexGrid_h#define MSFlexGrid_hinterface IVBDataObject;interface IVBDataObjectFiles;interface IRowCursor;interface IMSFlexGrid;interface DMSFlexGridEvents;interface IVBDataObject : IDispatch{ virtual HRESULT __stdcall Clear(); virtual HRESULT __stdcall GetData(short sFormat, VARIANT* pvData);
来自: quasiceo > 《delphi》
0条评论
发表
请遵守用户 评论公约
Thunk 技术的一个改进
//这里写thunk代码的汇编语句....thunk_end: ;}}__asm{mov x1,offset thunk_begin; //取 Thunk代码段 的地址范围.mov x2,offset thunk_end;}addr1 = x1;addr2 = x2;}因此,在函数中thunk代码模板放在一...
浅论Java访问COM/ActiveX
浅论Java访问COM/ActiveX.其中很重要的原因就是,目前Java对Windows构件模型的支持力度不够,使得Java程序很难复用Windows平台下丰富的构件资源,例如日历、制表、Word等各种控件(COM/ActiveX)。C/C++...
SPEECH SDK中编程文档 - 骆驼空间站 - 博客园
不知道你能不能发一些基... --vivienne1183 5. re: SPEECH SDK中编程文档 请问博主,你有没有speech sdk中关于中文语音识别的相关资料,如果在有CB的语音识别的程序代码那就更感谢拉。简单地说就是&quo...
Exposing Windows Forms Controls as ActiveX co...
// Delete the ‘Control‘ key, but don‘t throw an exception if it does not exist k.DeleteSubKey ( "Control" , false ...
Mozilla ActiveX control
Mozilla ActiveX controlMozilla ActiveX Control Introduction Motivation.Exact DOM mapping between IE and Mozilla.This is a test application I have written in Visual Basic to test the Mozil...
Packaging ActiveX Controls
Expands the files found in the .cab file.Multiple .cab files with the .inf saved in a separate .cab file Multiple .cab files with the .inf and x86 binary bundled in a single .cab file A s...
com技术内幕
第一个参数const CLSID&待创建组件的CLSID,第二个参数DWORD dwClsContext是待创建组件的执行上下文,第三个参数COSERVERINFO*用于...
COM笔记_QueryInterface函数
由于所有的接口都是从IUnknown继承的,因此所有的接口都支持QueryInterface,所以组件的任何一个接口都可以被客户用来获取它所支持的其...
C 开发这一步必不可少:C 创建线程的方法
第三个参数表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。一般用0第3个参数:指定线程函数的地址,也就是线程调用...
微信扫码,在手机上查看选中内容